{"id":"0e7c0d73-05d9-4b0f-a2bd-d46a2e799195","entityType":"agent","slug":"clawhub-poxenstudio-mybooks","name":"MyBooks","canonicalUrl":"https://www.xpersona.co/agent/clawhub-poxenstudio-mybooks","canonicalPath":"/agent/clawhub-poxenstudio-mybooks","generatedAt":"2026-10-10T21:48:56.750Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T15:39:51.485Z","emptyReason":null},"description":"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取 Skill: MyBooks Owner: poxenstudio Summary: MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取 Tags: latest:1.0.7 Version history: v1.0.7 | 2026-09-28T04:09:53.903Z | user","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.4K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s173jhrdgj35f8pz7vay4vakah83g5q1:mybooks","sourceUrl":"https://clawhub.ai/poxenstudio/mybooks","homepage":"https://clawhub.ai/poxenstudio/skills/mybooks","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/poxenstudio/mybooks","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/poxenstudio/skills/mybooks","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":63,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T15:39:51.485Z","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-10T15:39:51.485Z","emptyReason":null},"stars":null,"forks":null,"downloads":1356,"packageName":null,"latestVersion":"1.0.7","tractionLabel":"1.4K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T15:39:51.485Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T15:39:51.485Z","lastCrawledAt":"2026-10-10T15:39:51.485Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T15:39:51.485Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.7","createdAt":"2026-09-28T04:09:53.903Z","changelog":"- Removed the file skill-card.md, which previously provided a skill summary. - No change to skill features or behavior; this is a documentation cleanup.","fileCount":5,"zipByteSize":34536},{"version":"1.0.6","createdAt":"2026-09-21T03:46:51.007Z","changelog":"- Added detailed permission and network policy declarations to SKILL.md for transparency about local file and network access. - Clarified authentication flow and credential handling, including security of user credentials and strict host restrictions. - Documented HTTPS enforcement—plain HTTP is limited to localhost or LAN unless explicitly overridden; public addresses must use HTTPS. - Updated filesystem and network permissions: skill now explicitly lists when and how local file read/write are performed. - Removed file: skill-card.md.","fileCount":5,"zipByteSize":31758},{"version":"1.0.5","createdAt":"2026-09-21T03:00:37.571Z","changelog":"- Removed the skill-card.md file. - SKILL.md description and feature list updated: now mentions new features for reading time management by date, and booklist management (create/browse/add/remove/like books), available since v4.3.0+. - No changes to API structure, authentication, or examples. - No impact on existing functionality; documentation now covers more features.","fileCount":5,"zipByteSize":29398},{"version":"1.0.4","createdAt":"2026-08-27T13:19:21.924Z","changelog":"- Updated the description to mention support for querying and manually updating per-format reading time and progress for specific books.","fileCount":5,"zipByteSize":25936},{"version":"1.0.3","createdAt":"2026-08-21T13:40:58.400Z","changelog":"- 支持图书批注导出","fileCount":5,"zipByteSize":24093},{"version":"1.0.2","createdAt":"2026-08-12T06:39:06.543Z","changelog":"- Added support for importing annotations from third-party reading apps (such as WeChat Reading), with dedicated tool. - Expanded skill description to include annotation import and MiMo TTS audiobook features (TTS API configuration, EPUB to audiobook, conversion progress, voice cloning, and prompt management). - Described new and updated error codes related to TTS/audiobooks and voice cloning. - Added mention of `MYBOOKS_SSL_VERIFY` environment variable for servers using self-signed certificates. - Updated and extended usage notes and tool documentation accordingly.","fileCount":5,"zipByteSize":22155},{"version":"1.0.1","createdAt":"2026-06-28T01:07:04.422Z","changelog":"mybooks v1.0.1 - Updated documentation in SKILL.md: added the new `save_meta_to_file` tool for writing updated metadata back to ebook files. - Enhanced `get_book` and `edit_book` tools to support additional fields (such as `series_index` and structured `files` array). - Removed deprecated or redundant files (skill-card.md). - Various clarifications and detail improvements throughout help/documentation.","fileCount":5,"zipByteSize":13163},{"version":"1.0.0","createdAt":"2026-06-01T00:47:36.076Z","changelog":"mybooks 1.0.0 — Initial Release - Provides integration with MyBooks (PoxenStudio/Talebook), a personal book management system. - Supports searching, viewing, editing, and auto-filling metadata for books in your library. - Allows sending books to email or reading devices and managing reading states. - Enables viewing library statistics, categories, user info, and detailed book data. - Requires configuration of MYBOOKS_HOST, MYBOOKS_USER, and MYBOOKS_PASSWORD environment variables for secure access.","fileCount":5,"zipByteSize":12449}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173jhrdgj35f8pz7vay4vakah83g5q1:mybooks","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"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-poxenstudio-mybooks/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/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-10T21:48:56.746Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-poxenstudio-mybooks/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":"high","updatedAt":"2026-10-10T15:39:51.485Z","emptyReason":null},"readme":"Skill: MyBooks\n\nOwner: poxenstudio\n\nSummary: MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取\n\nTags: latest:1.0.7\n\nVersion history:\n\nv1.0.7 | 2026-09-28T04:09:53.903Z | user\n\n- Removed the file skill-card.md, which previously provided a skill summary.\n- No change to skill features or behavior; this is a documentation cleanup.\n\nv1.0.6 | 2026-09-21T03:46:51.007Z | user\n\n- Added detailed permission and network policy declarations to SKILL.md for transparency about local file and network access.\n- Clarified authentication flow and credential handling, including security of user credentials and strict host restrictions.\n- Documented HTTPS enforcement—plain HTTP is limited to localhost or LAN unless explicitly overridden; public addresses must use HTTPS.\n- Updated filesystem and network permissions: skill now explicitly lists when and how local file read/write are performed.\n- Removed file: skill-card.md.\n\nv1.0.5 | 2026-09-21T03:00:37.571Z | user\n\n- Removed the skill-card.md file.\n- SKILL.md description and feature list updated: now mentions new features for reading time management by date, and booklist management (create/browse/add/remove/like books), available since v4.3.0+.\n- No changes to API structure, authentication, or examples.\n- No impact on existing functionality; documentation now covers more features.\n\nv1.0.4 | 2026-08-27T13:19:21.924Z | user\n\n- Updated the description to mention support for querying and manually updating per-format reading time and progress for specific books.\n\nv1.0.3 | 2026-08-21T13:40:58.400Z | user\n\n- 支持图书批注导出\n\nv1.0.2 | 2026-08-12T06:39:06.543Z | user\n\n- Added support for importing annotations from third-party reading apps (such as WeChat Reading), with dedicated tool.\n- Expanded skill description to include annotation import and MiMo TTS audiobook features (TTS API configuration, EPUB to audiobook, conversion progress, voice cloning, and prompt management).\n- Described new and updated error codes related to TTS/audiobooks and voice cloning.\n- Added mention of `MYBOOKS_SSL_VERIFY` environment variable for servers using self-signed certificates.\n- Updated and extended usage notes and tool documentation accordingly.\n\nv1.0.1 | 2026-06-28T01:07:04.422Z | auto\n\nmybooks v1.0.1\n\n- Updated documentation in SKILL.md: added the new `save_meta_to_file` tool for writing updated metadata back to ebook files.\n- Enhanced `get_book` and `edit_book` tools to support additional fields (such as `series_index` and structured `files` array).\n- Removed deprecated or redundant files (skill-card.md).\n- Various clarifications and detail improvements throughout help/documentation.\n\nv1.0.0 | 2026-06-01T00:47:36.076Z | auto\n\nmybooks 1.0.0 — Initial Release\n\n- Provides integration with MyBooks (PoxenStudio/Talebook), a personal book management system.\n- Supports searching, viewing, editing, and auto-filling metadata for books in your library.\n- Allows sending books to email or reading devices and managing reading states.\n- Enables viewing library statistics, categories, user info, and detailed book data.\n- Requires configuration of MYBOOKS_HOST, MYBOOKS_USER, and MYBOOKS_PASSWORD environment variables for secure access.\n\nArchive index:\n\nArchive v1.0.7: 5 files, 34536 bytes\n\nFiles: scripts/mybooks_api.py (54156b), skill-card.md (2030b), skill.json (46b), SKILL.md (65818b), _meta.json (126b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: mybooks\nhomepage: https://www.mybooks.top\nallowed-tools: Bash(python3:*)\nmetadata: {\"clawdbot\":{},\"openclaw\":{\"requires\":{\"bins\":[\"python3\"],\"env\":[\"MYBOOKS_HOST\",\"MYBOOKS_USER\",\"MYBOOKS_PASSWORD\"]},\"permissions\":{\"network\":{\"required\":true,\"scope\":\"user-configured MYBOOKS_HOST only\",\"protocols\":[\"http\",\"https\"]},\"filesystem\":{\"read\":\"only when uploading: ebook files (book_upload) and mp3/wav samples (tts_clone_upload) at paths the user gives\",\"write\":\"only tts_clone_audio save_to (.wav, never overwrites)\"}}}}\ndescription: \"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取原始数据）,以及MiMo TTS有声书功能（配置TTS API、EPUB转有声书、查询转换进度、克隆音色与语音提示词管理，需管理员权限）等\"\n---\n\n# MyBooks\n\n## Requirements\n```bash\n# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n# 明文 http 仅允许回环/内网地址（如 192.168.x.x）；公网地址必须用 https\n# 确需对非内网地址使用明文 http 时：export MYBOOKS_ALLOW_INSECURE_HTTP=\"true\"\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'\n```\n\n> **安全提示**：请勿将凭据写入共享或全局配置文件（如 `~/.openclaw/.env`），以避免凭据被其他 agent 或进程意外读取。建议通过会话级环境变量或专用密钥管理工具传入凭据。\n\n## 权限与网络声明\n\n- **网络访问（必需）**：本 skill 是 MyBooks 服务器的 REST 客户端，所有工具都通过 HTTP(S) 访问**且仅访问**用户自己配置的 `MYBOOKS_HOST`，不连接任何其他地址，无遥测、无第三方回传。\n- **会修改数据的工具**：`edit_book`、`set_folder`、`rename_folder`、`push_notes`(`dry_run:false`)、`clear_imported_notes`、`book_fill`、`save_meta_to_file`、`book_upload`、`book_add_by_isbn`、`wants`/`favorite`/`reading`/`read_done`、`set_reading_time`、`delete_reading_time`、书单的创建/修改/删除/增删书/点赞、以及全部 `tts_*` 写操作。删除类工具（`delete_booklist`、`delete_reading_time`）脚本内强制 `confirm:true` 两步确认。\n- **本地文件读取**：仅 `book_upload`（限电子书扩展名 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx）和 `tts_clone_upload`（限 mp3/wav，≤7MB）会读取用户明确给出路径的文件并上传到 `MYBOOKS_HOST`；agent **不得**自行挑选文件上传。\n- **本地文件写入**：仅 `tts_clone_audio` 的 `save_to`（必须 `.wav` 结尾，且不覆盖已存在文件）。\n- **凭据**：见下方\"认证方式\"。\n\n## 通用响应格式与认证方式\n\n### 通用 JSON 响应结构\n所有 API 均返回如下格式：\n```json\n{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}\n```\n\n常见错误码：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"ok\"` | 操作成功 |\n| `\"user.need_login\"` | 未登录或登录态已过期 |\n| `\"permission\"` | 无权限执行该操作 |\n| `\"params.invalid\"` | 请求参数错误 |\n| `\"params.book.invalid\"` | 书籍不存在或 ID 错误 |\n| `\"task.running\"` | 后台任务正在进行中，稍后重试 |\n| `\"tts.converting\"` | TTS 转换任务正在运行 |\n| `\"tts.no_config\"` | 未配置 TTS API |\n| `\"clone.exists\"` | 克隆音色名称已存在 |\n| `\"clone.not_found\"` | 克隆音色不存在 |\n| `\"clone.too_large\"` | 文件超过 7MB 限制 |\n| `\"clone.invalid_format\"` | 仅支持 MP3/WAV 格式 |\n| `\"prompt.exists\"` | 提示词名称已存在 |\n| `\"prompt.not_found\"` | 提示词不存在 |\n\n### 认证方式\n- 脚本通过 `MYBOOKS_USER` / `MYBOOKS_PASSWORD` 环境变量自动调用 `/api/user/sign_in` 完成登录\n- 服务端通过 **Secure Cookie**（`user_id` + `lt`）维持会话\n- 若响应中出现 `err=user.need_login`，脚本会自动重新登录后重试一次；仍失败则报错退出\n- **凭据去向说明**：`MYBOOKS_USER` / `MYBOOKS_PASSWORD` **只会**以表单形式 POST 到用户自己配置的 `MYBOOKS_HOST` 的 `/api/user/sign_in`，不会发往任何其他地址；登录请求不跟随重定向；`MYBOOKS_HOST` 必须是 `http(s)://host[:port]` 且不含内嵌账号密码，对非内网地址要求 https\n- **必须**在调用前配置 `MYBOOKS_HOST`、`MYBOOKS_USER`、`MYBOOKS_PASSWORD` 三个环境变量，否则脚本直接报错退出\n\n---\n\n## 工具列表\n\n### `get_user_info` — 用户信息与系统统计\n\n**使用场景**：获取当前登录用户信息，同时返回书库总体统计（书籍数、作者数等）\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_user_info '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"user\": { \"is_login\": true, \"nickname\": \"管理员\", \"is_admin\": true },\n  \"sys\": { \"books\": 1280, \"authors\": 342, \"tags\": 86, \"mtime\": \"2025-03-01\" }\n}\n```\n\n---\n\n### `library_stats` — 书库统计\n\n**使用场景**：获取书库详细统计，包括电子书/实体书数量及本月新增\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py library_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_books\": 1280,\n    \"ebook_count\": 1210,\n    \"physical_count\": 70,\n    \"month_ebook_count\": 12,\n    \"month_physical_count\": 3,\n    \"current_year\": 2025,\n    \"current_month\": 3\n  }\n}\n```\n\n---\n\n### `reading_stats` — 阅读统计\n\n**使用场景**：获取当前用户的阅读统计（在读/已读数量、本月数据）及当前在读书单\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py reading_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_reading\": 5,\n    \"total_read_done\": 42,\n    \"month_reading\": 2,\n    \"month_read_done\": 3\n  },\n  \"current_reading_books\": [ /* 书籍对象列表 */ ],\n  \"month_read_done_books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_books` — 搜索书籍\n\n**使用场景**：\n- 关键词模糊搜索（书名/作者/简介），支持简繁体自动转换：\"有没有余华的书？\" / \"找一下《三体》\"\n- 按字段精确定位：只查书名、只查作者、按 ISBN 查找：\"ISBN 9787536692930 是哪本书？\"\n- 组合条件搜索：多个字段参数同时给出时按 **AND** 组合：\"余华在作家出版社出的书\"\n- Calibre 条件表达式：`name` 中写入 `字段:值` 形式的表达式，支持 `AND`/`OR`/`NOT` 与括号：\"评分 4 星以上的科幻小说\"\n\n**参数**（`name`/`title`/`author`/`isbn`/`publisher`/`series`/`tag` 至少提供一个）：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `name` | string | ❌ | — | 关键词、纯 ISBN 号或 Calibre 条件表达式（见下方说明） |\n| `title` | string | ❌ | — | 书名，**精确匹配** |\n| `author` | string | ❌ | — | 作者，包含匹配 |\n| `isbn` | string | ❌ | — | ISBN-10 / ISBN-13，可带 `-` |\n| `publisher` | string | ❌ | — | 出版社，包含匹配 |\n| `series` | string | ❌ | — | 丛书，包含匹配 |\n| `tag` | string | ❌ | — | 标签，包含匹配 |\n| `exact` | bool | ❌ | false | 为 true 时 `author`/`publisher`/`series`/`tag` 改为精确匹配 |\n| `order` | string | ❌ | — | 排序字段，如 `pubdate`、`rating`、`timestamp` |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**`name` 的三种解析方式**（后台自动识别）：\n1. **纯 ISBN**（10/13 位数字，可含 `-`）→ 按 ISBN 精确查找。\n2. **Calibre 条件表达式**（包含 `字段:` 形式，字段为 Calibre 内置搜索字段或 `#` 开头的自定义列）→ 原样交给 Calibre 搜索（同时追加简繁体转换版本以 OR 合并）。\n3. 其它 → 普通关键字，在书名/作者/简介等所有字段中模糊搜索。\n\n**Calibre 表达式速查**：\n\n| 写法 | 含义 |\n|------|------|\n| `title:三体` | 书名包含\"三体\" |\n| `title:=三体` | 书名**等于**\"三体\" |\n| `title:\"=三体 死神永生\"` | 值含空格时用双引号包住 |\n| `authors:=余华` | 作者精确为\"余华\" |\n| `tags:科幻 AND rating:>=4` | 标签含\"科幻\"且评分 ≥ 4 星 |\n| `publisher:作家 OR publisher:人民文学` | 任一出版社 |\n| `authors:刘慈欣 AND NOT tags:短篇` | 排除条件 |\n| `pubdate:>=2020` / `pubdate:<2000-01-01` | 出版日期范围 |\n| `formats:epub` | 有 EPUB 格式 |\n| `isbn:9787536692930` | 按 ISBN |\n| `#category:=\"小说\"` | 自定义列（分类） |\n| `title:~^三体` | 正则匹配 |\n\n常用字段：`title` `authors` `tags` `publisher` `series` `isbn` `identifiers` `comments` `rating` `pubdate` `timestamp` `formats` `languages` `id`，以及 `#` 开头的自定义列。\n\n**执行脚本**：\n```bash\n# 关键词\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"name\":\"三体\"}'\n# 按 ISBN\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"isbn\":\"978-7-5366-9293-0\"}'\n# 组合条件：余华 + 作家出版社\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"author\":\"余华\",\"publisher\":\"作家出版社\"}'\n# 书名精确匹配\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"title\":\"活着\"}'\n# Calibre 表达式\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"name\":\"tags:科幻 AND rating:>=4\",\"order\":\"rating\"}'\n```\n\n**选择建议**：用户只给出模糊描述时用 `name` 关键词；明确说出\"作者是…/出版社是…/ISBN…\"时用对应字段参数；需要评分、日期、格式、排除等条件时用 Calibre 表达式。字段参数与 `name` 可同时使用，彼此为 AND 关系。\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"title\": \"搜索作者:余华 出版社:作家出版社\",\n  \"total\": 3,\n  \"books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_by_category` — 按分类查询书籍\n\n**使用场景**：查询指定分类下的所有书籍（基于自定义 `#category` 字段）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `category` | string | ✅ | — | 分类名称，如 \"科幻\" |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_by_category '{\"category\":\"科幻\"}'\n```\n\n---\n\n### `list_folders` — 查看目录树\n\n**使用场景**：查看书库的\"目录\"（层级有上限，当前为两级，如 `文学.小说`）及各目录书籍数量；未设置目录的书在根目录 `/`\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_folders '{}'\n```\n\n**响应示例**（`count` 含子目录，`root_count` 为未设置目录的书）：\n```json\n{\n  \"err\": \"ok\",\n  \"folders\": [\n    { \"name\": \"文学\", \"count\": 12, \"children\": [{ \"name\": \"小说\", \"count\": 8 }] }\n  ],\n  \"root_count\": 5,\n  \"max_depth\": 2\n}\n```\n\n---\n\n### `search_by_folder` — 按目录查询书籍\n\n**使用场景**：查看某个目录下**直属**的书（不含子目录的书）；`path` 为空表示根目录\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `path` | string | ❌ | `\"\"` | 目录路径，用 `.` 连接，如 `\"文学\"`、`\"文学.小说\"` |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_by_folder '{\"path\":\"文学.小说\"}'\n```\n\n---\n\n### `set_folder` — 设置书籍目录\n\n**使用场景**：把一本或多本书放进某个目录。单本需管理员或书籍所有者；批量（`book_ids`）仅管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | 二选一 | 单本书 ID |\n| `book_ids` | array | 二选一 | 批量书籍 ID 列表 |\n| `folder` | string | ✅ | 目录路径，层级数以 `list_folders` 返回的 `max_depth` 为准（当前为 2），每级 1–24 字符、不含标点，如 `\"文学.小说\"`；传 `\"\"`/`\"清除\"`/`\"clear\"` 移出目录 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py set_folder '{\"book_id\":42,\"folder\":\"文学.小说\"}'\n```\n\n---\n\n### `rename_folder` — 重命名目录\n\n**使用场景**：修改目录的最后一段名称（仅管理员），子目录随之改名，如 `文学` → `读物` 后 `文学.小说` 变为 `读物.小说`\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `path` | string | ✅ | 现有目录路径 |\n| `name` | string | ✅ | 新的末段名称（1–24 字符、不含标点和 `.`） |\n| `merge` | bool | ❌ | 默认 `false`。目标目录已存在时服务端返回 `folder.exists`（附 `count`、`target`）且**不修改任何数据**；合并**不可撤回**，必须先向用户说明并获得确认，再带 `\"merge\":true` 重发 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py rename_folder '{\"path\":\"文学.小说\",\"name\":\"故事\"}'\n```\n\n---\n\n### `get_book` — 书籍详情\n\n**使用场景**：获取指定书籍的完整信息，包括元数据、可用格式、封面、阅读状态等\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book\": {\n    \"id\": 42,\n    \"title\": \"活着\",\n    \"authors\": [\"余华\"],\n    \"tags\": [\"小说\", \"中国文学\"],\n    \"publisher\": \"作家出版社\",\n    \"isbn\": \"9787506365437\",\n    \"pubdate\": \"2012-08-01\",\n    \"rating\": 9,\n    \"comments\": \"《活着》讲述了...\",\n    \"category\": \"现代文学\",\n    \"available_formats\": [\"epub\", \"pdf\"],\n    \"files\": [\n      {\n        \"format\": \"EPUB\",\n        \"size\": 1330899,\n        \"href\": \"/api/book/42.EPUB\"\n      }\n    ],\n    \"cover_url\": \"/get/cover/42\",\n    \"series\": \"余华作品集\",\n    \"series_index\": 1,\n    \"state\": {\n      \"favorite\": 0,\n      \"wants\": 0,\n      \"read_state\": 1\n    },\n    \"tags\": [\"小说\", \"中国文学\"]\n  },\n  \"kindle_sender\": \"sender@example.com\"\n}\n```\n\n---\n\n### `edit_book` — 编辑书籍元数据\n\n**使用场景**：\n- 手动修改书名、作者、标签、分类等字段\n- 修改实体书数量或类型\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `title` | string | ❌ | 书名 |\n| `authors` | array | ❌ | 作者列表，如 `[\"余华\"]` |\n| `tags` | array | ❌ | 标签列表，**替换**原有标签（想追加需先 `get_book` 获取现有标签再合并） |\n| `publisher` | string | ❌ | 出版社 |\n| `isbn` | string | ❌ | ISBN 编号 |\n| `series` | string | ❌ | 系列/丛书名 |\n| `series_index` | int | ❌ | 系列中的顺序号 |\n| `rating` | number | ❌ | 评分（0–10） |\n| `languages` | array | ❌ | 语言代码列表，如 `[\"zho\"]`（中文）、`[\"eng\"]`（英文）、`[\"zha\"]`（繁体中文） |\n| `pubdate` | string | ❌ | 出版日期，格式：`\"2024-01-15\"` / `\"2024-01\"` / `\"2024\"` |\n| `comments` | string | ❌ | 书籍简介，支持 HTML，请勿将 `<>` 转义为 `&lt;&gt;` |\n| `category` | string | ❌ | 自定义分类（最长 80 字符；传 `\"清除\"` 或 `\"clear\"` 清空分类） |\n| `book_count` | int | ❌ | 实体书数量（需配合 `book_type: 1` 使用） |\n| `book_type` | int | ❌ | 书籍类型：`0`=电子书，`1`=实体书 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py edit_book '{\"book_id\":42,\"tags\":[\"小说\",\"中国文学\"],\"category\":\"现代文学\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"更新成功\", \"books\": [42] }\n```\n\n---\n\n### `push_notes` — 导入第三方批注（微信读书等）\n\n**使用场景**：把从其他阅读 App（目前是微信读书）读到的划线/想法，通过服务端全文检索定位到 MyBooks 书库里对应 EPUB 书籍的正文位置，写入这本书的阅读记录。详细方案见 `plan/WeChatReading_Annotation_Import_Plan.md`。\n\n**前提**：目标书籍必须已经在 MyBooks 书库里，且**必须有 EPUB 格式**（定位算法依赖 EPUB 的正文结构，其它格式不支持）。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID（须为 EPUB 格式） |\n| `anchors` | array | ✅ | — | 待导入的批注列表，见下 |\n| `anchors[].id` | string | ✅ | — | 来源系统里的稳定 ID（如微信读书的 `bookmarkId`/`reviewId`），用于生成幂等的记录 ID——同样的 `anchors` 重复调用不会重复导入 |\n| `anchors[].text` | string | ❌ | — | 划线/引用的原文，用于全文检索定位；不传则视为\"无原文锚点\"（章节点评/整本书评），会退化为\"挂在章节开头\"的书签 |\n| `anchors[].chapterHint` | string | ❌ | — | 来源系统里的章节标题，`text` 未提供时用于定位章节起始位置 |\n| `anchors[].note` | string | ❌ | — | 用户写的想法/点评正文 |\n| `anchors[].color` | string | ❌ | `\"yellow\"` | 高亮颜色 |\n| `anchors[].style` | string | ❌ | `\"highlight\"` | `highlight`/`underline`/`squiggly` |\n| `anchors[].createdAt` | int | ❌ | 当前时间 | 来源系统里的创建时间（毫秒时间戳） |\n| `anchors[].source` | string | ❌ | `\"wxread\"` | 来源标记 |\n| `on_ambiguous` | string | ❌ | `\"error\"` | 原文在书里检索到多处命中时的处理：`\"error\"`=不写入、标记为歧义待复核；`\"first_match\"`=取第一个命中位置写入 |\n| `dry_run` | bool | ❌ | `true` | `true`=只做检索定位、返回预览报告，不写入；`false`=同时写入。**务必先用 `dry_run:true` 看一遍报告、跟用户确认后再用 `dry_run:false` 提交，不要一步到位直接写入** |\n| `force` | bool | ❌ | `false` | 重复导入默认会**自动判重**：某条 `anchors[].id` 如果 `text`/`chapterHint` 跟上次导入时一样，直接复用上次的定位结果，不会重新跑检索（响应里对应条目会带 `\"reused\": true`）。`force:true` 会跳过判重、强制重新定位所有条目——只有书籍文件本身被替换过这种场景才需要，**日常重复同步不要传这个参数**，判重本身就是为了处理\"微信读书上有新批注后再次同步\"这种情况设计的 |\n\n**再次同步（判重）说明**：微信读书没有增量接口，每次都会拿到全量划线/想法列表。直接把全量列表再传一遍给 `push_notes` 是安全且推荐的做法——服务端会按 `anchors[].id` 匹配上次导入的记录，`text`/`chapterHint` 没变的条目不会重新定位（省时间，也避免同一条批注每次定位到略有不同的位置），只有新增的、或者原文本身变了的条目才会真正重新检索。如果只是想法/评论内容改了但划线原文没变，也会被识别为\"位置没变、内容更新\"，只更新想法文本，不重新定位。\n\n**执行脚本**：\n```bash\n# 第一步：预览（默认 dry_run:true），不会写入任何数据\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ]\n}'\n\n# 第二步：跟用户确认预览报告无误后，正式写入\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ],\n  \"dry_run\": false\n}'\n```\n\n**响应示例**（预览，`dry_run:true`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": true,\n  \"results\": [\n    { \"id\": \"wx-bm-1001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\", \"matchCount\": 1 },\n    { \"id\": \"wx-review-2001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/8!/4)\", \"degraded\": \"chapter_start\" }\n  ]\n}\n```\n\n**响应示例**（提交，`dry_run:false`，额外带 `pushed`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": false,\n  \"results\": [ /* 同上 */ ],\n  \"pushed\": { \"notes\": [ /* 写入后的最终记录，字段与 GET /api/sync 一致 */ ] }\n}\n```\n\n**`results[].status` 取值**：\n| 值 | 含义 | 建议处理 |\n|----|------|----------|\n| `\"ok\"` | 定位成功，`cfi` 有值 | 展示给用户确认；`degraded:\"chapter_start\"` 表示这是退化的章节级书签，不是精确定位，需要提示用户区分 |\n| `\"no_match\"` | 原文在书里没有检索到 | 大概率两边不是同一版本的书，或原文被来源系统二次编辑过；列入失败清单，不会写入 |\n| `\"ambiguous\"` | 原文命中了多处（`matchCount` > 1），且 `on_ambiguous=\"error\"` | 列入歧义清单，需要人工复核；不会写入 |\n| `\"error\"` | 该条内部处理出错（如 CFI 生成失败） | 列入失败清单，不会写入 |\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式，或找不到 EPUB 文件 |\n| `\"sync.import.failed\"` | 服务端批注定位流程整体失败（如 CFI 子进程异常）——不同于单条 `status:\"error\"`，这是整批请求都没有结果 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `get_notes` — 查询书籍批注\n\n**使用场景**：查看某本书已有的划线/批注/书签（通过 `GET /api/sync` 实现，`type=notes`）。\n\n- \"这本书我都划了哪些线？\" / \"看看《活着》的批注\"\n- 确认 `push_notes` 导入结果，或在 `clear_imported_notes` 前先看一眼现有批注\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ❌ | — | 书籍 ID；与 `title` 二选一，优先生效 |\n| `title` | string | ❌ | — | 书名；不传 `book_id` 时用于搜索定位书籍，仅精确匹配到唯一一本书才会继续查询——命中多本时返回 `candidates` 列表，需要调用方明确选择后改传 `book_id` |\n| `own` | int | ❌ | `1` | `1`=只返回当前用户自己的批注；`0`=额外并入其他用户在这本书上共享的批注（受服务端 `ENABLE_SHARED_NOTES` 开关约束） |\n\n**执行脚本**：\n```bash\n# 按 book_id 查询自己的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"book_id\":42}'\n\n# 按书名查询，并包含其他用户共享的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"title\":\"活着\",\"own\":0}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"books\": null,\n  \"configs\": null,\n  \"notes\": [\n    {\n      \"id\": \"wxread-wx-bm-1001\",\n      \"book_hash\": \"cloud-42-epub\",\n      \"type\": \"annotation\",\n      \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\",\n      \"text\": \"他手里拿着两大块磁铁\",\n      \"note\": \"开篇的魔幻现实主义笔法\",\n      \"style\": \"highlight\",\n      \"color\": \"yellow\",\n      \"updated_at\": 1755600000000,\n      \"deleted_at\": null\n    }\n  ]\n}\n```\n**`notes[]` 每条记录的字段**：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `id` | string | 记录唯一 ID；`push_notes` 导入的批注固定带 `wxread-` 前缀 |\n| `book_hash` | string | 所属书籍的 hash（云端书籍固定为 `cloud-<book_id>-epub`） |\n| `type` | string | `\"bookmark\"`（书签）/ `\"annotation\"`（划线+想法）/ `\"excerpt\"`（摘录） |\n| `cfi` | string | 该批注在 EPUB 正文里的定位（canonical CFI） |\n| `text` | string | 划线/摘录的原文，书签类可能为空 |\n| `note` | string | 用户写的想法/点评正文 |\n| `style` | string | `\"highlight\"` / `\"underline\"` / `\"squiggly\"` |\n| `color` | string | 高亮颜色，如 `\"yellow\"`，也可能是十六进制色值 |\n| `global` | bool | 可选；为 `true` 表示对本章节内该 `text` 的所有出现位置生效 |\n| `page` | number | 可选；分页/固定排版格式下的页码 |\n| `updated_at` | number | 最近一次更新的毫秒时间戳，用于判断是否新增/变更 |\n| `deleted_at` | number/null | 墓碑时间戳；非 `null` 表示该批注已被删除，仍会出现在结果里但应视为已删除 |\n\n按书名查询时命中多本书会返回：\n```json\n{ \"status\": \"error\", \"message\": \"Multiple books matched this title; specify book_id\", \"candidates\": [ {\"id\": 42, \"title\": \"活着\", \"authors\": [\"余华\"]}, ... ] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `clear_imported_notes` — 清空某本书已导入的批注（重置用，非日常操作）\n\n**使用场景**：撤销/重置某本书通过 `push_notes` 导入的全部批注——比如导入用错了数据、或者 `on_ambiguous:\"first_match\"` 选错了位置，用户明确要求\"重新导入一遍\"。**不要**把这个当成处理\"再次同步\"的常规手段——`push_notes` 本身已经会自动判重（见上），日常重复同步应该直接再调一次 `push_notes`，不需要先清空。\n\n**范围**：只会清除当前登录用户通过 `push_notes` 导入的批注（`id` 带 `wxread-` 前缀的），不影响这本书上其他人的批注，也不影响用户自己在 MyReader 里手动做的批注。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py clear_imported_notes '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 42, \"book_hash\": \"cloud-42-epub\", \"cleared\": 5 }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `book_fill` — 自动联网填充书籍信息\n\n**使用场景**：\n- \"帮我更新《XX》的封面和简介\"\n- \"书库里有很多书信息不完整，帮我补全\"\n- 批量补全多本书的封面、简介、出版社、出版日期、标签等\n\n**权限**：需要管理员权限\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `idlist` | array 或 `\"all\"` | ✅ | 书籍 ID 数组，或 `\"all\"` 表示全库处理 |\n\n**注意**：任务在后台异步执行，调用后立即返回；书名**默认保留原值不修改**（防止错误覆盖）\n\n**执行脚本**：\n```bash\n# 更新单本书\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42]}'\n\n# 批量更新\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42,43,44]}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"任务启动成功！请耐心等待，稍后再来刷新页面\" }\n```\n\n---\n\n### `save_meta_to_file` — 将元数据保存到电子书文件\n\n**使用场景**：\n- 在书库中修改了书名/作者/简介/标签等元数据后，希望这些信息也写入电子书文件本身（而不只是存在书库数据库里）\n- 仅支持 epub / azw3 / pdf 格式；其余格式（如 mobi、txt）不受影响\n\n**权限**：需要登录，且为管理员或该书籍的所有者\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `fmt` | string | ❌ | 仅同步指定格式（`epub`/`azw3`/`pdf`），省略则同步所有支持的格式 |\n\n**执行脚本**：\n```bash\n# 同步所有支持的格式\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42}'\n\n# 仅同步 epub\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42,\"fmt\":\"epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"成功将元数据同步到文件：EPUB\", \"success_formats\": [\"EPUB\"], \"failed_formats\": [] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"user.no_permission\"` | 非管理员或非书籍所有者 |\n| `\"book.not_found\"` | 书籍不存在 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式（或没有指定的 `fmt`） |\n| `\"book.meta.not_found\"` | 无法获取书籍元数据 |\n| `\"save.failed\"` | 所有格式均同步失败（返回中含 `failed_formats`） |\n\n---\n\n### `mailto` — 发送书籍到邮箱\n\n**使用场景**：将书籍以附件形式发送到指定邮箱（如 Kindle 邮箱）\n\n**格式优先级**：epub > azw3 > pdf > mobi > txt（取首个存在的格式）\n\n**权限**：需要登录，且账号需有推送权限（`can_push`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `email` | string | ✅ | 目标邮箱地址（可以是 Kindle 邮箱） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py mailto '{\"book_id\":42,\"email\":\"user@kindle.com\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"后台正在推送，稍后可以刷新页面，在通知消息中查看结果。\" }\n```\n\n---\n\n### `send_to_device` — 发送书籍到阅读器设备\n\n**使用场景**：通过 WiFi 将书籍直接推送到阅读器设备（仅支持当前网络内的临时设备）\n\n**支持的设备类型（`device_type`）**：\n\n| 类型 | 设备 | 传输方式 | `device_url` 说明 |\n|------|------|----------|-------------------|\n| `kindle` | Kindle 系列 | 邮件发送 | 不需填写，改用 `mailbox` 参数 |\n| `duokan` | 多看阅读器 | HTTP WiFi 上传 | 设备局域网 IP，如 `192.168.1.100` |\n| `ireader` | 掌阅 iReader | HTTP WiFi 上传 | 设备局域网 IP |\n| `hanwang` | 汉王电纸书 | HTTP WiFi 上传 | 设备局域网 IP |\n| `boox` | 文石 BOOX | HTTP WiFi 上传 | 设备局域网 IP |\n| `dangdang` | 当当阅读器 | HTTP WiFi 上传 | 设备局域网 IP |\n\n**WiFi 传输格式优先级**：epub > azw3 > pdf > txt\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `device_type` | string | ✅ | 设备类型（见上表） |\n| `device_url` | string | kindle 以外必填 | 设备局域网 IP 或地址（如 `\"192.168.1.100\"` 或 `\"http://192.168.1.100:80\"`） |\n| `mailbox` | string | kindle 时必填 | Kindle 邮箱地址 |\n\n**执行脚本**：\n```bash\n# 发送到多看设备\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"duokan\",\"device_url\":\"192.168.1.100\"}'\n\n# 发送到 Kindle（通过邮件）\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"kindle\",\"mailbox\":\"mykindle@kindle.cn\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"书籍发送成功\" }\n```\n\n---\n\n### `categories` — 查看分类信息\n\n**使用场景**：获取当前书库中所有自定义分类及各分类下的书籍数量\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py categories '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"categories\": [\n    { \"name\": \"现代文学\", \"count\": 128 },\n    { \"name\": \"科幻\", \"count\": 56 }\n  ]\n}\n```\n\n---\n\n### `list_authors` — 查看作者列表\n\n**使用场景**：获取所有有在库书籍的作者及其书籍数量\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `show` | string | ❌ | 传 `\"all\"` 显示全部，否则返回前 N 条 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_authors '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"meta\": \"author\",\n  \"title\": \"全部作者\",\n  \"items\": [\n    { \"name\": \"余华\", \"count\": 5 },\n    { \"name\": \"刘慈欣\", \"count\": 8 }\n  ],\n  \"total\": 342\n}\n```\n\n---\n\n### `get_author_books` — 查询作者的在库书籍\n\n**使用场景**：获取指定作者在书库中的所有书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `author_name` | string | ✅ | — | 作者名 |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_author_books '{\"author_name\":\"余华\"}'\n```\n\n---\n\n### `book_upload` — 上传电子书\n\n**使用场景**：上传本地电子书文件到书库，支持 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx 等格式\n\n**权限**：需要登录，且账号需有上传权限（`can_upload`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `file_path` | string | ✅ | 本地文件的绝对路径 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_upload '{\"file_path\":\"/path/to/book.epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 123 }\n```\n\n---\n\n### `book_add_by_isbn` — 通过 ISBN 添加实体书\n\n**使用场景**：\n- 扫描实体书的 ISBN 条码后，将书入库\n- 若该 ISBN 书籍已存在，则自动将实体书数量 +1\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `isbn` | string | ✅ | ISBN 编号，如 `\"9787020024759\"` |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_add_by_isbn '{\"isbn\":\"9787020024759\"}'\n```\n\n**响应示例**（新增）：\n```json\n{ \"err\": \"ok\", \"msg\": \"图书添加成功\", \"book_id\": 456 }\n```\n\n**响应示例**（已存在，更新数量）：\n```json\n{ \"err\": \"ok\", \"msg\": \"实体书数量已更新，当前数量：2\", \"book_id\": 123 }\n```\n\n---\n\n### `wants` — 标记/取消想读\n\n**使用场景**：将书籍加入/移出\"想读（待读）\"清单\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `wants` | bool | ❌ | `true` | `true`=标记想读，`false`=取消 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py wants '{\"book_id\":42}'\n```\n\n---\n\n### `list_wants` — 想读清单\n\n**使用场景**：获取当前用户的\"想读（待读）\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_wants '{}'\n```\n\n---\n\n### `favorite` — 收藏/取消收藏\n\n**使用场景**：收藏或取消收藏指定书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `favorite` | bool | ❌ | `true` | `true`=收藏，`false`=取消收藏 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py favorite '{\"book_id\":42}'\n```\n\n---\n\n### `list_favorites` — 收藏列表\n\n**使用场景**：获取当前用户的所有收藏书籍\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_favorites '{}'\n```\n\n---\n\n### `reading` — 设置阅读状态\n\n**使用场景**：标记某本书的阅读状态（未读/在读/已读完）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `read_state` | int | ✅ | 阅读状态：`0`=未读，`1`=在读，`2`=已读完 |\n\n**执行脚本**：\n```bash\n# 标记为在读\n<skill-installation-path>/scripts/mybooks_api.py reading '{\"book_id\":42,\"read_state\":1}'\n```\n\n---\n\n### `list_reading` — 在读书单\n\n**使用场景**：获取当前用户的\"正在阅读\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_reading '{}'\n```\n\n---\n\n### `read_done` — 标记已读完\n\n**使用场景**：快捷将某本书标记为已读完（即 `reading` 工具中 `read_state=2` 的简化版）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py read_done '{\"book_id\":42}'\n```\n\n---\n\n### `list_read_done` — 已读清单\n\n**使用场景**：获取当前用户的\"已读完\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_read_done '{}'\n```\n\n---\n\n### `get_book_reading_stats` — 分格式阅读时长/进度统计\n\n**使用场景**：查看某本书**分格式**（epub/pdf/mobi 等）的阅读时长、阅读进度、开始/完成阅读的时间、开始阅读的次数。与 `reading`/`read_done` 的整本书阅读状态不同，这个接口是\"格式\"级别的细粒度数据。\n\n- \"这本书我读了多久？\" / \"我读到哪了？\" / \"这本书 epub 版我什么时候开始读的？\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book_reading_stats '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": [\n    {\n      \"format\": \"epub\",\n      \"state\": 0,\n      \"total_seconds\": 5421,\n      \"progress_current\": 3,\n      \"progress_total\": 488,\n      \"progress_percent\": 0.61,\n      \"start_time\": \"2026-08-20T10:00:00Z\",\n      \"finish_time\": null,\n      \"start_count\": 1,\n      \"update_time\": \"2026-08-27T09:12:00Z\"\n    }\n  ]\n}\n```\n\n`state`：`0`=在读，`1`=已完成。没有任何格式统计数据时 `stats` 为空数组 `[]`（比如从未通过 MyReader/网页阅读器打开过这本书）。\n\n---\n\n### `update_book_reading_stats` — 手动更新阅读时长/进度\n\n**使用场景**：手动补记或纠正某本书某个格式的阅读数据——导入历史阅读记录、用户口述\"我刚读完这本书的 PDF 版\"、或者网页阅读器等没有自动进度上报的场景。日常通过 MyReader 阅读的书籍会自动统计，**不需要**调用这个工具。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `format` | string | ✅ | 电子书格式，如 `epub`/`pdf`/`mobi`/`azw3`/`txt` |\n| `duration_seconds` | int | ❌ | 累加到该格式累计阅读时长（是增量，不是覆盖总值） |\n| `progress` | array | ❌ | `[当前, 总数]`，如 `[120, 488]`；达到约 100% 会自动标记为已完成 |\n| `start_time` | string | ❌ | ISO8601 字符串或时间戳；显式开启新一轮阅读（开始次数 +1） |\n| `finish_time` | string | ❌ | ISO8601 字符串或时间戳；显式标记本轮阅读已完成 |\n| `state` | int | ❌ | `0`=在读，`1`=已完成，效果与传 `finish_time` 类似（不需要同时传两个） |\n\n**执行脚本**：\n```bash\n# 补记刚读的 40 分钟，并更新进度\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"pdf\",\"duration_seconds\":2400,\"progress\":[50,200]}'\n\n# 手动标记这本书的 epub 版已读完\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"epub\",\"state\":1}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"stats\": { \"format\": \"pdf\", \"state\": 0, \"total_seconds\": 2400, \"progress_current\": 50, \"progress_total\": 200, \"progress_percent\": 25.0, \"start_time\": \"2026-08-27T09:00:00Z\", \"finish_time\": null, \"start_count\": 1, \"update_time\": \"2026-08-27T09:40:00Z\" } }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 缺少 `format`，或 `progress`/`state` 参数格式错误 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n### `get_reading_time` / `set_reading_time` / `delete_reading_time` — 按日期补录阅读时间\n\n> **版本要求：MyBooks v4.3.0+**（旧版本服务端没有 `/api/book/<id>/reading_time`，调用会 404）。\n\n**使用场景**：某天读了书但没有通过 MyReader/网页阅读器自动计时（纸质书、其他 App 等），按**日期**补录一条手工阅读记录。每本书每天最多一条手工记录：再次 `set_reading_time` 同一天是**覆盖**（不是累加），差值会同步到当日阅读统计、该书分格式累计时长和用户总阅读时长。与 `update_book_reading_stats`（按格式累加时长/进度）不同，这里是按天的\"覆盖式\"记录。\n\n**限制**：书籍必须有电子书格式（记录会挂到已有的阅读格式，否则挂到可用格式之一）；日期不能晚于今天；`duration_seconds` 范围 0~64800（18 小时）。均需登录，只影响当前用户自己的数据。\n\n**参数**：\n\n| 工具 | 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|------|\n| 三个都有 | `book_id` | int | ✅ | 书籍 ID |\n| 三个都有 | `date` | string | ✅ | 日期，格式 `YYYY-MM-DD` |\n| `set_reading_time` | `duration_seconds` | int | ✅ | 当天该书的阅读总秒数（覆盖原手工记录） |\n| `set_reading_time` | `start_time` | string | ❌ | 开始时间（文本，如 `\"20:30\"`） |\n| `set_reading_time` | `end_time` | string | ❌ | 结束时间（文本） |\n| `delete_reading_time` | `confirm` | bool | 删除时必填 | 必须为 `true` 才会真正删除，否则只返回预览 |\n\n**执行脚本**：\n```bash\n# 查询某天的手工记录及参考数据（自动记录的秒数、手工秒数、该书总时长）\n<skill-installation-path>/scripts/mybooks_api.py get_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n\n# 补录（或覆盖）：当天读了 45 分钟\n<skill-installation-path>/scripts/mybooks_api.py set_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\",\"duration_seconds\":2700,\"start_time\":\"20:30\",\"end_time\":\"21:15\"}'\n\n# 删除当天的手工记录（同步回退统计）\n<skill-installation-path>/scripts/mybooks_api.py delete_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n# ↑ 不带 confirm 只返回待删记录预览（err:\"confirm.required\"），不会删除；用户明确同意后加 \"confirm\":true 才真正删除\n<skill-installation-path>/scripts/mybooks_api.py delete_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\",\"confirm\":true}'\n```\n\n**响应示例**：\n```json\n// get_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" }, \"date_recorded_seconds\": 600, \"manual_recorded_seconds\": 2700, \"book_total_seconds\": 8121 }\n// set_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" } }\n// delete_reading_time\n{ \"err\": \"ok\", \"deleted\": true }\n```\n`entry` 为 `null` 表示该日没有手工记录；`deleted:false` 表示本来就没有可删的记录。`entry` 的具体字段以服务端返回为准。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 日期格式错误/是未来日期、缺少或超出范围的 `duration_seconds`、书籍没有可阅读的电子书格式 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n## 书单工具列表\n\n> **版本要求：MyBooks v4.3.0+**（旧版本没有 `/api/booklist*` 接口）。书单（booklist）是用户自建的书籍集合，每人数量有上限，可设为公开供他人浏览、点赞。\n\n**权限规则**：浏览公开书单不需登录；创建/修改/删除书单、增删书籍、点赞需要登录，其中修改/删除/增删书籍仅限书单所有者或管理员；私有书单仅所有者/管理员可看，且不能点赞。\n\n**书单对象**（各接口 `booklist(s)` 里的元素）主要字段：`id`、`name`、`description`、`color`、`is_public`、`is_sticky`、`view_count`、`like_count`、`book_count`、`create_time`、`update_time`、`owner`（`id`/`username`/`avatar`）、`is_owner`、`liked_by_me`；列表接口另带 `cover_books`（最多 12 本的封面卡片）。\n\n| 工具 | 说明 | 参数 |\n|------|------|------|\n| `list_my_booklists` | 我的书单（需登录） | 无 |\n| `list_public_booklists` | 公开书单，分页 | `page`（默认 1）、`page_size`（默认 20，最大 50） |\n| `list_liked_booklists` | 我点赞过的书单（需登录） | 无 |\n| `get_booklist` | 书单详情 + 分页书籍（`books`、`books_total`） | `booklist_id`（必填）、`order`（`desc` 默认/`asc`，按加入时间）、`page`、`page_size`（默认 24，最大 60） |\n| `create_booklist` | 新建书单 | `name`（必填）、`description`（≤500 字）、`color`、`is_public`（默认 false） |\n| `update_booklist` | 修改书单，只改传入的字段 | `booklist_id`（必填）、`name`/`description`/`color`/`is_public` |\n| `delete_booklist` | 删除书单（**不会删除书籍本身**）。脚本强制两步确认：不带 `confirm:true` 时**不会删除**，只返回 `err:\"confirm.required\"` 和书单预览（名称/书数量）；须把预览给用户看，用户明确同意后再带 `\"confirm\":true` 重新调用 | `booklist_id`（必填）、`confirm`（真正删除时必须为 `true`） |\n| `booklist_add_books` | 批量加书（不存在的书自动忽略） | `booklist_id`（必填）、`book_ids`（数组，必填） |\n| `booklist_remove_book` | 移出一本书 | `booklist_id`、`book_id`（均必填） |\n| `like_booklist` | 点赞/取消点赞（切换） | `booklist_id`（必填） |\n| `get_book_booklists` | 我的书单里哪些已包含某本书（`contains_book`） | `book_id`（必填） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_my_booklists '{}'\n<skill-installation-path>/scripts/mybooks_api.py create_booklist '{\"name\":\"2026 科幻必读\",\"description\":\"年度科幻\",\"is_public\":true}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_add_books '{\"booklist_id\":7,\"book_ids\":[42,43]}'\n<skill-installation-path>/scripts/mybooks_api.py get_booklist '{\"booklist_id\":7,\"page\":1}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_remove_book '{\"booklist_id\":7,\"book_id\":43}'\n# 删除书单：第一次调用只返回预览，不会删除\n<skill-installation-path>/scripts/mybooks_api.py delete_booklist '{\"booklist_id\":7}'\n# 用户明确同意后才带 confirm\n<skill-installation-path>/scripts/mybooks_api.py delete_booklist '{\"booklist_id\":7,\"confirm\":true}'\n```\n\n**响应示例**（`get_booklist`）：\n```json\n{\n  \"err\": \"ok\",\n  \"booklist\": {\n    \"id\": 7, \"name\": \"2026 科幻必读\", \"is_public\": true, \"book_count\": 2, \"like_count\": 3,\n    \"is_owner\": true, \"liked_by_me\": false,\n    \"books\": [ { \"book_id\": 42, \"title\": \"三体\", \"img\": \"...\", \"thumb\": \"...\", \"href\": \"/book/42\" } ],\n    \"books_total\": 2, \"page\": 1, \"page_size\": 24\n  }\n}\n```\n写操作响应：`create_booklist`/`update_booklist` 返回 `booklist` + `msg`；`booklist_add_books` 返回 `added`、`book_count`；`booklist_remove_book` 返回 `book_count`；`like_booklist` 返回 `liked`（当前是否已点赞）。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"confirm.required\"` | 删除类操作缺少 `confirm:true`，未执行任何删除，仅返回预览 |\n| `\"booklist.not_found\"` | 书单不存在 |\n| `\"booklist.limit_exceeded\"` | 已达每人书单数量上限 |\n| `\"permission.denied\"` | 无权限（非所有者/管理员，或私有书单） |\n| `\"params.invalid\"` | 参数错误（名称为空、未指定书籍、书不在书单中等） |\n| `\"params.book.invalid\"` | `booklist_add_books` 中的书籍全部不存在 |\n\n---\n\n## TTS 有声书工具列表（MiMo TTS，需管理员权限）\n\n> 将 EPUB 电子书转换为有声书。所有 TTS 接口均需要**管理员权限**。\n\n### `tts_save_config` — 保存 TTS API 配置\n\n**使用场景**：配置 TTS API 的连接参数（API URL、模型、密钥、类型等），保存后服务端加密存储\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `api_url` | string | ✅ | API 地址，如 `https://api.xiaomimimo.com/v1/chat/completions` |\n| `model_name` | string | ✅ | 模型 ID，MiMo TTS 类型固定为 `mimo-v2.5-tts` |\n| `api_type` | string | ✅ | API 类型：`chat_completions`（MiMo TTS）/ `audio_speech`（OpenAI 兼容）/ `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型：`bearer`（默认）/ `basic` / `custom` |\n| `voice_name` | string | ❌ | 预置音色 ID（`api_type=chat_completions` 且 `voiceType=preset` 时）或 `audio_speech` 的音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述（`voiceType=custom` 时） |\n| `clone_voice` | string | ❌ | 克隆音色名称（`voiceType=clone` 时） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_save_config '{\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"配置已保存\"\n}\n```\n\n---\n\n### `tts_test_connection` — 测试 API 连接\n\n**使用场景**：使用当前保存的配置发送一次测试请求，验证 API Key 和端点是否可用\n\n**权限**：管理员\n\n**参数**：无（使用已保存的配置）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_test_connection '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"连接成功\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"tts.no_config\"` | 未保存配置，请先调用 `tts_save_config` |\n| `\"tts.connection_failed\"` | 无法连接到 API 服务器 |\n| `\"tts.invalid_key\"` | API Key 无效 |\n\n---\n\n### `tts_convert` — 开始 EPUB 转有声书\n\n**使用场景**：将指定 EPUB 电子书转换为有声书，后台逐章合成 WAV 音频\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `api_url` | string | ✅ | API 地址 |\n| `model_name` | string | ✅ | 模型 ID |\n| `api_type` | string | ✅ | API 类型：`chat_completions` / `audio_speech` / `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型（默认 `bearer`） |\n| `voice_name` | string | ❌ | 预置音色 ID 或 `audio_speech` 音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述 |\n| `clone_voice` | string | ❌ | 克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_convert '{\"book_id\":42,\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"转换任务已启动\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"tts.converting\"` | 已有转换任务在运行 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式 |\n\n---\n\n### `tts_progress` — 查询转换进度\n\n**使用场景**：查询当前 TTS 转换任务的进度、阶段和章节信息\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_progress '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"status\": \"running\",\n  \"progress\": 35,\n  \"stage\": \"converting\",\n  \"current_chapter\": 7,\n  \"total_chapters\": 20,\n  \"current_title\": \"第七章 归途\",\n  \"book_id\": 42\n}\n```\n\n**status 值**：\n| 值 | 含义 |\n|----|------|\n| `\"idle\"` | 无任务运行 |\n| `\"running\"` | 转换进行中 |\n| `\"completed\"` | 转换已完成 |\n| `\"failed\"` | 转换失败 |\n\n---\n\n### `tts_clone_upload` — 上传克隆音色\n\n**使用场景**：上传 MP3/WAV 音频样本作为克隆音色，上传后自动切换到 `mimo-v2.5-tts-voiceclone` 模型\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称（如\"旁白\"、\"男主\"） |\n| `file_path` | string | ✅ | 本地音频文件的绝对路径（MP3/WAV，≤7MB） |\n\n**限制**：\n- 格式：仅支持 `.mp3` 和 `.wav`\n- 大小：原始文件 ≤ 7MB（Base64 编码后约 9.3MB，MiMo 官方限制 Base64 ≤ 10MB）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_upload '{\"voice_name\":\"旁白\",\"file_path\":\"/path/to/sample.mp3\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色上传成功\",\n  \"data\": { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 }\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"clone.exists\"` | 音色名称已存在 |\n| `\"clone.too_large\"` | 文件超过 7MB |\n| `\"clone.invalid_format\"` | 格式不支持 |\n\n---\n\n### `tts_clone_list` — 克隆音色列表\n\n**使用场景**：获取所有已上传的克隆音色列表\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"clones\": [\n    { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 },\n    { \"name\": \"男主\", \"ext\": \"wav\", \"size\": 2097152 }\n  ]\n}\n```\n\n---\n\n### `tts_clone_delete` — 删除克隆音色\n\n**使用场景**：删除指定的克隆音色\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 要删除的克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_delete '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色已删除\"\n}\n```\n\n---\n\n### `tts_clone_audio` — 下载克隆音频\n\n**使用场景**：下载/试听指定的克隆音色原始音频文件（返回二进制 WAV 数据）\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称 |\n| `save_to` | string | ❌ | 保存到本地路径（不传则返回 base64） |\n\n**执行脚本**：\n```bash\n# 保存到文件\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\",\"save_to\":\"/tmp/clone_preview.wav\"}'\n\n# 返回 base64（小文件）\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**（保存到文件）：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"音频已保存\",\n  \"path\": \"/tmp/clone_preview.wav\",\n  \"size\": 1048576\n}\n```\n\n---\n\n### `tts_prompt_list` — 提示词列表\n\n**使用场景**：获取所有已保存的自定义语音提示词\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"prompts\": [\n    { \"name\": \"温柔女声\", \"desc\": \"温柔细腻的语调，语速偏慢，咬字清晰\" },\n    { \"name\": \"沉稳男声\", \"desc\": \"沉稳厚重的语调，语速适中偏低\" }\n  ]\n}\n```\n\n---\n\n### `tts_prompt_save` — 保存提示词\n\n**使用场景**：将自定义音色描述保存为提示词（同名覆盖），存储于服务端 `voice_prompts.json`\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 提示词名称 |\n| `desc` | string | ✅ | 音色描述（自然语言描述语音特征） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_save '{\"name\":\"温柔女声\",\"desc\":\"温柔细腻的语调，语速偏慢，咬字清晰，富有亲和力\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已保存\"\n}\n```\n\n---\n\n### `tts_prompt_delete` — 删除提示词\n\n**使用场景**：删除指定的语音提示词\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 要删除的提示词名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_delete '{\"name\":\"温柔女声\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已删除\"\n}\n```\n\n---\n\n## 使用场景决策指南\n\n```\n用户请求\n│\n├─ \"书库有多少书？\" / \"统计书库\"\n│   → library_stats（详细分类统计）\n│   → 或 get_user_info（快速总数）\n│\n├─ \"我读了多少书？\" / \"阅读情况\"\n│   → reading_stats\n│\n├─ \"找一下 XX 书\" / \"搜索 YY 作者\"\n│   → search_books（按关键词）\n│\n├─ \"找 XX 分类下的书\"\n│   → search_by_category\n│\n├─ \"XX 目录下有什么书\" / \"书库有哪些目录\"\n│   → search_by_folder / list_folders\n│\n├─ \"查看书籍详情\"\n│   → get_book\n│\n├─ \"这本书我都划了哪些线？\" / \"看看《XX》的批注/书签\"\n│   → get_notes（传 book_id 或 title；own:0 可连他人共享的批注一起看）\n│\n├─ \"更新/补全《XX》的封面、简介、标签信息\"（自动从网上获取）\n│   → book_fill（需要管理员权限，传入 book_id 数组）\n│\n├─ \"手动修改《XX》的标签/分类/书名等字段\"\n│   → 先 search_books 确认 book_id → 再 edit_book\n│\n├─ \"把修改后的元数据也写入电子书文件本身\" / \"同步元数据到文件\"\n│   → save_meta_to_file（仅 epub/azw3/pdf，需管理员或书籍所有者权限）\n│\n├─ \"把我在微信读书上的划线/想法导入这本书\" / \"导入第三方批注\"\n│   → 先确认目标书是 EPUB 格式，再用 push_notes（先 dry_run:true 预览，用户确认后再 dry_run:false 提交）\n│   → 微信读书上有新批注后再次同步：直接把全量列表再传一遍 push_notes 即可，会自动判重，不用先清空\n│\n├─ \"撤销/重置这本书导入的批注\" / \"刚才导入错了，重新来一遍\"\n│   → clear_imported_notes（只影响当前用户自己通过 push_notes 导入的批注），然后重新调 push_notes\n│\n\n├─ \"把书发给我的 Kindle / 发到邮箱\"\n│   → mailto（发邮箱附件）\n│\n├─ \"把书发到我的多看/掌阅/BOOX 设备\"\n│   → send_to_device（需设备在同一局域网并开启 WiFi 接收）\n│\n├─ \"上传这本书\" / \"添加实体书\"\n│   → book_upload（电子书文件）\n│   → book_add_by_isbn（实体书 ISBN）\n│\n├─ \"这本书想读\" / \"加入待读清单\"\n│   → wants\n│\n├─ \"收藏这本书\"\n│   → favorite\n│\n├─ \"标记正在读\" / \"标记已读完\"\n│   → reading（read_state: 1 或 2）\n│   → read_done（快捷标记已读完）\n│\n├─ \"这本书读了多久？\" / \"读到哪了？\" / \"epub 版什么时候开始读的？\"\n│   → get_book_reading_stats（分格式的时长/进度/开始完成时间）\n│\n├─ \"帮我补记这本书的阅读时长\" / \"标记这本书 XX 格式已读完\"（无自动心跳的场景）\n│   → update_book_reading_stats\n│\n├─ \"补录某天的阅读时间\" / \"昨天晚上读了 45 分钟没记上\"（v4.3.0+）\n│   → set_reading_time（按日期覆盖）；查看用 get_reading_time；撤销用 delete_reading_time\n│\n├─ \"我有哪些书单？\" / \"把这本书加到《XX》书单\" / \"新建一个书单\"（v4.3.0+）\n│   → list_my_booklists / booklist_add_books / create_booklist\n│   → 看书单里的书：get_booklist；浏览大家的公开书单：list_public_booklists\n│   → 这本书已经在哪些书单里：get_book_booklists\n│\n└─ \"有哪些分类？\" / \"XX 作者有哪些书？\"\n    → categories / list_authors / get_author_books\n```\n\n### TTS 场景\n\n```\n用户请求\n│\n├─ \"配置 TTS API\" / \"设置 MiMo API Key\"\n│   → tts_save_config\n│\n├─ \"测试 API 能不能用\" / \"连接正常吗\"\n│   → tts_test_connection\n│\n├─ \"把这本书转成有声书\" / \"开始转换\"\n│   → tts_convert（需先有配置或直接传参）\n│\n├─ \"转换到哪了\" / \"进度怎么样\"\n│   → tts_progress\n│\n├─ \"上传克隆音色\" / \"我想用自己的声音\"\n│   → tts_clone_upload\n│\n├─ \"有哪些克隆音色\" / \"看看上传的音色\"\n│   → tts_clone_list\n│\n├─ \"删除克隆音色\" / \"不要这个音色了\"\n│   → tts_clone_delete\n│\n├─ \"试听克隆音色\" / \"下载克隆音频\"\n│   → tts_clone_audio\n│\n├─ \"有哪些提示词\" / \"保存的音色描述\"\n│   → tts_prompt_list\n│\n├─ \"保存这个音色描述\" / \"存一个提示词\"\n│   → tts_prompt_save\n│\n└─ \"删除提示词\" / \"不要这个描述了\"\n    → tts_prompt_delete\n```\n\n---\n\n## 预置音色参考\n\nMiMo TTS 类型（`api_type=chat_completions`）内置 9 个预置音色：\n\n| ID | 名称 | 语言 | 性别 |\n|----|------|------|------|\n| `mimo_default` | MiMo-默认 | 中文 | 女 |\n| `冰糖` | 冰糖 | 中文 | 女 |\n| `茉莉` | 茉莉 | 中文 | 女 |\n| `苏打` | 苏打 | 中文 | 男 |\n| `白桦` | 白桦 | 中文 | 男 |\n| `Mia` | Mia | 英文 | 女 |\n| `Chloe` | Chloe | 英文 | 女 |\n| `Milo` | Milo | 英文 | 男 |\n| `Dean` | Dean | 英文 | 男 |\n\n---\n\n## 错误处理规范\n\n| `err` 值 | 含义 | 建议处理 |\n|----------|------|----------|\n| `\"ok\"` | 操作成功 | 展示结果 |\n| `\"user.need_login\"` | 未登录或登录态过期 | 脚本自动重登录，仍失败则检查环境变量 |\n| `\"permission\"` | 无权限 | 说明当前账号权限不足，需管理员协助 |\n| `\"params.book.invalid\"` | 书籍不存在 | 建议用 `search_books` 重新确认 book_id |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式（或找不到 EPUB 文件） | `push_notes` 专属：提示用户该书无法导入批注，仅支持 EPUB |\n| `\"sync.import.failed\"` | `push_notes` 批注定位流程整体失败 | 与单条 `results[].status:\"error\"` 不同，是整批请求都没有结果，稍后重试或检查书籍文件是否损坏 |\n| `\"task.running\"` | 后台有任务在运行 | 等待当前任务完成后重试 |\n| `\"book.notfound\"` | ISBN 对应的书籍未在网上找到 | 换其他数据源或手动添加 |\n| `\"connection.failed\"` | 无法连接到设备 | 检查设备 IP 和 WiFi 接收功能是否开启 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式 | 提示用户该书无法同步元数据到文件 |\n| `\"tts.converting\"` | TTS 转换任务进行中 | 等待完成后重试 |\n| `\"tts.no_config\"` | 未配置 TTS API | 先调用 `tts_save_config` |\n| `\"clone.too_large\"` | 克隆音色文件超限 | 提示用户裁剪音频至 7MB 内 |\n| `\"clone.invalid_format\"` | 克隆音色格式不支持 | 仅支持 MP3/WAV |\n| `\"clone.exists\"` | 克隆音色名称重复 | 换名或先删除旧的 |\n\n---\n\n## 注意事项\n\n1. **认证**：每次调用前脚本会自动登录，无需手动管理 Cookie；若未配置环境变量，脚本立即报错退出。\n2. **book_id**：书籍的唯一整数标识符，可通过 `search_books` 或 `get_book` 获取。\n3. **book_fill 异步性**：联网填充任务在后台运行，调用后立即返回；可通过 `get_book` 查看更新结果。\n4. **edit_book 标签替换**：`tags` 参数会**完整替换**原有标签，如需追加请先 `get_book` 获取现有标签再合并传入。\n5. **send_to_device 限制**：仅支持本地临时推送，不支持通过服务器中转到远程设备。\n6. **在线数据源**：`book_fill` 依赖豆瓣（douban）、百科（baike）等在线源，网络不可用或书籍较冷门时可能无结果。\n7. **批量 book_fill**：建议每批不超过 10 本，避免触发后台任务冲突（`task.running` 错误）。\n8. **TTS 管理员权限**：所有 TTS 接口均需要管理员权限，普通用户无法使用。\n9. **TTS 异步转换**：`tts_convert` 启动后台任务后立即返回，需用 `tts_progress` 轮询进度。\n10. **TTS 断点续传**：重复转换同一本书时，自动跳过已存在的 WAV 文件（≥44 字节），中断后可继续。\n11. **TTS 音频输出**：转换完成后，音频输出到 `/audio/{book_id}` 页面播放，也可通过 Web 界面访问。\n12. **TTS 克隆音色限制**：MP3/WAV ≤ 7MB；上传后自动切换 `mimo-v2.5-tts-voiceclone` 模型。\n13. **TTS 提示词存储**：提示词保存在服务端 `voice_prompts.json`，跨浏览器共享，不依赖本地存储。\n14. **TTS API Key 加密**：API Key 经 PBKDF2-SHA256 + 流加密保存，密钥文件权限 0o600。\n15. **TTS 模型锁定**：MiMo TTS 类型下模型 ID 固定为 `mimo-v2.5-tts`，不可修改；`audio_speech` 和 `custom` 类型可自由修改。\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn7efqfkfz4afhzzg8xd9bbcdh82drav\",\n  \"slug\": \"mybooks\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1790568593903\n}\n\nFile v1.0.7:skill-card.md\n\n## Description:\n\nHelps users manage a MyBooks library, reading activity, annotations, book transfers, and administrator-controlled audiobook conversion and voice settings.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[poxenstudio](https://clawhub.ai/user/poxenstudio)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nMyBooks users can ask an agent to find and organize books, track reading, import annotations, transfer ebooks, and manage audiobooks when authorized.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Credentials, book text, voice samples, or TTS keys may be processed by the configured MyBooks server or TTS provider.\n\nMitigation: Use a trusted server and HTTPS for non-local hosts, keep credentials session-scoped, and review TTS use before sharing sensitive content.\n\nRisk: Uploading an unintended local ebook or voice sample could expose private material.\n\nMitigation: Upload only files explicitly selected by the user and confirm their destination.\n\nRisk: Library edits, annotation imports, and deletions can change or remove user data.\n\nMitigation: Preview supported changes and obtain user confirmation before destructive actions.\n\n## Reference(s):\n\n- [MyBooks skill on ClawHub](https://clawhub.ai/poxenstudio/skills/mybooks)\n- [MyBooks website](https://www.mybooks.top)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration guidance]\n\n**Output Format:** [Natural-language responses based on MyBooks API results, with optional commands or configuration steps]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May save a requested voice recording as a WAV file.]\n\n## Skill Version(s):\n\n1.0.7 (source: ClawHub release evidence)\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 v1.0.7:skill.json\n\n{\n  \"name\": \"MyBooks\",\n  \"license\": \"MIT-0\"\n}\n\nArchive v1.0.6: 5 files, 31758 bytes\n\nFiles: scripts/mybooks_api.py (50225b), skill-card.md (2758b), skill.json (46b), SKILL.md (59698b), _meta.json (126b)\n\nFile v1.0.6:SKILL.md\n\n---\nname: mybooks\nhomepage: https://www.mybooks.top\nallowed-tools: Bash(python3:*)\nmetadata: {\"clawdbot\":{},\"openclaw\":{\"requires\":{\"bins\":[\"python3\"],\"env\":[\"MYBOOKS_HOST\",\"MYBOOKS_USER\",\"MYBOOKS_PASSWORD\"]},\"permissions\":{\"network\":{\"required\":true,\"scope\":\"user-configured MYBOOKS_HOST only\",\"protocols\":[\"http\",\"https\"]},\"filesystem\":{\"read\":\"only when uploading: ebook files (book_upload) and mp3/wav samples (tts_clone_upload) at paths the user gives\",\"write\":\"only tts_clone_audio save_to (.wav, never overwrites)\"}}}}\ndescription: \"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取原始数据）,以及MiMo TTS有声书功能（配置TTS API、EPUB转有声书、查询转换进度、克隆音色与语音提示词管理，需管理员权限）等\"\n---\n\n# MyBooks\n\n## Requirements\n```bash\n# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n# 明文 http 仅允许回环/内网地址（如 192.168.x.x）；公网地址必须用 https\n# 确需对非内网地址使用明文 http 时：export MYBOOKS_ALLOW_INSECURE_HTTP=\"true\"\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'\n```\n\n> **安全提示**：请勿将凭据写入共享或全局配置文件（如 `~/.openclaw/.env`），以避免凭据被其他 agent 或进程意外读取。建议通过会话级环境变量或专用密钥管理工具传入凭据。\n\n## 权限与网络声明\n\n- **网络访问（必需）**：本 skill 是 MyBooks 服务器的 REST 客户端，所有工具都通过 HTTP(S) 访问**且仅访问**用户自己配置的 `MYBOOKS_HOST`，不连接任何其他地址，无遥测、无第三方回传。\n- **会修改数据的工具**：`edit_book`、`push_notes`(`dry_run:false`)、`clear_imported_notes`、`book_fill`、`save_meta_to_file`、`book_upload`、`book_add_by_isbn`、`wants`/`favorite`/`reading`/`read_done`、`set_reading_time`、`delete_reading_time`、书单的创建/修改/删除/增删书/点赞、以及全部 `tts_*` 写操作。删除类工具（`delete_booklist`、`delete_reading_time`）脚本内强制 `confirm:true` 两步确认。\n- **本地文件读取**：仅 `book_upload`（限电子书扩展名 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx）和 `tts_clone_upload`（限 mp3/wav，≤7MB）会读取用户明确给出路径的文件并上传到 `MYBOOKS_HOST`；agent **不得**自行挑选文件上传。\n- **本地文件写入**：仅 `tts_clone_audio` 的 `save_to`（必须 `.wav` 结尾，且不覆盖已存在文件）。\n- **凭据**：见下方\"认证方式\"。\n\n## 通用响应格式与认证方式\n\n### 通用 JSON 响应结构\n所有 API 均返回如下格式：\n```json\n{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}\n```\n\n常见错误码：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"ok\"` | 操作成功 |\n| `\"user.need_login\"` | 未登录或登录态已过期 |\n| `\"permission\"` | 无权限执行该操作 |\n| `\"params.invalid\"` | 请求参数错误 |\n| `\"params.book.invalid\"` | 书籍不存在或 ID 错误 |\n| `\"task.running\"` | 后台任务正在进行中，稍后重试 |\n| `\"tts.converting\"` | TTS 转换任务正在运行 |\n| `\"tts.no_config\"` | 未配置 TTS API |\n| `\"clone.exists\"` | 克隆音色名称已存在 |\n| `\"clone.not_found\"` | 克隆音色不存在 |\n| `\"clone.too_large\"` | 文件超过 7MB 限制 |\n| `\"clone.invalid_format\"` | 仅支持 MP3/WAV 格式 |\n| `\"prompt.exists\"` | 提示词名称已存在 |\n| `\"prompt.not_found\"` | 提示词不存在 |\n\n### 认证方式\n- 脚本通过 `MYBOOKS_USER` / `MYBOOKS_PASSWORD` 环境变量自动调用 `/api/user/sign_in` 完成登录\n- 服务端通过 **Secure Cookie**（`user_id` + `lt`）维持会话\n- 若响应中出现 `err=user.need_login`，脚本会自动重新登录后重试一次；仍失败则报错退出\n- **凭据去向说明**：`MYBOOKS_USER` / `MYBOOKS_PASSWORD` **只会**以表单形式 POST 到用户自己配置的 `MYBOOKS_HOST` 的 `/api/user/sign_in`，不会发往任何其他地址；登录请求不跟随重定向；`MYBOOKS_HOST` 必须是 `http(s)://host[:port]` 且不含内嵌账号密码，对非内网地址要求 https\n- **必须**在调用前配置 `MYBOOKS_HOST`、`MYBOOKS_USER`、`MYBOOKS_PASSWORD` 三个环境变量，否则脚本直接报错退出\n\n---\n\n## 工具列表\n\n### `get_user_info` — 用户信息与系统统计\n\n**使用场景**：获取当前登录用户信息，同时返回书库总体统计（书籍数、作者数等）\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_user_info '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"user\": { \"is_login\": true, \"nickname\": \"管理员\", \"is_admin\": true },\n  \"sys\": { \"books\": 1280, \"authors\": 342, \"tags\": 86, \"mtime\": \"2025-03-01\" }\n}\n```\n\n---\n\n### `library_stats` — 书库统计\n\n**使用场景**：获取书库详细统计，包括电子书/实体书数量及本月新增\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py library_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_books\": 1280,\n    \"ebook_count\": 1210,\n    \"physical_count\": 70,\n    \"month_ebook_count\": 12,\n    \"month_physical_count\": 3,\n    \"current_year\": 2025,\n    \"current_month\": 3\n  }\n}\n```\n\n---\n\n### `reading_stats` — 阅读统计\n\n**使用场景**：获取当前用户的阅读统计（在读/已读数量、本月数据）及当前在读书单\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py reading_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_reading\": 5,\n    \"total_read_done\": 42,\n    \"month_reading\": 2,\n    \"month_read_done\": 3\n  },\n  \"current_reading_books\": [ /* 书籍对象列表 */ ],\n  \"month_read_done_books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_books` — 搜索书籍\n\n**使用场景**：\n- 按书名或作者名搜索，支持简繁体自动转换\n- \"有没有余华的书？\" / \"找一下《三体》\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `name` | string | ✅ | — | 搜索关键词（书名或作者名） |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"name\":\"三体\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"title\": \"搜索：三体\",\n  \"total\": 3,\n  \"books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_by_category` — 按分类查询书籍\n\n**使用场景**：查询指定分类下的所有书籍（基于自定义 `#category` 字段）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `category` | string | ✅ | — | 分类名称，如 \"科幻\" |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_by_category '{\"category\":\"科幻\"}'\n```\n\n---\n\n### `get_book` — 书籍详情\n\n**使用场景**：获取指定书籍的完整信息，包括元数据、可用格式、封面、阅读状态等\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book\": {\n    \"id\": 42,\n    \"title\": \"活着\",\n    \"authors\": [\"余华\"],\n    \"tags\": [\"小说\", \"中国文学\"],\n    \"publisher\": \"作家出版社\",\n    \"isbn\": \"9787506365437\",\n    \"pubdate\": \"2012-08-01\",\n    \"rating\": 9,\n    \"comments\": \"《活着》讲述了...\",\n    \"category\": \"现代文学\",\n    \"available_formats\": [\"epub\", \"pdf\"],\n    \"files\": [\n      {\n        \"format\": \"EPUB\",\n        \"size\": 1330899,\n        \"href\": \"/api/book/42.EPUB\"\n      }\n    ],\n    \"cover_url\": \"/get/cover/42\",\n    \"series\": \"余华作品集\",\n    \"series_index\": 1,\n    \"state\": {\n      \"favorite\": 0,\n      \"wants\": 0,\n      \"read_state\": 1\n    },\n    \"tags\": [\"小说\", \"中国文学\"]\n  },\n  \"kindle_sender\": \"sender@example.com\"\n}\n```\n\n---\n\n### `edit_book` — 编辑书籍元数据\n\n**使用场景**：\n- 手动修改书名、作者、标签、分类等字段\n- 修改实体书数量或类型\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `title` | string | ❌ | 书名 |\n| `authors` | array | ❌ | 作者列表，如 `[\"余华\"]` |\n| `tags` | array | ❌ | 标签列表，**替换**原有标签（想追加需先 `get_book` 获取现有标签再合并） |\n| `publisher` | string | ❌ | 出版社 |\n| `isbn` | string | ❌ | ISBN 编号 |\n| `series` | string | ❌ | 系列/丛书名 |\n| `series_index` | int | ❌ | 系列中的顺序号 |\n| `rating` | number | ❌ | 评分（0–10） |\n| `languages` | array | ❌ | 语言代码列表，如 `[\"zho\"]`（中文）、`[\"eng\"]`（英文）、`[\"zha\"]`（繁体中文） |\n| `pubdate` | string | ❌ | 出版日期，格式：`\"2024-01-15\"` / `\"2024-01\"` / `\"2024\"` |\n| `comments` | string | ❌ | 书籍简介，支持 HTML，请勿将 `<>` 转义为 `&lt;&gt;` |\n| `category` | string | ❌ | 自定义分类（最长 80 字符；传 `\"清除\"` 或 `\"clear\"` 清空分类） |\n| `book_count` | int | ❌ | 实体书数量（需配合 `book_type: 1` 使用） |\n| `book_type` | int | ❌ | 书籍类型：`0`=电子书，`1`=实体书 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py edit_book '{\"book_id\":42,\"tags\":[\"小说\",\"中国文学\"],\"category\":\"现代文学\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"更新成功\", \"books\": [42] }\n```\n\n---\n\n### `push_notes` — 导入第三方批注（微信读书等）\n\n**使用场景**：把从其他阅读 App（目前是微信读书）读到的划线/想法，通过服务端全文检索定位到 MyBooks 书库里对应 EPUB 书籍的正文位置，写入这本书的阅读记录。详细方案见 `plan/WeChatReading_Annotation_Import_Plan.md`。\n\n**前提**：目标书籍必须已经在 MyBooks 书库里，且**必须有 EPUB 格式**（定位算法依赖 EPUB 的正文结构，其它格式不支持）。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID（须为 EPUB 格式） |\n| `anchors` | array | ✅ | — | 待导入的批注列表，见下 |\n| `anchors[].id` | string | ✅ | — | 来源系统里的稳定 ID（如微信读书的 `bookmarkId`/`reviewId`），用于生成幂等的记录 ID——同样的 `anchors` 重复调用不会重复导入 |\n| `anchors[].text` | string | ❌ | — | 划线/引用的原文，用于全文检索定位；不传则视为\"无原文锚点\"（章节点评/整本书评），会退化为\"挂在章节开头\"的书签 |\n| `anchors[].chapterHint` | string | ❌ | — | 来源系统里的章节标题，`text` 未提供时用于定位章节起始位置 |\n| `anchors[].note` | string | ❌ | — | 用户写的想法/点评正文 |\n| `anchors[].color` | string | ❌ | `\"yellow\"` | 高亮颜色 |\n| `anchors[].style` | string | ❌ | `\"highlight\"` | `highlight`/`underline`/`squiggly` |\n| `anchors[].createdAt` | int | ❌ | 当前时间 | 来源系统里的创建时间（毫秒时间戳） |\n| `anchors[].source` | string | ❌ | `\"wxread\"` | 来源标记 |\n| `on_ambiguous` | string | ❌ | `\"error\"` | 原文在书里检索到多处命中时的处理：`\"error\"`=不写入、标记为歧义待复核；`\"first_match\"`=取第一个命中位置写入 |\n| `dry_run` | bool | ❌ | `true` | `true`=只做检索定位、返回预览报告，不写入；`false`=同时写入。**务必先用 `dry_run:true` 看一遍报告、跟用户确认后再用 `dry_run:false` 提交，不要一步到位直接写入** |\n| `force` | bool | ❌ | `false` | 重复导入默认会**自动判重**：某条 `anchors[].id` 如果 `text`/`chapterHint` 跟上次导入时一样，直接复用上次的定位结果，不会重新跑检索（响应里对应条目会带 `\"reused\": true`）。`force:true` 会跳过判重、强制重新定位所有条目——只有书籍文件本身被替换过这种场景才需要，**日常重复同步不要传这个参数**，判重本身就是为了处理\"微信读书上有新批注后再次同步\"这种情况设计的 |\n\n**再次同步（判重）说明**：微信读书没有增量接口，每次都会拿到全量划线/想法列表。直接把全量列表再传一遍给 `push_notes` 是安全且推荐的做法——服务端会按 `anchors[].id` 匹配上次导入的记录，`text`/`chapterHint` 没变的条目不会重新定位（省时间，也避免同一条批注每次定位到略有不同的位置），只有新增的、或者原文本身变了的条目才会真正重新检索。如果只是想法/评论内容改了但划线原文没变，也会被识别为\"位置没变、内容更新\"，只更新想法文本，不重新定位。\n\n**执行脚本**：\n```bash\n# 第一步：预览（默认 dry_run:true），不会写入任何数据\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ]\n}'\n\n# 第二步：跟用户确认预览报告无误后，正式写入\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ],\n  \"dry_run\": false\n}'\n```\n\n**响应示例**（预览，`dry_run:true`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": true,\n  \"results\": [\n    { \"id\": \"wx-bm-1001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\", \"matchCount\": 1 },\n    { \"id\": \"wx-review-2001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/8!/4)\", \"degraded\": \"chapter_start\" }\n  ]\n}\n```\n\n**响应示例**（提交，`dry_run:false`，额外带 `pushed`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": false,\n  \"results\": [ /* 同上 */ ],\n  \"pushed\": { \"notes\": [ /* 写入后的最终记录，字段与 GET /api/sync 一致 */ ] }\n}\n```\n\n**`results[].status` 取值**：\n| 值 | 含义 | 建议处理 |\n|----|------|----------|\n| `\"ok\"` | 定位成功，`cfi` 有值 | 展示给用户确认；`degraded:\"chapter_start\"` 表示这是退化的章节级书签，不是精确定位，需要提示用户区分 |\n| `\"no_match\"` | 原文在书里没有检索到 | 大概率两边不是同一版本的书，或原文被来源系统二次编辑过；列入失败清单，不会写入 |\n| `\"ambiguous\"` | 原文命中了多处（`matchCount` > 1），且 `on_ambiguous=\"error\"` | 列入歧义清单，需要人工复核；不会写入 |\n| `\"error\"` | 该条内部处理出错（如 CFI 生成失败） | 列入失败清单，不会写入 |\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式，或找不到 EPUB 文件 |\n| `\"sync.import.failed\"` | 服务端批注定位流程整体失败（如 CFI 子进程异常）——不同于单条 `status:\"error\"`，这是整批请求都没有结果 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `get_notes` — 查询书籍批注\n\n**使用场景**：查看某本书已有的划线/批注/书签（通过 `GET /api/sync` 实现，`type=notes`）。\n\n- \"这本书我都划了哪些线？\" / \"看看《活着》的批注\"\n- 确认 `push_notes` 导入结果，或在 `clear_imported_notes` 前先看一眼现有批注\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ❌ | — | 书籍 ID；与 `title` 二选一，优先生效 |\n| `title` | string | ❌ | — | 书名；不传 `book_id` 时用于搜索定位书籍，仅精确匹配到唯一一本书才会继续查询——命中多本时返回 `candidates` 列表，需要调用方明确选择后改传 `book_id` |\n| `own` | int | ❌ | `1` | `1`=只返回当前用户自己的批注；`0`=额外并入其他用户在这本书上共享的批注（受服务端 `ENABLE_SHARED_NOTES` 开关约束） |\n\n**执行脚本**：\n```bash\n# 按 book_id 查询自己的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"book_id\":42}'\n\n# 按书名查询，并包含其他用户共享的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"title\":\"活着\",\"own\":0}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"books\": null,\n  \"configs\": null,\n  \"notes\": [\n    {\n      \"id\": \"wxread-wx-bm-1001\",\n      \"book_hash\": \"cloud-42-epub\",\n      \"type\": \"annotation\",\n      \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\",\n      \"text\": \"他手里拿着两大块磁铁\",\n      \"note\": \"开篇的魔幻现实主义笔法\",\n      \"style\": \"highlight\",\n      \"color\": \"yellow\",\n      \"updated_at\": 1755600000000,\n      \"deleted_at\": null\n    }\n  ]\n}\n```\n**`notes[]` 每条记录的字段**：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `id` | string | 记录唯一 ID；`push_notes` 导入的批注固定带 `wxread-` 前缀 |\n| `book_hash` | string | 所属书籍的 hash（云端书籍固定为 `cloud-<book_id>-epub`） |\n| `type` | string | `\"bookmark\"`（书签）/ `\"annotation\"`（划线+想法）/ `\"excerpt\"`（摘录） |\n| `cfi` | string | 该批注在 EPUB 正文里的定位（canonical CFI） |\n| `text` | string | 划线/摘录的原文，书签类可能为空 |\n| `note` | string | 用户写的想法/点评正文 |\n| `style` | string | `\"highlight\"` / `\"underline\"` / `\"squiggly\"` |\n| `color` | string | 高亮颜色，如 `\"yellow\"`，也可能是十六进制色值 |\n| `global` | bool | 可选；为 `true` 表示对本章节内该 `text` 的所有出现位置生效 |\n| `page` | number | 可选；分页/固定排版格式下的页码 |\n| `updated_at` | number | 最近一次更新的毫秒时间戳，用于判断是否新增/变更 |\n| `deleted_at` | number/null | 墓碑时间戳；非 `null` 表示该批注已被删除，仍会出现在结果里但应视为已删除 |\n\n按书名查询时命中多本书会返回：\n```json\n{ \"status\": \"error\", \"message\": \"Multiple books matched this title; specify book_id\", \"candidates\": [ {\"id\": 42, \"title\": \"活着\", \"authors\": [\"余华\"]}, ... ] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `clear_imported_notes` — 清空某本书已导入的批注（重置用，非日常操作）\n\n**使用场景**：撤销/重置某本书通过 `push_notes` 导入的全部批注——比如导入用错了数据、或者 `on_ambiguous:\"first_match\"` 选错了位置，用户明确要求\"重新导入一遍\"。**不要**把这个当成处理\"再次同步\"的常规手段——`push_notes` 本身已经会自动判重（见上），日常重复同步应该直接再调一次 `push_notes`，不需要先清空。\n\n**范围**：只会清除当前登录用户通过 `push_notes` 导入的批注（`id` 带 `wxread-` 前缀的），不影响这本书上其他人的批注，也不影响用户自己在 MyReader 里手动做的批注。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py clear_imported_notes '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 42, \"book_hash\": \"cloud-42-epub\", \"cleared\": 5 }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `book_fill` — 自动联网填充书籍信息\n\n**使用场景**：\n- \"帮我更新《XX》的封面和简介\"\n- \"书库里有很多书信息不完整，帮我补全\"\n- 批量补全多本书的封面、简介、出版社、出版日期、标签等\n\n**权限**：需要管理员权限\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `idlist` | array 或 `\"all\"` | ✅ | 书籍 ID 数组，或 `\"all\"` 表示全库处理 |\n\n**注意**：任务在后台异步执行，调用后立即返回；书名**默认保留原值不修改**（防止错误覆盖）\n\n**执行脚本**：\n```bash\n# 更新单本书\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42]}'\n\n# 批量更新\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42,43,44]}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"任务启动成功！请耐心等待，稍后再来刷新页面\" }\n```\n\n---\n\n### `save_meta_to_file` — 将元数据保存到电子书文件\n\n**使用场景**：\n- 在书库中修改了书名/作者/简介/标签等元数据后，希望这些信息也写入电子书文件本身（而不只是存在书库数据库里）\n- 仅支持 epub / azw3 / pdf 格式；其余格式（如 mobi、txt）不受影响\n\n**权限**：需要登录，且为管理员或该书籍的所有者\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `fmt` | string | ❌ | 仅同步指定格式（`epub`/`azw3`/`pdf`），省略则同步所有支持的格式 |\n\n**执行脚本**：\n```bash\n# 同步所有支持的格式\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42}'\n\n# 仅同步 epub\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42,\"fmt\":\"epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"成功将元数据同步到文件：EPUB\", \"success_formats\": [\"EPUB\"], \"failed_formats\": [] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"user.no_permission\"` | 非管理员或非书籍所有者 |\n| `\"book.not_found\"` | 书籍不存在 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式（或没有指定的 `fmt`） |\n| `\"book.meta.not_found\"` | 无法获取书籍元数据 |\n| `\"save.failed\"` | 所有格式均同步失败（返回中含 `failed_formats`） |\n\n---\n\n### `mailto` — 发送书籍到邮箱\n\n**使用场景**：将书籍以附件形式发送到指定邮箱（如 Kindle 邮箱）\n\n**格式优先级**：epub > azw3 > pdf > mobi > txt（取首个存在的格式）\n\n**权限**：需要登录，且账号需有推送权限（`can_push`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `email` | string | ✅ | 目标邮箱地址（可以是 Kindle 邮箱） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py mailto '{\"book_id\":42,\"email\":\"user@kindle.com\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"后台正在推送，稍后可以刷新页面，在通知消息中查看结果。\" }\n```\n\n---\n\n### `send_to_device` — 发送书籍到阅读器设备\n\n**使用场景**：通过 WiFi 将书籍直接推送到阅读器设备（仅支持当前网络内的临时设备）\n\n**支持的设备类型（`device_type`）**：\n\n| 类型 | 设备 | 传输方式 | `device_url` 说明 |\n|------|------|----------|-------------------|\n| `kindle` | Kindle 系列 | 邮件发送 | 不需填写，改用 `mailbox` 参数 |\n| `duokan` | 多看阅读器 | HTTP WiFi 上传 | 设备局域网 IP，如 `192.168.1.100` |\n| `ireader` | 掌阅 iReader | HTTP WiFi 上传 | 设备局域网 IP |\n| `hanwang` | 汉王电纸书 | HTTP WiFi 上传 | 设备局域网 IP |\n| `boox` | 文石 BOOX | HTTP WiFi 上传 | 设备局域网 IP |\n| `dangdang` | 当当阅读器 | HTTP WiFi 上传 | 设备局域网 IP |\n\n**WiFi 传输格式优先级**：epub > azw3 > pdf > txt\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `device_type` | string | ✅ | 设备类型（见上表） |\n| `device_url` | string | kindle 以外必填 | 设备局域网 IP 或地址（如 `\"192.168.1.100\"` 或 `\"http://192.168.1.100:80\"`） |\n| `mailbox` | string | kindle 时必填 | Kindle 邮箱地址 |\n\n**执行脚本**：\n```bash\n# 发送到多看设备\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"duokan\",\"device_url\":\"192.168.1.100\"}'\n\n# 发送到 Kindle（通过邮件）\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"kindle\",\"mailbox\":\"mykindle@kindle.cn\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"书籍发送成功\" }\n```\n\n---\n\n### `categories` — 查看分类信息\n\n**使用场景**：获取当前书库中所有自定义分类及各分类下的书籍数量\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py categories '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"categories\": [\n    { \"name\": \"现代文学\", \"count\": 128 },\n    { \"name\": \"科幻\", \"count\": 56 }\n  ]\n}\n```\n\n---\n\n### `list_authors` — 查看作者列表\n\n**使用场景**：获取所有有在库书籍的作者及其书籍数量\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `show` | string | ❌ | 传 `\"all\"` 显示全部，否则返回前 N 条 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_authors '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"meta\": \"author\",\n  \"title\": \"全部作者\",\n  \"items\": [\n    { \"name\": \"余华\", \"count\": 5 },\n    { \"name\": \"刘慈欣\", \"count\": 8 }\n  ],\n  \"total\": 342\n}\n```\n\n---\n\n### `get_author_books` — 查询作者的在库书籍\n\n**使用场景**：获取指定作者在书库中的所有书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `author_name` | string | ✅ | — | 作者名 |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_author_books '{\"author_name\":\"余华\"}'\n```\n\n---\n\n### `book_upload` — 上传电子书\n\n**使用场景**：上传本地电子书文件到书库，支持 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx 等格式\n\n**权限**：需要登录，且账号需有上传权限（`can_upload`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `file_path` | string | ✅ | 本地文件的绝对路径 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_upload '{\"file_path\":\"/path/to/book.epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 123 }\n```\n\n---\n\n### `book_add_by_isbn` — 通过 ISBN 添加实体书\n\n**使用场景**：\n- 扫描实体书的 ISBN 条码后，将书入库\n- 若该 ISBN 书籍已存在，则自动将实体书数量 +1\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `isbn` | string | ✅ | ISBN 编号，如 `\"9787020024759\"` |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_add_by_isbn '{\"isbn\":\"9787020024759\"}'\n```\n\n**响应示例**（新增）：\n```json\n{ \"err\": \"ok\", \"msg\": \"图书添加成功\", \"book_id\": 456 }\n```\n\n**响应示例**（已存在，更新数量）：\n```json\n{ \"err\": \"ok\", \"msg\": \"实体书数量已更新，当前数量：2\", \"book_id\": 123 }\n```\n\n---\n\n### `wants` — 标记/取消想读\n\n**使用场景**：将书籍加入/移出\"想读（待读）\"清单\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `wants` | bool | ❌ | `true` | `true`=标记想读，`false`=取消 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py wants '{\"book_id\":42}'\n```\n\n---\n\n### `list_wants` — 想读清单\n\n**使用场景**：获取当前用户的\"想读（待读）\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_wants '{}'\n```\n\n---\n\n### `favorite` — 收藏/取消收藏\n\n**使用场景**：收藏或取消收藏指定书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `favorite` | bool | ❌ | `true` | `true`=收藏，`false`=取消收藏 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py favorite '{\"book_id\":42}'\n```\n\n---\n\n### `list_favorites` — 收藏列表\n\n**使用场景**：获取当前用户的所有收藏书籍\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_favorites '{}'\n```\n\n---\n\n### `reading` — 设置阅读状态\n\n**使用场景**：标记某本书的阅读状态（未读/在读/已读完）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `read_state` | int | ✅ | 阅读状态：`0`=未读，`1`=在读，`2`=已读完 |\n\n**执行脚本**：\n```bash\n# 标记为在读\n<skill-installation-path>/scripts/mybooks_api.py reading '{\"book_id\":42,\"read_state\":1}'\n```\n\n---\n\n### `list_reading` — 在读书单\n\n**使用场景**：获取当前用户的\"正在阅读\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_reading '{}'\n```\n\n---\n\n### `read_done` — 标记已读完\n\n**使用场景**：快捷将某本书标记为已读完（即 `reading` 工具中 `read_state=2` 的简化版）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py read_done '{\"book_id\":42}'\n```\n\n---\n\n### `list_read_done` — 已读清单\n\n**使用场景**：获取当前用户的\"已读完\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_read_done '{}'\n```\n\n---\n\n### `get_book_reading_stats` — 分格式阅读时长/进度统计\n\n**使用场景**：查看某本书**分格式**（epub/pdf/mobi 等）的阅读时长、阅读进度、开始/完成阅读的时间、开始阅读的次数。与 `reading`/`read_done` 的整本书阅读状态不同，这个接口是\"格式\"级别的细粒度数据。\n\n- \"这本书我读了多久？\" / \"我读到哪了？\" / \"这本书 epub 版我什么时候开始读的？\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book_reading_stats '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": [\n    {\n      \"format\": \"epub\",\n      \"state\": 0,\n      \"total_seconds\": 5421,\n      \"progress_current\": 3,\n      \"progress_total\": 488,\n      \"progress_percent\": 0.61,\n      \"start_time\": \"2026-08-20T10:00:00Z\",\n      \"finish_time\": null,\n      \"start_count\": 1,\n      \"update_time\": \"2026-08-27T09:12:00Z\"\n    }\n  ]\n}\n```\n\n`state`：`0`=在读，`1`=已完成。没有任何格式统计数据时 `stats` 为空数组 `[]`（比如从未通过 MyReader/网页阅读器打开过这本书）。\n\n---\n\n### `update_book_reading_stats` — 手动更新阅读时长/进度\n\n**使用场景**：手动补记或纠正某本书某个格式的阅读数据——导入历史阅读记录、用户口述\"我刚读完这本书的 PDF 版\"、或者网页阅读器等没有自动进度上报的场景。日常通过 MyReader 阅读的书籍会自动统计，**不需要**调用这个工具。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `format` | string | ✅ | 电子书格式，如 `epub`/`pdf`/`mobi`/`azw3`/`txt` |\n| `duration_seconds` | int | ❌ | 累加到该格式累计阅读时长（是增量，不是覆盖总值） |\n| `progress` | array | ❌ | `[当前, 总数]`，如 `[120, 488]`；达到约 100% 会自动标记为已完成 |\n| `start_time` | string | ❌ | ISO8601 字符串或时间戳；显式开启新一轮阅读（开始次数 +1） |\n| `finish_time` | string | ❌ | ISO8601 字符串或时间戳；显式标记本轮阅读已完成 |\n| `state` | int | ❌ | `0`=在读，`1`=已完成，效果与传 `finish_time` 类似（不需要同时传两个） |\n\n**执行脚本**：\n```bash\n# 补记刚读的 40 分钟，并更新进度\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"pdf\",\"duration_seconds\":2400,\"progress\":[50,200]}'\n\n# 手动标记这本书的 epub 版已读完\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"epub\",\"state\":1}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"stats\": { \"format\": \"pdf\", \"state\": 0, \"total_seconds\": 2400, \"progress_current\": 50, \"progress_total\": 200, \"progress_percent\": 25.0, \"start_time\": \"2026-08-27T09:00:00Z\", \"finish_time\": null, \"start_count\": 1, \"update_time\": \"2026-08-27T09:40:00Z\" } }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 缺少 `format`，或 `progress`/`state` 参数格式错误 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n### `get_reading_time` / `set_reading_time` / `delete_reading_time` — 按日期补录阅读时间\n\n> **版本要求：MyBooks v4.3.0+**（旧版本服务端没有 `/api/book/<id>/reading_time`，调用会 404）。\n\n**使用场景**：某天读了书但没有通过 MyReader/网页阅读器自动计时（纸质书、其他 App 等），按**日期**补录一条手工阅读记录。每本书每天最多一条手工记录：再次 `set_reading_time` 同一天是**覆盖**（不是累加），差值会同步到当日阅读统计、该书分格式累计时长和用户总阅读时长。与 `update_book_reading_stats`（按格式累加时长/进度）不同，这里是按天的\"覆盖式\"记录。\n\n**限制**：书籍必须有电子书格式（记录会挂到已有的阅读格式，否则挂到可用格式之一）；日期不能晚于今天；`duration_seconds` 范围 0~64800（18 小时）。均需登录，只影响当前用户自己的数据。\n\n**参数**：\n\n| 工具 | 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|------|\n| 三个都有 | `book_id` | int | ✅ | 书籍 ID |\n| 三个都有 | `date` | string | ✅ | 日期，格式 `YYYY-MM-DD` |\n| `set_reading_time` | `duration_seconds` | int | ✅ | 当天该书的阅读总秒数（覆盖原手工记录） |\n| `set_reading_time` | `start_time` | string | ❌ | 开始时间（文本，如 `\"20:30\"`） |\n| `set_reading_time` | `end_time` | string | ❌ | 结束时间（文本） |\n| `delete_reading_time` | `confirm` | bool | 删除时必填 | 必须为 `true` 才会真正删除，否则只返回预览 |\n\n**执行脚本**：\n```bash\n# 查询某天的手工记录及参考数据（自动记录的秒数、手工秒数、该书总时长）\n<skill-installation-path>/scripts/mybooks_api.py get_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n\n# 补录（或覆盖）：当天读了 45 分钟\n<skill-installation-path>/scripts/mybooks_api.py set_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\",\"duration_seconds\":2700,\"start_time\":\"20:30\",\"end_time\":\"21:15\"}'\n\n# 删除当天的手工记录（同步回退统计）\n<skill-installation-path>/scripts/mybooks_api.py delete_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n# ↑ 不带 confirm 只返回待删记录预览（err:\"confirm.required\"），不会删除；用户明确同意后加 \"confirm\":true 才真正删除\n<skill-installation-path>/scripts/mybooks_api.py delete_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\",\"confirm\":true}'\n```\n\n**响应示例**：\n```json\n// get_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" }, \"date_recorded_seconds\": 600, \"manual_recorded_seconds\": 2700, \"book_total_seconds\": 8121 }\n// set_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" } }\n// delete_reading_time\n{ \"err\": \"ok\", \"deleted\": true }\n```\n`entry` 为 `null` 表示该日没有手工记录；`deleted:false` 表示本来就没有可删的记录。`entry` 的具体字段以服务端返回为准。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 日期格式错误/是未来日期、缺少或超出范围的 `duration_seconds`、书籍没有可阅读的电子书格式 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n## 书单工具列表\n\n> **版本要求：MyBooks v4.3.0+**（旧版本没有 `/api/booklist*` 接口）。书单（booklist）是用户自建的书籍集合，每人数量有上限，可设为公开供他人浏览、点赞。\n\n**权限规则**：浏览公开书单不需登录；创建/修改/删除书单、增删书籍、点赞需要登录，其中修改/删除/增删书籍仅限书单所有者或管理员；私有书单仅所有者/管理员可看，且不能点赞。\n\n**书单对象**（各接口 `booklist(s)` 里的元素）主要字段：`id`、`name`、`description`、`color`、`is_public`、`is_sticky`、`view_count`、`like_count`、`book_count`、`create_time`、`update_time`、`owner`（`id`/`username`/`avatar`）、`is_owner`、`liked_by_me`；列表接口另带 `cover_books`（最多 12 本的封面卡片）。\n\n| 工具 | 说明 | 参数 |\n|------|------|------|\n| `list_my_booklists` | 我的书单（需登录） | 无 |\n| `list_public_booklists` | 公开书单，分页 | `page`（默认 1）、`page_size`（默认 20，最大 50） |\n| `list_liked_booklists` | 我点赞过的书单（需登录） | 无 |\n| `get_booklist` | 书单详情 + 分页书籍（`books`、`books_total`） | `booklist_id`（必填）、`order`（`desc` 默认/`asc`，按加入时间）、`page`、`page_size`（默认 24，最大 60） |\n| `create_booklist` | 新建书单 | `name`（必填）、`description`（≤500 字）、`color`、`is_public`（默认 false） |\n| `update_booklist` | 修改书单，只改传入的字段 | `booklist_id`（必填）、`name`/`description`/`color`/`is_public` |\n| `delete_booklist` | 删除书单（**不会删除书籍本身**）。脚本强制两步确认：不带 `confirm:true` 时**不会删除**，只返回 `err:\"confirm.required\"` 和书单预览（名称/书数量）；须把预览给用户看，用户明确同意后再带 `\"confirm\":true` 重新调用 | `booklist_id`（必填）、`confirm`（真正删除时必须为 `true`） |\n| `booklist_add_books` | 批量加书（不存在的书自动忽略） | `booklist_id`（必填）、`book_ids`（数组，必填） |\n| `booklist_remove_book` | 移出一本书 | `booklist_id`、`book_id`（均必填） |\n| `like_booklist` | 点赞/取消点赞（切换） | `booklist_id`（必填） |\n| `get_book_booklists` | 我的书单里哪些已包含某本书（`contains_book`） | `book_id`（必填） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_my_booklists '{}'\n<skill-installation-path>/scripts/mybooks_api.py create_booklist '{\"name\":\"2026 科幻必读\",\"description\":\"年度科幻\",\"is_public\":true}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_add_books '{\"booklist_id\":7,\"book_ids\":[42,43]}'\n<skill-installation-path>/scripts/mybooks_api.py get_booklist '{\"booklist_id\":7,\"page\":1}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_remove_book '{\"booklist_id\":7,\"book_id\":43}'\n# 删除书单：第一次调用只返回预览，不会删除\n<skill-installation-path>/scripts/mybooks_api.py delete_booklist '{\"booklist_id\":7}'\n# 用户明确同意后才带 confirm\n<skill-installation-path>/scripts/mybooks_api.py delete_booklist '{\"booklist_id\":7,\"confirm\":true}'\n```\n\n**响应示例**（`get_booklist`）：\n```json\n{\n  \"err\": \"ok\",\n  \"booklist\": {\n    \"id\": 7, \"name\": \"2026 科幻必读\", \"is_public\": true, \"book_count\": 2, \"like_count\": 3,\n    \"is_owner\": true, \"liked_by_me\": false,\n    \"books\": [ { \"book_id\": 42, \"title\": \"三体\", \"img\": \"...\", \"thumb\": \"...\", \"href\": \"/book/42\" } ],\n    \"books_total\": 2, \"page\": 1, \"page_size\": 24\n  }\n}\n```\n写操作响应：`create_booklist`/`update_booklist` 返回 `booklist` + `msg`；`booklist_add_books` 返回 `added`、`book_count`；`booklist_remove_book` 返回 `book_count`；`like_booklist` 返回 `liked`（当前是否已点赞）。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"confirm.required\"` | 删除类操作缺少 `confirm:true`，未执行任何删除，仅返回预览 |\n| `\"booklist.not_found\"` | 书单不存在 |\n| `\"booklist.limit_exceeded\"` | 已达每人书单数量上限 |\n| `\"permission.denied\"` | 无权限（非所有者/管理员，或私有书单） |\n| `\"params.invalid\"` | 参数错误（名称为空、未指定书籍、书不在书单中等） |\n| `\"params.book.invalid\"` | `booklist_add_books` 中的书籍全部不存在 |\n\n---\n\n## TTS 有声书工具列表（MiMo TTS，需管理员权限）\n\n> 将 EPUB 电子书转换为有声书。所有 TTS 接口均需要**管理员权限**。\n\n### `tts_save_config` — 保存 TTS API 配置\n\n**使用场景**：配置 TTS API 的连接参数（API URL、模型、密钥、类型等），保存后服务端加密存储\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `api_url` | string | ✅ | API 地址，如 `https://api.xiaomimimo.com/v1/chat/completions` |\n| `model_name` | string | ✅ | 模型 ID，MiMo TTS 类型固定为 `mimo-v2.5-tts` |\n| `api_type` | string | ✅ | API 类型：`chat_completions`（MiMo TTS）/ `audio_speech`（OpenAI 兼容）/ `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型：`bearer`（默认）/ `basic` / `custom` |\n| `voice_name` | string | ❌ | 预置音色 ID（`api_type=chat_completions` 且 `voiceType=preset` 时）或 `audio_speech` 的音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述（`voiceType=custom` 时） |\n| `clone_voice` | string | ❌ | 克隆音色名称（`voiceType=clone` 时） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_save_config '{\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"配置已保存\"\n}\n```\n\n---\n\n### `tts_test_connection` — 测试 API 连接\n\n**使用场景**：使用当前保存的配置发送一次测试请求，验证 API Key 和端点是否可用\n\n**权限**：管理员\n\n**参数**：无（使用已保存的配置）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_test_connection '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"连接成功\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"tts.no_config\"` | 未保存配置，请先调用 `tts_save_config` |\n| `\"tts.connection_failed\"` | 无法连接到 API 服务器 |\n| `\"tts.invalid_key\"` | API Key 无效 |\n\n---\n\n### `tts_convert` — 开始 EPUB 转有声书\n\n**使用场景**：将指定 EPUB 电子书转换为有声书，后台逐章合成 WAV 音频\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `api_url` | string | ✅ | API 地址 |\n| `model_name` | string | ✅ | 模型 ID |\n| `api_type` | string | ✅ | API 类型：`chat_completions` / `audio_speech` / `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型（默认 `bearer`） |\n| `voice_name` | string | ❌ | 预置音色 ID 或 `audio_speech` 音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述 |\n| `clone_voice` | string | ❌ | 克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_convert '{\"book_id\":42,\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"转换任务已启动\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"tts.converting\"` | 已有转换任务在运行 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式 |\n\n---\n\n### `tts_progress` — 查询转换进度\n\n**使用场景**：查询当前 TTS 转换任务的进度、阶段和章节信息\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_progress '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"status\": \"running\",\n  \"progress\": 35,\n  \"stage\": \"converting\",\n  \"current_chapter\": 7,\n  \"total_chapters\": 20,\n  \"current_title\": \"第七章 归途\",\n  \"book_id\": 42\n}\n```\n\n**status 值**：\n| 值 | 含义 |\n|----|------|\n| `\"idle\"` | 无任务运行 |\n| `\"running\"` | 转换进行中 |\n| `\"completed\"` | 转换已完成 |\n| `\"failed\"` | 转换失败 |\n\n---\n\n### `tts_clone_upload` — 上传克隆音色\n\n**使用场景**：上传 MP3/WAV 音频样本作为克隆音色，上传后自动切换到 `mimo-v2.5-tts-voiceclone` 模型\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称（如\"旁白\"、\"男主\"） |\n| `file_path` | string | ✅ | 本地音频文件的绝对路径（MP3/WAV，≤7MB） |\n\n**限制**：\n- 格式：仅支持 `.mp3` 和 `.wav`\n- 大小：原始文件 ≤ 7MB（Base64 编码后约 9.3MB，MiMo 官方限制 Base64 ≤ 10MB）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_upload '{\"voice_name\":\"旁白\",\"file_path\":\"/path/to/sample.mp3\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色上传成功\",\n  \"data\": { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 }\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"clone.exists\"` | 音色名称已存在 |\n| `\"clone.too_large\"` | 文件超过 7MB |\n| `\"clone.invalid_format\"` | 格式不支持 |\n\n---\n\n### `tts_clone_list` — 克隆音色列表\n\n**使用场景**：获取所有已上传的克隆音色列表\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"clones\": [\n    { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 },\n    { \"name\": \"男主\", \"ext\": \"wav\", \"size\": 2097152 }\n  ]\n}\n```\n\n---\n\n### `tts_clone_delete` — 删除克隆音色\n\n**使用场景**：删除指定的克隆音色\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 要删除的克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_delete '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色已删除\"\n}\n```\n\n---\n\n### `tts_clone_audio` — 下载克隆音频\n\n**使用场景**：下载/试听指定的克隆音色原始音频文件（返回二进制 WAV 数据）\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称 |\n| `save_to` | string | ❌ | 保存到本地路径（不传则返回 base64） |\n\n**执行脚本**：\n```bash\n# 保存到文件\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\",\"save_to\":\"/tmp/clone_preview.wav\"}'\n\n# 返回 base64（小文件）\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**（保存到文件）：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"音频已保存\",\n  \"path\": \"/tmp/clone_preview.wav\",\n  \"size\": 1048576\n}\n```\n\n---\n\n### `tts_prompt_list` — 提示词列表\n\n**使用场景**：获取所有已保存的自定义语音提示词\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"prompts\": [\n    { \"name\": \"温柔女声\", \"desc\": \"温柔细腻的语调，语速偏慢，咬字清晰\" },\n    { \"name\": \"沉稳男声\", \"desc\": \"沉稳厚重的语调，语速适中偏低\" }\n  ]\n}\n```\n\n---\n\n### `tts_prompt_save` — 保存提示词\n\n**使用场景**：将自定义音色描述保存为提示词（同名覆盖），存储于服务端 `voice_prompts.json`\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 提示词名称 |\n| `desc` | string | ✅ | 音色描述（自然语言描述语音特征） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_save '{\"name\":\"温柔女声\",\"desc\":\"温柔细腻的语调，语速偏慢，咬字清晰，富有亲和力\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已保存\"\n}\n```\n\n---\n\n### `tts_prompt_delete` — 删除提示词\n\n**使用场景**：删除指定的语音提示词\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 要删除的提示词名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_delete '{\"name\":\"温柔女声\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已删除\"\n}\n```\n\n---\n\n## 使用场景决策指南\n\n```\n用户请求\n│\n├─ \"书库有多少书？\" / \"统计书库\"\n│   → library_stats（详细分类统计）\n│   → 或 get_user_info（快速总数）\n│\n├─ \"我读了多少书？\" / \"阅读情况\"\n│   → reading_stats\n│\n├─ \"找一下 XX 书\" / \"搜索 YY 作者\"\n│   → search_books（按关键词）\n│\n├─ \"找 XX 分类下的书\"\n│   → search_by_category\n│\n├─ \"查看书籍详情\"\n│   → get_book\n│\n├─ \"这本书我都划了哪些线？\" / \"看看《XX》的批注/书签\"\n│   → get_notes（传 book_id 或 title；own:0 可连他人共享的批注一起看）\n│\n├─ \"更新/补全《XX》的封面、简介、标签信息\"（自动从网上获取）\n│   → book_fill（需要管理员权限，传入 book_id 数组）\n│\n├─ \"手动修改《XX》的标签/分类/书名等字段\"\n│   → 先 search_books 确认 book_id → 再 edit_book\n│\n├─ \"把修改后的元数据也写入电子书文件本身\" / \"同步元数据到文件\"\n│   → save_meta_to_file（仅 epub/azw3/pdf，需管理员或书籍所有者权限）\n│\n├─ \"把我在微信读书上的划线/想法导入这本书\" / \"导入第三方批注\"\n│   → 先确认目标书是 EPUB 格式，再用 push_notes（先 dry_run:true 预览，用户确认后再 dry_run:false 提交）\n│   → 微信读书上有新批注后再次同步：直接把全量列表再传一遍 push_notes 即可，会自动判重，不用先清空\n│\n├─ \"撤销/重置这本书导入的批注\" / \"刚才导入错了，重新来一遍\"\n│   → clear_imported_notes（只影响当前用户自己通过 push_notes 导入的批注），然后重新调 push_notes\n│\n\n├─ \"把书发给我的 Kindle / 发到邮箱\"\n│   → mailto（发邮箱附件）\n│\n├─ \"把书发到我的多看/掌阅/BOOX 设备\"\n│   → send_to_device（需设备在同一局域网并开启 WiFi 接收）\n│\n├─ \"上传这本书\" / \"添加实体书\"\n│   → book_upload（电子书文件）\n│   → book_add_by_isbn（实体书 ISBN）\n│\n├─ \"这本书想读\" / \"加入待读清单\"\n│   → wants\n│\n├─ \"收藏这本书\"\n│   → favorite\n│\n├─ \"标记正在读\" / \"标记已读完\"\n│   → reading（read_state: 1 或 2）\n│   → read_done（快捷标记已读完）\n│\n├─ \"这本书读了多久？\" / \"读到哪了？\" / \"epub 版什么时候开始读的？\"\n│   → get_book_reading_stats（分格式的时长/进度/开始完成时间）\n│\n├─ \"帮我补记这本书的阅读时长\" / \"标记这本书 XX 格式已读完\"（无自动心跳的场景）\n│   → update_book_reading_stats\n│\n├─ \"补录某天的阅读时间\" / \"昨天晚上读了 45 分钟没记上\"（v4.3.0+）\n│   → set_reading_time（按日期覆盖）；查看用 get_reading_time；撤销用 delete_reading_time\n│\n├─ \"我有哪些书单？\" / \"把这本书加到《XX》书单\" / \"新建一个书单\"（v4.3.0+）\n│   → list_my_booklists / booklist_add_books / create_booklist\n│   → 看书单里的书：get_booklist；浏览大家的公开书单：list_public_booklists\n│   → 这本书已经在哪些书单里：get_book_booklists\n│\n└─ \"有哪些分类？\" / \"XX 作者有哪些书？\"\n    → categories / list_authors / get_author_books\n```\n\n### TTS 场景\n\n```\n用户请求\n│\n├─ \"配置 TTS API\" / \"设置 MiMo API Key\"\n│   → tts_save_config\n│\n├─ \"测试 API 能不能用\" / \"连接正常吗\"\n│   → tts_test_connection\n│\n├─ \"把这本书转成有声书\" / \"开始转换\"\n│   → tts_convert（需先有配置或直接传参）\n│\n├─ \"转换到哪了\" / \"进度怎么样\"\n│   → tts_progress\n│\n├─ \"上传克隆音色\" / \"我想用自己的声音\"\n│   → tts_clone_upload\n│\n├─ \"有哪些克隆音色\" / \"看看上传的音色\"\n│   → tts_clone_list\n│\n├─ \"删除克隆音色\" / \"不要这个音色了\"\n│   → tts_clone_delete\n│\n├─ \"试听克隆音色\" / \"下载克隆音频\"\n│   → tts_clone_audio\n│\n├─ \"有哪些提示词\" / \"保存的音色描述\"\n│   → tts_prompt_list\n│\n├─ \"保存这个音色描述\" / \"存一个提示词\"\n│   → tts_prompt_save\n│\n└─ \"删除提示词\" / \"不要这个描述了\"\n    → tts_prompt_delete\n```\n\n---\n\n## 预置音色参考\n\nMiMo TTS 类型（`api_type=chat_completions`）内置 9 个预置音色：\n\n| ID | 名称 | 语言 | 性别 |\n|----|------|------|------|\n| `mimo_default` | MiMo-默认 | 中文 | 女 |\n| `冰糖` | 冰糖 | 中文 | 女 |\n| `茉莉` | 茉莉 | 中文 | 女 |\n| `苏打` | 苏打 | 中文 | 男 |\n| `白桦` | 白桦 | 中文 | 男 |\n| `Mia` | Mia | 英文 | 女 |\n| `Chloe` | Chloe | 英文 | 女 |\n| `Milo` | Milo | 英文 | 男 |\n| `Dean` | Dean | 英文 | 男 |\n\n---\n\n## 错误处理规范\n\n| `err` 值 | 含义 | 建议处理 |\n|----------|------|----------|\n| `\"ok\"` | 操作成功 | 展示结果 |\n| `\"user.need_login\"` | 未登录或登录态过期 | 脚本自动重登录，仍失败则检查环境变量 |\n| `\"permission\"` | 无权限 | 说明当前账号权限不足，需管理员协助 |\n| `\"params.book.invalid\"` | 书籍不存在 | 建议用 `search_books` 重新确认 book_id |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式（或找不到 EPUB 文件） | `push_notes` 专属：提示用户该书无法导入批注，仅支持 EPUB |\n| `\"sync.import.failed\"` | `push_notes` 批注定位流程整体失败 | 与单条 `results[].status:\"error\"` 不同，是整批请求都没有结果，稍后重试或检查书籍文件是否损坏 |\n| `\"task.running\"` | 后台有任务在运行 | 等待当前任务完成后重试 |\n| `\"book.notfound\"` | ISBN 对应的书籍未在网上找到 | 换其他数据源或手动添加 |\n| `\"connection.failed\"` | 无法连接到设备 | 检查设备 IP 和 WiFi 接收功能是否开启 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式 | 提示用户该书无法同步元数据到文件 |\n| `\"tts.converting\"` | TTS 转换任务进行中 | 等待完成后重试 |\n| `\"tts.no_config\"` | 未配置 TTS API | 先调用 `tts_save_config` |\n| `\"clone.too_large\"` | 克隆音色文件超限 | 提示用户裁剪音频至 7MB 内 |\n| `\"clone.invalid_format\"` | 克隆音色格式不支持 | 仅支持 MP3/WAV |\n| `\"clone.exists\"` | 克隆音色名称重复 | 换名或先删除旧的 |\n\n---\n\n## 注意事项\n\n1. **认证**：每次调用前脚本会自动登录，无需手动管理 Cookie；若未配置环境变量，脚本立即报错退出。\n2. **book_id**：书籍的唯一整数标识符，可通过 `search_books` 或 `get_book` 获取。\n3. **book_fill 异步性**：联网填充任务在后台运行，调用后立即返回；可通过 `get_book` 查看更新结果。\n4. **edit_book 标签替换**：`tags` 参数会**完整替换**原有标签，如需追加请先 `get_book` 获取现有标签再合并传入。\n5. **send_to_device 限制**：仅支持本地临时推送，不支持通过服务器中转到远程设备。\n6. **在线数据源**：`book_fill` 依赖豆瓣（douban）、百科（baike）等在线源，网络不可用或书籍较冷门时可能无结果。\n7. **批量 book_fill**：建议每批不超过 10 本，避免触发后台任务冲突（`task.running` 错误）。\n8. **TTS 管理员权限**：所有 TTS 接口均需要管理员权限，普通用户无法使用。\n9. **TTS 异步转换**：`tts_convert` 启动后台任务后立即返回，需用 `tts_progress` 轮询进度。\n10. **TTS 断点续传**：重复转换同一本书时，自动跳过已存在的 WAV 文件（≥44 字节），中断后可继续。\n11. **TTS 音频输出**：转换完成后，音频输出到 `/audio/{book_id}` 页面播放，也可通过 Web 界面访问。\n12. **TTS 克隆音色限制**：MP3/WAV ≤ 7MB；上传后自动切换 `mimo-v2.5-tts-voiceclone` 模型。\n13. **TTS 提示词存储**：提示词保存在服务端 `voice_prompts.json`，跨浏览器共享，不依赖本地存储。\n14. **TTS API Key 加密**：API Key 经 PBKDF2-SHA256 + 流加密保存，密钥文件权限 0o600。\n15. **TTS 模型锁定**：MiMo TTS 类型下模型 ID 固定为 `mimo-v2.5-tts`，不可修改；`audio_speech` 和 `custom` 类型可自由修改。\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn7efqfkfz4afhzzg8xd9bbcdh82drav\",\n  \"slug\": \"mybooks\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1789962411007\n}\n\nFile v1.0.6:skill-card.md\n\n## Description:\n\nMyBooks helps an agent manage a personal book library by searching and browsing books, viewing statistics, editing metadata, managing reading state and notes, uploading books, and using MiMo TTS audiobook features through a user-configured MyBooks server.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[poxenstudio](https://clawhub.ai/user/poxenstudio)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to operate their own MyBooks library from an agent session, including catalog search, metadata updates, reading progress management, note import, book upload, and TTS audiobook workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill uses MyBooks credentials and can mutate library data on the configured server.\n\nMitigation: Install only for trusted MyBooks servers, pass credentials through session-scoped environment variables or a dedicated secret manager, and review mutating actions before execution.\n\nRisk: TTS workflows may send book text, voice samples, or TTS provider credentials through the configured MyBooks server to the selected TTS service.\n\nMitigation: Use TTS only with trusted servers and providers, avoid real API keys in shared shells or logs, and avoid converting sensitive books or voice samples unless the transfer is acceptable.\n\nRisk: Book and voice-sample upload tools can read local files explicitly named by the user and upload them to MYBOOKS_HOST.\n\nMitigation: Upload only user-approved ebook, MP3, or WAV paths and confirm the destination host before sending files.\n\nRisk: Plain HTTP can expose credentials or content unless restricted to local or private networks.\n\nMitigation: Use HTTPS for public hosts; keep plain HTTP limited to localhost or LAN unless the user knowingly enables the documented override.\n\n## Reference(s):\n\n- [MyBooks homepage](https://www.mybooks.top)\n- [ClawHub skill page](https://clawhub.ai/poxenstudio/skills/mybooks)\n- [ClawHub publisher profile](https://clawhub.ai/user/poxenstudio)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell commands and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires python3 plus MYBOOKS_HOST, MYBOOKS_USER, and MYBOOKS_PASSWORD environment variables.]\n\n## Skill Version(s):\n\n1.0.6 (source: server release 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 v1.0.6:skill.json\n\n{\n  \"name\": \"MyBooks\",\n  \"license\": \"MIT-0\"\n}\n\nArchive v1.0.5: 5 files, 29398 bytes\n\nFiles: scripts/mybooks_api.py (46427b), skill-card.md (2637b), skill.json (46b), SKILL.md (56654b), _meta.json (126b)\n\nFile v1.0.5:SKILL.md\n\n---\nname: mybooks\nhomepage: https://www.mybooks.top\nallowed-tools: Bash(python3:*)\nmetadata: {\"clawdbot\":{},\"openclaw\":{\"requires\":{\"bins\":[\"python3\"],\"env\":[\"MYBOOKS_HOST\",\"MYBOOKS_USER\",\"MYBOOKS_PASSWORD\"]}}}\ndescription: \"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取原始数据）,以及MiMo TTS有声书功能（配置TTS API、EPUB转有声书、查询转换进度、克隆音色与语音提示词管理，需管理员权限）等\"\n---\n\n# MyBooks\n\n## Requirements\n```bash\n# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'\n```\n\n> **安全提示**：请勿将凭据写入共享或全局配置文件（如 `~/.openclaw/.env`），以避免凭据被其他 agent 或进程意外读取。建议通过会话级环境变量或专用密钥管理工具传入凭据。\n\n## 通用响应格式与认证方式\n\n### 通用 JSON 响应结构\n所有 API 均返回如下格式：\n```json\n{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}\n```\n\n常见错误码：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"ok\"` | 操作成功 |\n| `\"user.need_login\"` | 未登录或登录态已过期 |\n| `\"permission\"` | 无权限执行该操作 |\n| `\"params.invalid\"` | 请求参数错误 |\n| `\"params.book.invalid\"` | 书籍不存在或 ID 错误 |\n| `\"task.running\"` | 后台任务正在进行中，稍后重试 |\n| `\"tts.converting\"` | TTS 转换任务正在运行 |\n| `\"tts.no_config\"` | 未配置 TTS API |\n| `\"clone.exists\"` | 克隆音色名称已存在 |\n| `\"clone.not_found\"` | 克隆音色不存在 |\n| `\"clone.too_large\"` | 文件超过 7MB 限制 |\n| `\"clone.invalid_format\"` | 仅支持 MP3/WAV 格式 |\n| `\"prompt.exists\"` | 提示词名称已存在 |\n| `\"prompt.not_found\"` | 提示词不存在 |\n\n### 认证方式\n- 脚本通过 `MYBOOKS_USER` / `MYBOOKS_PASSWORD` 环境变量自动调用 `/api/user/sign_in` 完成登录\n- 服务端通过 **Secure Cookie**（`user_id` + `lt`）维持会话\n- 若响应中出现 `err=user.need_login`，脚本会自动重新登录后重试一次；仍失败则报错退出\n- **必须**在调用前配置 `MYBOOKS_HOST`、`MYBOOKS_USER`、`MYBOOKS_PASSWORD` 三个环境变量，否则脚本直接报错退出\n\n---\n\n## 工具列表\n\n### `get_user_info` — 用户信息与系统统计\n\n**使用场景**：获取当前登录用户信息，同时返回书库总体统计（书籍数、作者数等）\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_user_info '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"user\": { \"is_login\": true, \"nickname\": \"管理员\", \"is_admin\": true },\n  \"sys\": { \"books\": 1280, \"authors\": 342, \"tags\": 86, \"mtime\": \"2025-03-01\" }\n}\n```\n\n---\n\n### `library_stats` — 书库统计\n\n**使用场景**：获取书库详细统计，包括电子书/实体书数量及本月新增\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py library_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_books\": 1280,\n    \"ebook_count\": 1210,\n    \"physical_count\": 70,\n    \"month_ebook_count\": 12,\n    \"month_physical_count\": 3,\n    \"current_year\": 2025,\n    \"current_month\": 3\n  }\n}\n```\n\n---\n\n### `reading_stats` — 阅读统计\n\n**使用场景**：获取当前用户的阅读统计（在读/已读数量、本月数据）及当前在读书单\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py reading_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_reading\": 5,\n    \"total_read_done\": 42,\n    \"month_reading\": 2,\n    \"month_read_done\": 3\n  },\n  \"current_reading_books\": [ /* 书籍对象列表 */ ],\n  \"month_read_done_books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_books` — 搜索书籍\n\n**使用场景**：\n- 按书名或作者名搜索，支持简繁体自动转换\n- \"有没有余华的书？\" / \"找一下《三体》\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `name` | string | ✅ | — | 搜索关键词（书名或作者名） |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"name\":\"三体\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"title\": \"搜索：三体\",\n  \"total\": 3,\n  \"books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_by_category` — 按分类查询书籍\n\n**使用场景**：查询指定分类下的所有书籍（基于自定义 `#category` 字段）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `category` | string | ✅ | — | 分类名称，如 \"科幻\" |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_by_category '{\"category\":\"科幻\"}'\n```\n\n---\n\n### `get_book` — 书籍详情\n\n**使用场景**：获取指定书籍的完整信息，包括元数据、可用格式、封面、阅读状态等\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book\": {\n    \"id\": 42,\n    \"title\": \"活着\",\n    \"authors\": [\"余华\"],\n    \"tags\": [\"小说\", \"中国文学\"],\n    \"publisher\": \"作家出版社\",\n    \"isbn\": \"9787506365437\",\n    \"pubdate\": \"2012-08-01\",\n    \"rating\": 9,\n    \"comments\": \"《活着》讲述了...\",\n    \"category\": \"现代文学\",\n    \"available_formats\": [\"epub\", \"pdf\"],\n    \"files\": [\n      {\n        \"format\": \"EPUB\",\n        \"size\": 1330899,\n        \"href\": \"/api/book/42.EPUB\"\n      }\n    ],\n    \"cover_url\": \"/get/cover/42\",\n    \"series\": \"余华作品集\",\n    \"series_index\": 1,\n    \"state\": {\n      \"favorite\": 0,\n      \"wants\": 0,\n      \"read_state\": 1\n    },\n    \"tags\": [\"小说\", \"中国文学\"]\n  },\n  \"kindle_sender\": \"sender@example.com\"\n}\n```\n\n---\n\n### `edit_book` — 编辑书籍元数据\n\n**使用场景**：\n- 手动修改书名、作者、标签、分类等字段\n- 修改实体书数量或类型\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `title` | string | ❌ | 书名 |\n| `authors` | array | ❌ | 作者列表，如 `[\"余华\"]` |\n| `tags` | array | ❌ | 标签列表，**替换**原有标签（想追加需先 `get_book` 获取现有标签再合并） |\n| `publisher` | string | ❌ | 出版社 |\n| `isbn` | string | ❌ | ISBN 编号 |\n| `series` | string | ❌ | 系列/丛书名 |\n| `series_index` | int | ❌ | 系列中的顺序号 |\n| `rating` | number | ❌ | 评分（0–10） |\n| `languages` | array | ❌ | 语言代码列表，如 `[\"zho\"]`（中文）、`[\"eng\"]`（英文）、`[\"zha\"]`（繁体中文） |\n| `pubdate` | string | ❌ | 出版日期，格式：`\"2024-01-15\"` / `\"2024-01\"` / `\"2024\"` |\n| `comments` | string | ❌ | 书籍简介，支持 HTML，请勿将 `<>` 转义为 `&lt;&gt;` |\n| `category` | string | ❌ | 自定义分类（最长 80 字符；传 `\"清除\"` 或 `\"clear\"` 清空分类） |\n| `book_count` | int | ❌ | 实体书数量（需配合 `book_type: 1` 使用） |\n| `book_type` | int | ❌ | 书籍类型：`0`=电子书，`1`=实体书 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py edit_book '{\"book_id\":42,\"tags\":[\"小说\",\"中国文学\"],\"category\":\"现代文学\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"更新成功\", \"books\": [42] }\n```\n\n---\n\n### `push_notes` — 导入第三方批注（微信读书等）\n\n**使用场景**：把从其他阅读 App（目前是微信读书）读到的划线/想法，通过服务端全文检索定位到 MyBooks 书库里对应 EPUB 书籍的正文位置，写入这本书的阅读记录。详细方案见 `plan/WeChatReading_Annotation_Import_Plan.md`。\n\n**前提**：目标书籍必须已经在 MyBooks 书库里，且**必须有 EPUB 格式**（定位算法依赖 EPUB 的正文结构，其它格式不支持）。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID（须为 EPUB 格式） |\n| `anchors` | array | ✅ | — | 待导入的批注列表，见下 |\n| `anchors[].id` | string | ✅ | — | 来源系统里的稳定 ID（如微信读书的 `bookmarkId`/`reviewId`），用于生成幂等的记录 ID——同样的 `anchors` 重复调用不会重复导入 |\n| `anchors[].text` | string | ❌ | — | 划线/引用的原文，用于全文检索定位；不传则视为\"无原文锚点\"（章节点评/整本书评），会退化为\"挂在章节开头\"的书签 |\n| `anchors[].chapterHint` | string | ❌ | — | 来源系统里的章节标题，`text` 未提供时用于定位章节起始位置 |\n| `anchors[].note` | string | ❌ | — | 用户写的想法/点评正文 |\n| `anchors[].color` | string | ❌ | `\"yellow\"` | 高亮颜色 |\n| `anchors[].style` | string | ❌ | `\"highlight\"` | `highlight`/`underline`/`squiggly` |\n| `anchors[].createdAt` | int | ❌ | 当前时间 | 来源系统里的创建时间（毫秒时间戳） |\n| `anchors[].source` | string | ❌ | `\"wxread\"` | 来源标记 |\n| `on_ambiguous` | string | ❌ | `\"error\"` | 原文在书里检索到多处命中时的处理：`\"error\"`=不写入、标记为歧义待复核；`\"first_match\"`=取第一个命中位置写入 |\n| `dry_run` | bool | ❌ | `true` | `true`=只做检索定位、返回预览报告，不写入；`false`=同时写入。**务必先用 `dry_run:true` 看一遍报告、跟用户确认后再用 `dry_run:false` 提交，不要一步到位直接写入** |\n| `force` | bool | ❌ | `false` | 重复导入默认会**自动判重**：某条 `anchors[].id` 如果 `text`/`chapterHint` 跟上次导入时一样，直接复用上次的定位结果，不会重新跑检索（响应里对应条目会带 `\"reused\": true`）。`force:true` 会跳过判重、强制重新定位所有条目——只有书籍文件本身被替换过这种场景才需要，**日常重复同步不要传这个参数**，判重本身就是为了处理\"微信读书上有新批注后再次同步\"这种情况设计的 |\n\n**再次同步（判重）说明**：微信读书没有增量接口，每次都会拿到全量划线/想法列表。直接把全量列表再传一遍给 `push_notes` 是安全且推荐的做法——服务端会按 `anchors[].id` 匹配上次导入的记录，`text`/`chapterHint` 没变的条目不会重新定位（省时间，也避免同一条批注每次定位到略有不同的位置），只有新增的、或者原文本身变了的条目才会真正重新检索。如果只是想法/评论内容改了但划线原文没变，也会被识别为\"位置没变、内容更新\"，只更新想法文本，不重新定位。\n\n**执行脚本**：\n```bash\n# 第一步：预览（默认 dry_run:true），不会写入任何数据\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ]\n}'\n\n# 第二步：跟用户确认预览报告无误后，正式写入\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ],\n  \"dry_run\": false\n}'\n```\n\n**响应示例**（预览，`dry_run:true`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": true,\n  \"results\": [\n    { \"id\": \"wx-bm-1001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\", \"matchCount\": 1 },\n    { \"id\": \"wx-review-2001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/8!/4)\", \"degraded\": \"chapter_start\" }\n  ]\n}\n```\n\n**响应示例**（提交，`dry_run:false`，额外带 `pushed`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": false,\n  \"results\": [ /* 同上 */ ],\n  \"pushed\": { \"notes\": [ /* 写入后的最终记录，字段与 GET /api/sync 一致 */ ] }\n}\n```\n\n**`results[].status` 取值**：\n| 值 | 含义 | 建议处理 |\n|----|------|----------|\n| `\"ok\"` | 定位成功，`cfi` 有值 | 展示给用户确认；`degraded:\"chapter_start\"` 表示这是退化的章节级书签，不是精确定位，需要提示用户区分 |\n| `\"no_match\"` | 原文在书里没有检索到 | 大概率两边不是同一版本的书，或原文被来源系统二次编辑过；列入失败清单，不会写入 |\n| `\"ambiguous\"` | 原文命中了多处（`matchCount` > 1），且 `on_ambiguous=\"error\"` | 列入歧义清单，需要人工复核；不会写入 |\n| `\"error\"` | 该条内部处理出错（如 CFI 生成失败） | 列入失败清单，不会写入 |\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式，或找不到 EPUB 文件 |\n| `\"sync.import.failed\"` | 服务端批注定位流程整体失败（如 CFI 子进程异常）——不同于单条 `status:\"error\"`，这是整批请求都没有结果 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `get_notes` — 查询书籍批注\n\n**使用场景**：查看某本书已有的划线/批注/书签（通过 `GET /api/sync` 实现，`type=notes`）。\n\n- \"这本书我都划了哪些线？\" / \"看看《活着》的批注\"\n- 确认 `push_notes` 导入结果，或在 `clear_imported_notes` 前先看一眼现有批注\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ❌ | — | 书籍 ID；与 `title` 二选一，优先生效 |\n| `title` | string | ❌ | — | 书名；不传 `book_id` 时用于搜索定位书籍，仅精确匹配到唯一一本书才会继续查询——命中多本时返回 `candidates` 列表，需要调用方明确选择后改传 `book_id` |\n| `own` | int | ❌ | `1` | `1`=只返回当前用户自己的批注；`0`=额外并入其他用户在这本书上共享的批注（受服务端 `ENABLE_SHARED_NOTES` 开关约束） |\n\n**执行脚本**：\n```bash\n# 按 book_id 查询自己的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"book_id\":42}'\n\n# 按书名查询，并包含其他用户共享的批注\n<skill-installation-path>/scripts/mybooks_api.py get_notes '{\"title\":\"活着\",\"own\":0}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"books\": null,\n  \"configs\": null,\n  \"notes\": [\n    {\n      \"id\": \"wxread-wx-bm-1001\",\n      \"book_hash\": \"cloud-42-epub\",\n      \"type\": \"annotation\",\n      \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\",\n      \"text\": \"他手里拿着两大块磁铁\",\n      \"note\": \"开篇的魔幻现实主义笔法\",\n      \"style\": \"highlight\",\n      \"color\": \"yellow\",\n      \"updated_at\": 1755600000000,\n      \"deleted_at\": null\n    }\n  ]\n}\n```\n**`notes[]` 每条记录的字段**：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `id` | string | 记录唯一 ID；`push_notes` 导入的批注固定带 `wxread-` 前缀 |\n| `book_hash` | string | 所属书籍的 hash（云端书籍固定为 `cloud-<book_id>-epub`） |\n| `type` | string | `\"bookmark\"`（书签）/ `\"annotation\"`（划线+想法）/ `\"excerpt\"`（摘录） |\n| `cfi` | string | 该批注在 EPUB 正文里的定位（canonical CFI） |\n| `text` | string | 划线/摘录的原文，书签类可能为空 |\n| `note` | string | 用户写的想法/点评正文 |\n| `style` | string | `\"highlight\"` / `\"underline\"` / `\"squiggly\"` |\n| `color` | string | 高亮颜色，如 `\"yellow\"`，也可能是十六进制色值 |\n| `global` | bool | 可选；为 `true` 表示对本章节内该 `text` 的所有出现位置生效 |\n| `page` | number | 可选；分页/固定排版格式下的页码 |\n| `updated_at` | number | 最近一次更新的毫秒时间戳，用于判断是否新增/变更 |\n| `deleted_at` | number/null | 墓碑时间戳；非 `null` 表示该批注已被删除，仍会出现在结果里但应视为已删除 |\n\n按书名查询时命中多本书会返回：\n```json\n{ \"status\": \"error\", \"message\": \"Multiple books matched this title; specify book_id\", \"candidates\": [ {\"id\": 42, \"title\": \"活着\", \"authors\": [\"余华\"]}, ... ] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `clear_imported_notes` — 清空某本书已导入的批注（重置用，非日常操作）\n\n**使用场景**：撤销/重置某本书通过 `push_notes` 导入的全部批注——比如导入用错了数据、或者 `on_ambiguous:\"first_match\"` 选错了位置，用户明确要求\"重新导入一遍\"。**不要**把这个当成处理\"再次同步\"的常规手段——`push_notes` 本身已经会自动判重（见上），日常重复同步应该直接再调一次 `push_notes`，不需要先清空。\n\n**范围**：只会清除当前登录用户通过 `push_notes` 导入的批注（`id` 带 `wxread-` 前缀的），不影响这本书上其他人的批注，也不影响用户自己在 MyReader 里手动做的批注。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py clear_imported_notes '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 42, \"book_hash\": \"cloud-42-epub\", \"cleared\": 5 }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"sync.disabled\"` | 服务端数据同步功能未启用 |\n\n---\n\n### `book_fill` — 自动联网填充书籍信息\n\n**使用场景**：\n- \"帮我更新《XX》的封面和简介\"\n- \"书库里有很多书信息不完整，帮我补全\"\n- 批量补全多本书的封面、简介、出版社、出版日期、标签等\n\n**权限**：需要管理员权限\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `idlist` | array 或 `\"all\"` | ✅ | 书籍 ID 数组，或 `\"all\"` 表示全库处理 |\n\n**注意**：任务在后台异步执行，调用后立即返回；书名**默认保留原值不修改**（防止错误覆盖）\n\n**执行脚本**：\n```bash\n# 更新单本书\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42]}'\n\n# 批量更新\n<skill-installation-path>/scripts/mybooks_api.py book_fill '{\"idlist\":[42,43,44]}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"任务启动成功！请耐心等待，稍后再来刷新页面\" }\n```\n\n---\n\n### `save_meta_to_file` — 将元数据保存到电子书文件\n\n**使用场景**：\n- 在书库中修改了书名/作者/简介/标签等元数据后，希望这些信息也写入电子书文件本身（而不只是存在书库数据库里）\n- 仅支持 epub / azw3 / pdf 格式；其余格式（如 mobi、txt）不受影响\n\n**权限**：需要登录，且为管理员或该书籍的所有者\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `fmt` | string | ❌ | 仅同步指定格式（`epub`/`azw3`/`pdf`），省略则同步所有支持的格式 |\n\n**执行脚本**：\n```bash\n# 同步所有支持的格式\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42}'\n\n# 仅同步 epub\n<skill-installation-path>/scripts/mybooks_api.py save_meta_to_file '{\"book_id\":42,\"fmt\":\"epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"成功将元数据同步到文件：EPUB\", \"success_formats\": [\"EPUB\"], \"failed_formats\": [] }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"user.no_permission\"` | 非管理员或非书籍所有者 |\n| `\"book.not_found\"` | 书籍不存在 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式（或没有指定的 `fmt`） |\n| `\"book.meta.not_found\"` | 无法获取书籍元数据 |\n| `\"save.failed\"` | 所有格式均同步失败（返回中含 `failed_formats`） |\n\n---\n\n### `mailto` — 发送书籍到邮箱\n\n**使用场景**：将书籍以附件形式发送到指定邮箱（如 Kindle 邮箱）\n\n**格式优先级**：epub > azw3 > pdf > mobi > txt（取首个存在的格式）\n\n**权限**：需要登录，且账号需有推送权限（`can_push`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `email` | string | ✅ | 目标邮箱地址（可以是 Kindle 邮箱） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py mailto '{\"book_id\":42,\"email\":\"user@kindle.com\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"后台正在推送，稍后可以刷新页面，在通知消息中查看结果。\" }\n```\n\n---\n\n### `send_to_device` — 发送书籍到阅读器设备\n\n**使用场景**：通过 WiFi 将书籍直接推送到阅读器设备（仅支持当前网络内的临时设备）\n\n**支持的设备类型（`device_type`）**：\n\n| 类型 | 设备 | 传输方式 | `device_url` 说明 |\n|------|------|----------|-------------------|\n| `kindle` | Kindle 系列 | 邮件发送 | 不需填写，改用 `mailbox` 参数 |\n| `duokan` | 多看阅读器 | HTTP WiFi 上传 | 设备局域网 IP，如 `192.168.1.100` |\n| `ireader` | 掌阅 iReader | HTTP WiFi 上传 | 设备局域网 IP |\n| `hanwang` | 汉王电纸书 | HTTP WiFi 上传 | 设备局域网 IP |\n| `boox` | 文石 BOOX | HTTP WiFi 上传 | 设备局域网 IP |\n| `dangdang` | 当当阅读器 | HTTP WiFi 上传 | 设备局域网 IP |\n\n**WiFi 传输格式优先级**：epub > azw3 > pdf > txt\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `device_type` | string | ✅ | 设备类型（见上表） |\n| `device_url` | string | kindle 以外必填 | 设备局域网 IP 或地址（如 `\"192.168.1.100\"` 或 `\"http://192.168.1.100:80\"`） |\n| `mailbox` | string | kindle 时必填 | Kindle 邮箱地址 |\n\n**执行脚本**：\n```bash\n# 发送到多看设备\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"duokan\",\"device_url\":\"192.168.1.100\"}'\n\n# 发送到 Kindle（通过邮件）\n<skill-installation-path>/scripts/mybooks_api.py send_to_device \\\n  '{\"book_id\":42,\"device_type\":\"kindle\",\"mailbox\":\"mykindle@kindle.cn\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"书籍发送成功\" }\n```\n\n---\n\n### `categories` — 查看分类信息\n\n**使用场景**：获取当前书库中所有自定义分类及各分类下的书籍数量\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py categories '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"categories\": [\n    { \"name\": \"现代文学\", \"count\": 128 },\n    { \"name\": \"科幻\", \"count\": 56 }\n  ]\n}\n```\n\n---\n\n### `list_authors` — 查看作者列表\n\n**使用场景**：获取所有有在库书籍的作者及其书籍数量\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `show` | string | ❌ | 传 `\"all\"` 显示全部，否则返回前 N 条 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_authors '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"meta\": \"author\",\n  \"title\": \"全部作者\",\n  \"items\": [\n    { \"name\": \"余华\", \"count\": 5 },\n    { \"name\": \"刘慈欣\", \"count\": 8 }\n  ],\n  \"total\": 342\n}\n```\n\n---\n\n### `get_author_books` — 查询作者的在库书籍\n\n**使用场景**：获取指定作者在书库中的所有书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `author_name` | string | ✅ | — | 作者名 |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_author_books '{\"author_name\":\"余华\"}'\n```\n\n---\n\n### `book_upload` — 上传电子书\n\n**使用场景**：上传本地电子书文件到书库，支持 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx 等格式\n\n**权限**：需要登录，且账号需有上传权限（`can_upload`）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `file_path` | string | ✅ | 本地文件的绝对路径 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_upload '{\"file_path\":\"/path/to/book.epub\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"book_id\": 123 }\n```\n\n---\n\n### `book_add_by_isbn` — 通过 ISBN 添加实体书\n\n**使用场景**：\n- 扫描实体书的 ISBN 条码后，将书入库\n- 若该 ISBN 书籍已存在，则自动将实体书数量 +1\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `isbn` | string | ✅ | ISBN 编号，如 `\"9787020024759\"` |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py book_add_by_isbn '{\"isbn\":\"9787020024759\"}'\n```\n\n**响应示例**（新增）：\n```json\n{ \"err\": \"ok\", \"msg\": \"图书添加成功\", \"book_id\": 456 }\n```\n\n**响应示例**（已存在，更新数量）：\n```json\n{ \"err\": \"ok\", \"msg\": \"实体书数量已更新，当前数量：2\", \"book_id\": 123 }\n```\n\n---\n\n### `wants` — 标记/取消想读\n\n**使用场景**：将书籍加入/移出\"想读（待读）\"清单\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `wants` | bool | ❌ | `true` | `true`=标记想读，`false`=取消 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py wants '{\"book_id\":42}'\n```\n\n---\n\n### `list_wants` — 想读清单\n\n**使用场景**：获取当前用户的\"想读（待读）\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_wants '{}'\n```\n\n---\n\n### `favorite` — 收藏/取消收藏\n\n**使用场景**：收藏或取消收藏指定书籍\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID |\n| `favorite` | bool | ❌ | `true` | `true`=收藏，`false`=取消收藏 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py favorite '{\"book_id\":42}'\n```\n\n---\n\n### `list_favorites` — 收藏列表\n\n**使用场景**：获取当前用户的所有收藏书籍\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_favorites '{}'\n```\n\n---\n\n### `reading` — 设置阅读状态\n\n**使用场景**：标记某本书的阅读状态（未读/在读/已读完）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `read_state` | int | ✅ | 阅读状态：`0`=未读，`1`=在读，`2`=已读完 |\n\n**执行脚本**：\n```bash\n# 标记为在读\n<skill-installation-path>/scripts/mybooks_api.py reading '{\"book_id\":42,\"read_state\":1}'\n```\n\n---\n\n### `list_reading` — 在读书单\n\n**使用场景**：获取当前用户的\"正在阅读\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_reading '{}'\n```\n\n---\n\n### `read_done` — 标记已读完\n\n**使用场景**：快捷将某本书标记为已读完（即 `reading` 工具中 `read_state=2` 的简化版）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py read_done '{\"book_id\":42}'\n```\n\n---\n\n### `list_read_done` — 已读清单\n\n**使用场景**：获取当前用户的\"已读完\"书籍列表\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_read_done '{}'\n```\n\n---\n\n### `get_book_reading_stats` — 分格式阅读时长/进度统计\n\n**使用场景**：查看某本书**分格式**（epub/pdf/mobi 等）的阅读时长、阅读进度、开始/完成阅读的时间、开始阅读的次数。与 `reading`/`read_done` 的整本书阅读状态不同，这个接口是\"格式\"级别的细粒度数据。\n\n- \"这本书我读了多久？\" / \"我读到哪了？\" / \"这本书 epub 版我什么时候开始读的？\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book_reading_stats '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": [\n    {\n      \"format\": \"epub\",\n      \"state\": 0,\n      \"total_seconds\": 5421,\n      \"progress_current\": 3,\n      \"progress_total\": 488,\n      \"progress_percent\": 0.61,\n      \"start_time\": \"2026-08-20T10:00:00Z\",\n      \"finish_time\": null,\n      \"start_count\": 1,\n      \"update_time\": \"2026-08-27T09:12:00Z\"\n    }\n  ]\n}\n```\n\n`state`：`0`=在读，`1`=已完成。没有任何格式统计数据时 `stats` 为空数组 `[]`（比如从未通过 MyReader/网页阅读器打开过这本书）。\n\n---\n\n### `update_book_reading_stats` — 手动更新阅读时长/进度\n\n**使用场景**：手动补记或纠正某本书某个格式的阅读数据——导入历史阅读记录、用户口述\"我刚读完这本书的 PDF 版\"、或者网页阅读器等没有自动进度上报的场景。日常通过 MyReader 阅读的书籍会自动统计，**不需要**调用这个工具。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `format` | string | ✅ | 电子书格式，如 `epub`/`pdf`/`mobi`/`azw3`/`txt` |\n| `duration_seconds` | int | ❌ | 累加到该格式累计阅读时长（是增量，不是覆盖总值） |\n| `progress` | array | ❌ | `[当前, 总数]`，如 `[120, 488]`；达到约 100% 会自动标记为已完成 |\n| `start_time` | string | ❌ | ISO8601 字符串或时间戳；显式开启新一轮阅读（开始次数 +1） |\n| `finish_time` | string | ❌ | ISO8601 字符串或时间戳；显式标记本轮阅读已完成 |\n| `state` | int | ❌ | `0`=在读，`1`=已完成，效果与传 `finish_time` 类似（不需要同时传两个） |\n\n**执行脚本**：\n```bash\n# 补记刚读的 40 分钟，并更新进度\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"pdf\",\"duration_seconds\":2400,\"progress\":[50,200]}'\n\n# 手动标记这本书的 epub 版已读完\n<skill-installation-path>/scripts/mybooks_api.py update_book_reading_stats \\\n  '{\"book_id\":42,\"format\":\"epub\",\"state\":1}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"stats\": { \"format\": \"pdf\", \"state\": 0, \"total_seconds\": 2400, \"progress_current\": 50, \"progress_total\": 200, \"progress_percent\": 25.0, \"start_time\": \"2026-08-27T09:00:00Z\", \"finish_time\": null, \"start_count\": 1, \"update_time\": \"2026-08-27T09:40:00Z\" } }\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 缺少 `format`，或 `progress`/`state` 参数格式错误 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n### `get_reading_time` / `set_reading_time` / `delete_reading_time` — 按日期补录阅读时间\n\n> **版本要求：MyBooks v4.3.0+**（旧版本服务端没有 `/api/book/<id>/reading_time`，调用会 404）。\n\n**使用场景**：某天读了书但没有通过 MyReader/网页阅读器自动计时（纸质书、其他 App 等），按**日期**补录一条手工阅读记录。每本书每天最多一条手工记录：再次 `set_reading_time` 同一天是**覆盖**（不是累加），差值会同步到当日阅读统计、该书分格式累计时长和用户总阅读时长。与 `update_book_reading_stats`（按格式累加时长/进度）不同，这里是按天的\"覆盖式\"记录。\n\n**限制**：书籍必须有电子书格式（记录会挂到已有的阅读格式，否则挂到可用格式之一）；日期不能晚于今天；`duration_seconds` 范围 0~64800（18 小时）。均需登录，只影响当前用户自己的数据。\n\n**参数**：\n\n| 工具 | 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|------|\n| 三个都有 | `book_id` | int | ✅ | 书籍 ID |\n| 三个都有 | `date` | string | ✅ | 日期，格式 `YYYY-MM-DD` |\n| `set_reading_time` | `duration_seconds` | int | ✅ | 当天该书的阅读总秒数（覆盖原手工记录） |\n| `set_reading_time` | `start_time` | string | ❌ | 开始时间（文本，如 `\"20:30\"`） |\n| `set_reading_time` | `end_time` | string | ❌ | 结束时间（文本） |\n\n**执行脚本**：\n```bash\n# 查询某天的手工记录及参考数据（自动记录的秒数、手工秒数、该书总时长）\n<skill-installation-path>/scripts/mybooks_api.py get_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n\n# 补录（或覆盖）：当天读了 45 分钟\n<skill-installation-path>/scripts/mybooks_api.py set_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\",\"duration_seconds\":2700,\"start_time\":\"20:30\",\"end_time\":\"21:15\"}'\n\n# 删除当天的手工记录（同步回退统计）\n<skill-installation-path>/scripts/mybooks_api.py delete_reading_time '{\"book_id\":42,\"date\":\"2026-09-20\"}'\n```\n\n**响应示例**：\n```json\n// get_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" }, \"date_recorded_seconds\": 600, \"manual_recorded_seconds\": 2700, \"book_total_seconds\": 8121 }\n// set_reading_time\n{ \"err\": \"ok\", \"entry\": { \"date\": \"2026-09-20\", \"duration_seconds\": 2700, \"format\": \"epub\" } }\n// delete_reading_time\n{ \"err\": \"ok\", \"deleted\": true }\n```\n`entry` 为 `null` 表示该日没有手工记录；`deleted:false` 表示本来就没有可删的记录。`entry` 的具体字段以服务端返回为准。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.invalid\"` | 日期格式错误/是未来日期、缺少或超出范围的 `duration_seconds`、书籍没有可阅读的电子书格式 |\n| `\"params.book.invalid\"` | 书籍不存在 |\n\n---\n\n## 书单工具列表\n\n> **版本要求：MyBooks v4.3.0+**（旧版本没有 `/api/booklist*` 接口）。书单（booklist）是用户自建的书籍集合，每人数量有上限，可设为公开供他人浏览、点赞。\n\n**权限规则**：浏览公开书单不需登录；创建/修改/删除书单、增删书籍、点赞需要登录，其中修改/删除/增删书籍仅限书单所有者或管理员；私有书单仅所有者/管理员可看，且不能点赞。\n\n**书单对象**（各接口 `booklist(s)` 里的元素）主要字段：`id`、`name`、`description`、`color`、`is_public`、`is_sticky`、`view_count`、`like_count`、`book_count`、`create_time`、`update_time`、`owner`（`id`/`username`/`avatar`）、`is_owner`、`liked_by_me`；列表接口另带 `cover_books`（最多 12 本的封面卡片）。\n\n| 工具 | 说明 | 参数 |\n|------|------|------|\n| `list_my_booklists` | 我的书单（需登录） | 无 |\n| `list_public_booklists` | 公开书单，分页 | `page`（默认 1）、`page_size`（默认 20，最大 50） |\n| `list_liked_booklists` | 我点赞过的书单（需登录） | 无 |\n| `get_booklist` | 书单详情 + 分页书籍（`books`、`books_total`） | `booklist_id`（必填）、`order`（`desc` 默认/`asc`，按加入时间）、`page`、`page_size`（默认 24，最大 60） |\n| `create_booklist` | 新建书单 | `name`（必填）、`description`（≤500 字）、`color`、`is_public`（默认 false） |\n| `update_booklist` | 修改书单，只改传入的字段 | `booklist_id`（必填）、`name`/`description`/`color`/`is_public` |\n| `delete_booklist` | 删除书单（**不会删除书籍本身**，删除前先跟用户确认） | `booklist_id`（必填） |\n| `booklist_add_books` | 批量加书（不存在的书自动忽略） | `booklist_id`（必填）、`book_ids`（数组，必填） |\n| `booklist_remove_book` | 移出一本书 | `booklist_id`、`book_id`（均必填） |\n| `like_booklist` | 点赞/取消点赞（切换） | `booklist_id`（必填） |\n| `get_book_booklists` | 我的书单里哪些已包含某本书（`contains_book`） | `book_id`（必填） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py list_my_booklists '{}'\n<skill-installation-path>/scripts/mybooks_api.py create_booklist '{\"name\":\"2026 科幻必读\",\"description\":\"年度科幻\",\"is_public\":true}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_add_books '{\"booklist_id\":7,\"book_ids\":[42,43]}'\n<skill-installation-path>/scripts/mybooks_api.py get_booklist '{\"booklist_id\":7,\"page\":1}'\n<skill-installation-path>/scripts/mybooks_api.py booklist_remove_book '{\"booklist_id\":7,\"book_id\":43}'\n```\n\n**响应示例**（`get_booklist`）：\n```json\n{\n  \"err\": \"ok\",\n  \"booklist\": {\n    \"id\": 7, \"name\": \"2026 科幻必读\", \"is_public\": true, \"book_count\": 2, \"like_count\": 3,\n    \"is_owner\": true, \"liked_by_me\": false,\n    \"books\": [ { \"book_id\": 42, \"title\": \"三体\", \"img\": \"...\", \"thumb\": \"...\", \"href\": \"/book/42\" } ],\n    \"books_total\": 2, \"page\": 1, \"page_size\": 24\n  }\n}\n```\n写操作响应：`create_booklist`/`update_booklist` 返回 `booklist` + `msg`；`booklist_add_books` 返回 `added`、`book_count`；`booklist_remove_book` 返回 `book_count`；`like_booklist` 返回 `liked`（当前是否已点赞）。\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"booklist.not_found\"` | 书单不存在 |\n| `\"booklist.limit_exceeded\"` | 已达每人书单数量上限 |\n| `\"permission.denied\"` | 无权限（非所有者/管理员，或私有书单） |\n| `\"params.invalid\"` | 参数错误（名称为空、未指定书籍、书不在书单中等） |\n| `\"params.book.invalid\"` | `booklist_add_books` 中的书籍全部不存在 |\n\n---\n\n## TTS 有声书工具列表（MiMo TTS，需管理员权限）\n\n> 将 EPUB 电子书转换为有声书。所有 TTS 接口均需要**管理员权限**。\n\n### `tts_save_config` — 保存 TTS API 配置\n\n**使用场景**：配置 TTS API 的连接参数（API URL、模型、密钥、类型等），保存后服务端加密存储\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `api_url` | string | ✅ | API 地址，如 `https://api.xiaomimimo.com/v1/chat/completions` |\n| `model_name` | string | ✅ | 模型 ID，MiMo TTS 类型固定为 `mimo-v2.5-tts` |\n| `api_type` | string | ✅ | API 类型：`chat_completions`（MiMo TTS）/ `audio_speech`（OpenAI 兼容）/ `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型：`bearer`（默认）/ `basic` / `custom` |\n| `voice_name` | string | ❌ | 预置音色 ID（`api_type=chat_completions` 且 `voiceType=preset` 时）或 `audio_speech` 的音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述（`voiceType=custom` 时） |\n| `clone_voice` | string | ❌ | 克隆音色名称（`voiceType=clone` 时） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_save_config '{\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"配置已保存\"\n}\n```\n\n---\n\n### `tts_test_connection` — 测试 API 连接\n\n**使用场景**：使用当前保存的配置发送一次测试请求，验证 API Key 和端点是否可用\n\n**权限**：管理员\n\n**参数**：无（使用已保存的配置）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_test_connection '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"连接成功\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"tts.no_config\"` | 未保存配置，请先调用 `tts_save_config` |\n| `\"tts.connection_failed\"` | 无法连接到 API 服务器 |\n| `\"tts.invalid_key\"` | API Key 无效 |\n\n---\n\n### `tts_convert` — 开始 EPUB 转有声书\n\n**使用场景**：将指定 EPUB 电子书转换为有声书，后台逐章合成 WAV 音频\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `api_url` | string | ✅ | API 地址 |\n| `model_name` | string | ✅ | 模型 ID |\n| `api_type` | string | ✅ | API 类型：`chat_completions` / `audio_speech` / `custom` |\n| `api_key` | string | ✅ | API 密钥 |\n| `auth_type` | string | ❌ | 认证类型（默认 `bearer`） |\n| `voice_name` | string | ❌ | 预置音色 ID 或 `audio_speech` 音色名 |\n| `voice_desc` | string | ❌ | 自定义音色描述 |\n| `clone_voice` | string | ❌ | 克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_convert '{\"book_id\":42,\"api_url\":\"https://api.xiaomimimo.com/v1/chat/completions\",\"model_name\":\"mimo-v2.5-tts\",\"api_type\":\"chat_completions\",\"api_key\":\"sk-xxx\",\"voice_name\":\"mimo_default\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"转换任务已启动\"\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"params.book.invalid\"` | 书籍不存在 |\n| `\"tts.converting\"` | 已有转换任务在运行 |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式 |\n\n---\n\n### `tts_progress` — 查询转换进度\n\n**使用场景**：查询当前 TTS 转换任务的进度、阶段和章节信息\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_progress '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"status\": \"running\",\n  \"progress\": 35,\n  \"stage\": \"converting\",\n  \"current_chapter\": 7,\n  \"total_chapters\": 20,\n  \"current_title\": \"第七章 归途\",\n  \"book_id\": 42\n}\n```\n\n**status 值**：\n| 值 | 含义 |\n|----|------|\n| `\"idle\"` | 无任务运行 |\n| `\"running\"` | 转换进行中 |\n| `\"completed\"` | 转换已完成 |\n| `\"failed\"` | 转换失败 |\n\n---\n\n### `tts_clone_upload` — 上传克隆音色\n\n**使用场景**：上传 MP3/WAV 音频样本作为克隆音色，上传后自动切换到 `mimo-v2.5-tts-voiceclone` 模型\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称（如\"旁白\"、\"男主\"） |\n| `file_path` | string | ✅ | 本地音频文件的绝对路径（MP3/WAV，≤7MB） |\n\n**限制**：\n- 格式：仅支持 `.mp3` 和 `.wav`\n- 大小：原始文件 ≤ 7MB（Base64 编码后约 9.3MB，MiMo 官方限制 Base64 ≤ 10MB）\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_upload '{\"voice_name\":\"旁白\",\"file_path\":\"/path/to/sample.mp3\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色上传成功\",\n  \"data\": { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 }\n}\n```\n\n**常见错误**：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"clone.exists\"` | 音色名称已存在 |\n| `\"clone.too_large\"` | 文件超过 7MB |\n| `\"clone.invalid_format\"` | 格式不支持 |\n\n---\n\n### `tts_clone_list` — 克隆音色列表\n\n**使用场景**：获取所有已上传的克隆音色列表\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"clones\": [\n    { \"name\": \"旁白\", \"ext\": \"mp3\", \"size\": 1048576 },\n    { \"name\": \"男主\", \"ext\": \"wav\", \"size\": 2097152 }\n  ]\n}\n```\n\n---\n\n### `tts_clone_delete` — 删除克隆音色\n\n**使用场景**：删除指定的克隆音色\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 要删除的克隆音色名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_delete '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"克隆音色已删除\"\n}\n```\n\n---\n\n### `tts_clone_audio` — 下载克隆音频\n\n**使用场景**：下载/试听指定的克隆音色原始音频文件（返回二进制 WAV 数据）\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `voice_name` | string | ✅ | 克隆音色名称 |\n| `save_to` | string | ❌ | 保存到本地路径（不传则返回 base64） |\n\n**执行脚本**：\n```bash\n# 保存到文件\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\",\"save_to\":\"/tmp/clone_preview.wav\"}'\n\n# 返回 base64（小文件）\n<skill-installation-path>/scripts/mybooks_api.py tts_clone_audio '{\"voice_name\":\"旁白\"}'\n```\n\n**响应示例**（保存到文件）：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"音频已保存\",\n  \"path\": \"/tmp/clone_preview.wav\",\n  \"size\": 1048576\n}\n```\n\n---\n\n### `tts_prompt_list` — 提示词列表\n\n**使用场景**：获取所有已保存的自定义语音提示词\n\n**权限**：管理员\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_list '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"prompts\": [\n    { \"name\": \"温柔女声\", \"desc\": \"温柔细腻的语调，语速偏慢，咬字清晰\" },\n    { \"name\": \"沉稳男声\", \"desc\": \"沉稳厚重的语调，语速适中偏低\" }\n  ]\n}\n```\n\n---\n\n### `tts_prompt_save` — 保存提示词\n\n**使用场景**：将自定义音色描述保存为提示词（同名覆盖），存储于服务端 `voice_prompts.json`\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 提示词名称 |\n| `desc` | string | ✅ | 音色描述（自然语言描述语音特征） |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_save '{\"name\":\"温柔女声\",\"desc\":\"温柔细腻的语调，语速偏慢，咬字清晰，富有亲和力\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已保存\"\n}\n```\n\n---\n\n### `tts_prompt_delete` — 删除提示词\n\n**使用场景**：删除指定的语音提示词\n\n**权限**：管理员\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | ✅ | 要删除的提示词名称 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py tts_prompt_delete '{\"name\":\"温柔女声\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"msg\": \"提示词已删除\"\n}\n```\n\n---\n\n## 使用场景决策指南\n\n```\n用户请求\n│\n├─ \"书库有多少书？\" / \"统计书库\"\n│   → library_stats（详细分类统计）\n│   → 或 get_user_info（快速总数）\n│\n├─ \"我读了多少书？\" / \"阅读情况\"\n│   → reading_stats\n│\n├─ \"找一下 XX 书\" / \"搜索 YY 作者\"\n│   → search_books（按关键词）\n│\n├─ \"找 XX 分类下的书\"\n│   → search_by_category\n│\n├─ \"查看书籍详情\"\n│   → get_book\n│\n├─ \"这本书我都划了哪些线？\" / \"看看《XX》的批注/书签\"\n│   → get_notes（传 book_id 或 title；own:0 可连他人共享的批注一起看）\n│\n├─ \"更新/补全《XX》的封面、简介、标签信息\"（自动从网上获取）\n│   → book_fill（需要管理员权限，传入 book_id 数组）\n│\n├─ \"手动修改《XX》的标签/分类/书名等字段\"\n│   → 先 search_books 确认 book_id → 再 edit_book\n│\n├─ \"把修改后的元数据也写入电子书文件本身\" / \"同步元数据到文件\"\n│   → save_meta_to_file（仅 epub/azw3/pdf，需管理员或书籍所有者权限）\n│\n├─ \"把我在微信读书上的划线/想法导入这本书\" / \"导入第三方批注\"\n│   → 先确认目标书是 EPUB 格式，再用 push_notes（先 dry_run:true 预览，用户确认后再 dry_run:false 提交）\n│   → 微信读书上有新批注后再次同步：直接把全量列表再传一遍 push_notes 即可，会自动判重，不用先清空\n│\n├─ \"撤销/重置这本书导入的批注\" / \"刚才导入错了，重新来一遍\"\n│   → clear_imported_notes（只影响当前用户自己通过 push_notes 导入的批注），然后重新调 push_notes\n│\n\n├─ \"把书发给我的 Kindle / 发到邮箱\"\n│   → mailto（发邮箱附件）\n│\n├─ \"把书发到我的多看/掌阅/BOOX 设备\"\n│   → send_to_device（需设备在同一局域网并开启 WiFi 接收）\n│\n├─ \"上传这本书\" / \"添加实体书\"\n│   → book_upload（电子书文件）\n│   → book_add_by_isbn（实体书 ISBN）\n│\n├─ \"这本书想读\" / \"加入待读清单\"\n│   → wants\n│\n├─ \"收藏这本书\"\n│   → favorite\n│\n├─ \"标记正在读\" / \"标记已读完\"\n│   → reading（read_state: 1 或 2）\n│   → read_done（快捷标记已读完）\n│\n├─ \"这本书读了多久？\" / \"读到哪了？\" / \"epub 版什么时候开始读的？\"\n│   → get_book_reading_stats（分格式的时长/进度/开始完成时间）\n│\n├─ \"帮我补记这本书的阅读时长\" / \"标记这本书 XX 格式已读完\"（无自动心跳的场景）\n│   → update_book_reading_stats\n│\n├─ \"补录某天的阅读时间\" / \"昨天晚上读了 45 分钟没记上\"（v4.3.0+）\n│   → set_reading_time（按日期覆盖）；查看用 get_reading_time；撤销用 delete_reading_time\n│\n├─ \"我有哪些书单？\" / \"把这本书加到《XX》书单\" / \"新建一个书单\"（v4.3.0+）\n│   → list_my_booklists / booklist_add_books / create_booklist\n│   → 看书单里的书：get_booklist；浏览大家的公开书单：list_public_booklists\n│   → 这本书已经在哪些书单里：get_book_booklists\n│\n└─ \"有哪些分类？\" / \"XX 作者有哪些书？\"\n    → categories / list_authors / get_author_books\n```\n\n### TTS 场景\n\n```\n用户请求\n│\n├─ \"配置 TTS API\" / \"设置 MiMo API Key\"\n│   → tts_save_config\n│\n├─ \"测试 API 能不能用\" / \"连接正常吗\"\n│   → tts_test_connection\n│\n├─ \"把这本书转成有声书\" / \"开始转换\"\n│   → tts_convert（需先有配置或直接传参）\n│\n├─ \"转换到哪了\" / \"进度怎么样\"\n│   → tts_progress\n│\n├─ \"上传克隆音色\" / \"我想用自己的声音\"\n│   → tts_clone_upload\n│\n├─ \"有哪些克隆音色\" / \"看看上传的音色\"\n│   → tts_clone_list\n│\n├─ \"删除克隆音色\" / \"不要这个音色了\"\n│   → tts_clone_delete\n│\n├─ \"试听克隆音色\" / \"下载克隆音频\"\n│   → tts_clone_audio\n│\n├─ \"有哪些提示词\" / \"保存的音色描述\"\n│   → tts_prompt_list\n│\n├─ \"保存这个音色描述\" / \"存一个提示词\"\n│   → tts_prompt_save\n│\n└─ \"删除提示词\" / \"不要这个描述了\"\n    → tts_prompt_delete\n```\n\n---\n\n## 预置音色参考\n\nMiMo TTS 类型（`api_type=chat_completions`）内置 9 个预置音色：\n\n| ID | 名称 | 语言 | 性别 |\n|----|------|------|------|\n| `mimo_default` | MiMo-默认 | 中文 | 女 |\n| `冰糖` | 冰糖 | 中文 | 女 |\n| `茉莉` | 茉莉 | 中文 | 女 |\n| `苏打` | 苏打 | 中文 | 男 |\n| `白桦` | 白桦 | 中文 | 男 |\n| `Mia` | Mia | 英文 | 女 |\n| `Chloe` | Chloe | 英文 | 女 |\n| `Milo` | Milo | 英文 | 男 |\n| `Dean` | Dean | 英文 | 男 |\n\n---\n\n## 错误处理规范\n\n| `err` 值 | 含义 | 建议处理 |\n|----------|------|----------|\n| `\"ok\"` | 操作成功 | 展示结果 |\n| `\"user.need_login\"` | 未登录或登录态过期 | 脚本自动重登录，仍失败则检查环境变量 |\n| `\"permission\"` | 无权限 | 说明当前账号权限不足，需管理员协助 |\n| `\"params.book.invalid\"` | 书籍不存在 | 建议用 `search_books` 重新确认 book_id |\n| `\"book.no_epub\"` | 书籍没有 EPUB 格式（或找不到 EPUB 文件） | `push_notes` 专属：提示用户该书无法导入批注，仅支持 EPUB |\n| `\"sync.import.failed\"` | `push_notes` 批注定位流程整体失败 | 与单条 `results[].status:\"error\"` 不同，是整批请求都没有结果，稍后重试或检查书籍文件是否损坏 |\n| `\"task.running\"` | 后台有任务在运行 | 等待当前任务完成后重试 |\n| `\"book.notfound\"` | ISBN 对应的书籍未在网上找到 | 换其他数据源或手动添加 |\n| `\"connection.failed\"` | 无法连接到设备 | 检查设备 IP 和 WiFi 接收功能是否开启 |\n| `\"format.not_supported\"` | 书籍没有 epub/azw3/pdf 格式 | 提示用户该书无法同步元数据到文件 |\n| `\"tts.converting\"` | TTS 转换任务进行中 | 等待完成后重试 |\n| `\"tts.no_config\"` | 未配置 TTS API | 先调用 `tts_save_config` |\n| `\"clone.too_large\"` | 克隆音色文件超限 | 提示用户裁剪音频至 7MB 内 |\n| `\"clone.invalid_format\"` | 克隆音色格式不支持 | 仅支持 MP3/WAV |\n| `\"clone.exists\"` | 克隆音色名称重复 | 换名或先删除旧的 |\n\n---\n\n## 注意事项\n\n1. **认证**：每次调用前脚本会自动登录，无需手动管理 Cookie；若未配置环境变量，脚本立即报错退出。\n2. **book_id**：书籍的唯一整数标识符，可通过 `search_books` 或 `get_book` 获取。\n3. **book_fill 异步性**：联网填充任务在后台运行，调用后立即返回；可通过 `get_book` 查看更新结果。\n4. **edit_book 标签替换**：`tags` 参数会**完整替换**原有标签，如需追加请先 `get_book` 获取现有标签再合并传入。\n5. **send_to_device 限制**：仅支持本地临时推送，不支持通过服务器中转到远程设备。\n6. **在线数据源**：`book_fill` 依赖豆瓣（douban）、百科（baike）等在线源，网络不可用或书籍较冷门时可能无结果。\n7. **批量 book_fill**：建议每批不超过 10 本，避免触发后台任务冲突（`task.running` 错误）。\n8. **TTS 管理员权限**：所有 TTS 接口均需要管理员权限，普通用户无法使用。\n9. **TTS 异步转换**：`tts_convert` 启动后台任务后立即返回，需用 `tts_progress` 轮询进度。\n10. **TTS 断点续传**：重复转换同一本书时，自动跳过已存在的 WAV 文件（≥44 字节），中断后可继续。\n11. **TTS 音频输出**：转换完成后，音频输出到 `/audio/{book_id}` 页面播放，也可通过 Web 界面访问。\n12. **TTS 克隆音色限制**：MP3/WAV ≤ 7MB；上传后自动切换 `mimo-v2.5-tts-voiceclone` 模型。\n13. **TTS 提示词存储**：提示词保存在服务端 `voice_prompts.json`，跨浏览器共享，不依赖本地存储。\n14. **TTS API Key 加密**：API Key 经 PBKDF2-SHA256 + 流加密保存，密钥文件权限 0o600。\n15. **TTS 模型锁定**：MiMo TTS 类型下模型 ID 固定为 `mimo-v2.5-tts`，不可修改；`audio_speech` 和 `custom` 类型可自由修改。\n\nFile v1.0.5:_meta.json\n\n{\n  \"ownerId\": \"kn7efqfkfz4afhzzg8xd9bbcdh82drav\",\n  \"slug\": \"mybooks\",\n  \"version\": \"1.0.5\",\n  \"publishedAt\": 1789959637571\n}\n\nFile v1.0.5:skill-card.md\n\n## Description:\n\nMyBooks connects an agent to a MyBooks personal library server to search books, manage metadata and reading state, import notes, maintain booklists, send or upload books, and manage TTS audiobook workflows.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[poxenstudio](https://clawhub.ai/user/poxenstudio)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to let an agent operate a configured MyBooks library account through documented API tools. It supports library search, metadata maintenance, reading progress and note workflows, booklist management, file delivery or upload, and administrator-only TTS features.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can transmit local files, private book content, recipient addresses, device addresses, and TTS provider details to the configured MyBooks server or related services.\n\nMitigation: Install only for a trusted MyBooks server and confirm file paths, recipients, device addresses, TTS providers, and upload or send actions before execution.\n\nRisk: The skill can perform account-changing actions such as metadata edits, reading-state updates, booklist changes, note imports, deletions, and administrator-only TTS configuration.\n\nMitigation: Confirm destructive or account-changing actions with the user, use documented dry-run flows for note imports where available, and avoid admin credentials unless admin-only features are needed.\n\nRisk: The skill depends on MyBooks credentials supplied through environment variables.\n\nMitigation: Keep credentials session-scoped or in a dedicated secret manager and avoid storing them in shared or global configuration files.\n\n## Reference(s):\n\n- [MyBooks homepage](https://www.mybooks.top)\n- [ClawHub MyBooks skill page](https://clawhub.ai/poxenstudio/skills/mybooks)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, JSON, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with shell command examples and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires python3 plus MYBOOKS_HOST, MYBOOKS_USER, and MYBOOKS_PASSWORD; outputs depend on the configured MyBooks server and account permissions.]\n\n## Skill Version(s):\n\n1.0.5 (source: evidence.release.version)\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 v1.0.5:skill.json\n\n{\n  \"name\": \"MyBooks\",\n  \"license\": \"MIT-0\"\n}\n\nArchive v1.0.4: 5 files, 25936 bytes\n\nFiles: scripts/mybooks_api.py (38248b), skill-card.md (2972b), skill.json (46b), SKILL.md (49300b), _meta.json (126b)\n\nFile v1.0.4:SKILL.md\n\n---\nname: mybooks\nhomepage: https://www.mybooks.top\nallowed-tools: Bash(python3:*)\nmetadata: {\"clawdbot\":{},\"openclaw\":{\"requires\":{\"bins\":[\"python3\"],\"env\":[\"MYBOOKS_HOST\",\"MYBOOKS_USER\",\"MYBOOKS_PASSWORD\"]}}}\ndescription: \"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取原始数据）,以及MiMo TTS有声书功能（配置TTS API、EPUB转有声书、查询转换进度、克隆音色与语音提示词管理，需管理员权限）等\"\n---\n\n# MyBooks\n\n## Requirements\n```bash\n# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'\n```\n\n> **安全提示**：请勿将凭据写入共享或全局配置文件（如 `~/.openclaw/.env`），以避免凭据被其他 agent 或进程意外读取。建议通过会话级环境变量或专用密钥管理工具传入凭据。\n\n## 通用响应格式与认证方式\n\n### 通用 JSON 响应结构\n所有 API 均返回如下格式：\n```json\n{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}\n```\n\n常见错误码：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"ok\"` | 操作成功 |\n| `\"user.need_login\"` | 未登录或登录态已过期 |\n| `\"permission\"` | 无权限执行该操作 |\n| `\"params.invalid\"` | 请求参数错误 |\n| `\"params.book.invalid\"` | 书籍不存在或 ID 错误 |\n| `\"task.running\"` | 后台任务正在进行中，稍后重试 |\n| `\"tts.converting\"` | TTS 转换任务正在运行 |\n| `\"tts.no_config\"` | 未配置 TTS API |\n| `\"clone.exists\"` | 克隆音色名称已存在 |\n| `\"clone.not_found\"` | 克隆音色不存在 |\n| `\"clone.too_large\"` | 文件超过 7MB 限制 |\n| `\"clone.invalid_format\"` | 仅支持 MP3/WAV 格式 |\n| `\"prompt.exists\"` | 提示词名称已存在 |\n| `\"prompt.not_found\"` | 提示词不存在 |\n\n### 认证方式\n- 脚本通过 `MYBOOKS_USER` / `MYBOOKS_PASSWORD` 环境变量自动调用 `/api/user/sign_in` 完成登录\n- 服务端通过 **Secure Cookie**（`user_id` + `lt`）维持会话\n- 若响应中出现 `err=user.need_login`，脚本会自动重新登录后重试一次；仍失败则报错退出\n- **必须**在调用前配置 `MYBOOKS_HOST`、`MYBOOKS_USER`、`MYBOOKS_PASSWORD` 三个环境变量，否则脚本直接报错退出\n\n---\n\n## 工具列表\n\n### `get_user_info` — 用户信息与系统统计\n\n**使用场景**：获取当前登录用户信息，同时返回书库总体统计（书籍数、作者数等）\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_user_info '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"user\": { \"is_login\": true, \"nickname\": \"管理员\", \"is_admin\": true },\n  \"sys\": { \"books\": 1280, \"authors\": 342, \"tags\": 86, \"mtime\": \"2025-03-01\" }\n}\n```\n\n---\n\n### `library_stats` — 书库统计\n\n**使用场景**：获取书库详细统计，包括电子书/实体书数量及本月新增\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py library_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_books\": 1280,\n    \"ebook_count\": 1210,\n    \"physical_count\": 70,\n    \"month_ebook_count\": 12,\n    \"month_physical_count\": 3,\n    \"current_year\": 2025,\n    \"current_month\": 3\n  }\n}\n```\n\n---\n\n### `reading_stats` — 阅读统计\n\n**使用场景**：获取当前用户的阅读统计（在读/已读数量、本月数据）及当前在读书单\n\n**参数**：无\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py reading_stats '{}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_reading\": 5,\n    \"total_read_done\": 42,\n    \"month_reading\": 2,\n    \"month_read_done\": 3\n  },\n  \"current_reading_books\": [ /* 书籍对象列表 */ ],\n  \"month_read_done_books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_books` — 搜索书籍\n\n**使用场景**：\n- 按书名或作者名搜索，支持简繁体自动转换\n- \"有没有余华的书？\" / \"找一下《三体》\"\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `name` | string | ✅ | — | 搜索关键词（书名或作者名） |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_books '{\"name\":\"三体\"}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"title\": \"搜索：三体\",\n  \"total\": 3,\n  \"books\": [ /* 书籍对象列表 */ ]\n}\n```\n\n---\n\n### `search_by_category` — 按分类查询书籍\n\n**使用场景**：查询指定分类下的所有书籍（基于自定义 `#category` 字段）\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `category` | string | ✅ | — | 分类名称，如 \"科幻\" |\n| `num` | int | ❌ | 20 | 每页数量 |\n| `page` | int | ❌ | 1 | 页码，从 1 开始 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py search_by_category '{\"category\":\"科幻\"}'\n```\n\n---\n\n### `get_book` — 书籍详情\n\n**使用场景**：获取指定书籍的完整信息，包括元数据、可用格式、封面、阅读状态等\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py get_book '{\"book_id\":42}'\n```\n\n**响应示例**：\n```json\n{\n  \"err\": \"ok\",\n  \"book\": {\n    \"id\": 42,\n    \"title\": \"活着\",\n    \"authors\": [\"余华\"],\n    \"tags\": [\"小说\", \"中国文学\"],\n    \"publisher\": \"作家出版社\",\n    \"isbn\": \"9787506365437\",\n    \"pubdate\": \"2012-08-01\",\n    \"rating\": 9,\n    \"comments\": \"《活着》讲述了...\",\n    \"category\": \"现代文学\",\n    \"available_formats\": [\"epub\", \"pdf\"],\n    \"files\": [\n      {\n        \"format\": \"EPUB\",\n        \"size\": 1330899,\n        \"href\": \"/api/book/42.EPUB\"\n      }\n    ],\n    \"cover_url\": \"/get/cover/42\",\n    \"series\": \"余华作品集\",\n    \"series_index\": 1,\n    \"state\": {\n      \"favorite\": 0,\n      \"wants\": 0,\n      \"read_state\": 1\n    },\n    \"tags\": [\"小说\", \"中国文学\"]\n  },\n  \"kindle_sender\": \"sender@example.com\"\n}\n```\n\n---\n\n### `edit_book` — 编辑书籍元数据\n\n**使用场景**：\n- 手动修改书名、作者、标签、分类等字段\n- 修改实体书数量或类型\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `book_id` | int | ✅ | 书籍 ID |\n| `title` | string | ❌ | 书名 |\n| `authors` | array | ❌ | 作者列表，如 `[\"余华\"]` |\n| `tags` | array | ❌ | 标签列表，**替换**原有标签（想追加需先 `get_book` 获取现有标签再合并） |\n| `publisher` | string | ❌ | 出版社 |\n| `isbn` | string | ❌ | ISBN 编号 |\n| `series` | string | ❌ | 系列/丛书名 |\n| `series_index` | int | ❌ | 系列中的顺序号 |\n| `rating` | number | ❌ | 评分（0–10） |\n| `languages` | array | ❌ | 语言代码列表，如 `[\"zho\"]`（中文）、`[\"eng\"]`（英文）、`[\"zha\"]`（繁体中文） |\n| `pubdate` | string | ❌ | 出版日期，格式：`\"2024-01-15\"` / `\"2024-01\"` / `\"2024\"` |\n| `comments` | string | ❌ | 书籍简介，支持 HTML，请勿将 `<>` 转义为 `&lt;&gt;` |\n| `category` | string | ❌ | 自定义分类（最长 80 字符；传 `\"清除\"` 或 `\"clear\"` 清空分类） |\n| `book_count` | int | ❌ | 实体书数量（需配合 `book_type: 1` 使用） |\n| `book_type` | int | ❌ | 书籍类型：`0`=电子书，`1`=实体书 |\n\n**执行脚本**：\n```bash\n<skill-installation-path>/scripts/mybooks_api.py edit_book '{\"book_id\":42,\"tags\":[\"小说\",\"中国文学\"],\"category\":\"现代文学\"}'\n```\n\n**响应示例**：\n```json\n{ \"err\": \"ok\", \"msg\": \"更新成功\", \"books\": [42] }\n```\n\n---\n\n### `push_notes` — 导入第三方批注（微信读书等）\n\n**使用场景**：把从其他阅读 App（目前是微信读书）读到的划线/想法，通过服务端全文检索定位到 MyBooks 书库里对应 EPUB 书籍的正文位置，写入这本书的阅读记录。详细方案见 `plan/WeChatReading_Annotation_Import_Plan.md`。\n\n**前提**：目标书籍必须已经在 MyBooks 书库里，且**必须有 EPUB 格式**（定位算法依赖 EPUB 的正文结构，其它格式不支持）。\n\n**参数**：\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n|------|------|------|--------|------|\n| `book_id` | int | ✅ | — | 书籍 ID（须为 EPUB 格式） |\n| `anchors` | array | ✅ | — | 待导入的批注列表，见下 |\n| `anchors[].id` | string | ✅ | — | 来源系统里的稳定 ID（如微信读书的 `bookmarkId`/`reviewId`），用于生成幂等的记录 ID——同样的 `anchors` 重复调用不会重复导入 |\n| `anchors[].text` | string | ❌ | — | 划线/引用的原文，用于全文检索定位；不传则视为\"无原文锚点\"（章节点评/整本书评），会退化为\"挂在章节开头\"的书签 |\n| `anchors[].chapterHint` | string | ❌ | — | 来源系统里的章节标题，`text` 未提供时用于定位章节起始位置 |\n| `anchors[].note` | string | ❌ | — | 用户写的想法/点评正文 |\n| `anchors[].color` | string | ❌ | `\"yellow\"` | 高亮颜色 |\n| `anchors[].style` | string | ❌ | `\"highlight\"` | `highlight`/`underline`/`squiggly` |\n| `anchors[].createdAt` | int | ❌ | 当前时间 | 来源系统里的创建时间（毫秒时间戳） |\n| `anchors[].source` | string | ❌ | `\"wxread\"` | 来源标记 |\n| `on_ambiguous` | string | ❌ | `\"error\"` | 原文在书里检索到多处命中时的处理：`\"error\"`=不写入、标记为歧义待复核；`\"first_match\"`=取第一个命中位置写入 |\n| `dry_run` | bool | ❌ | `true` | `true`=只做检索定位、返回预览报告，不写入；`false`=同时写入。**务必先用 `dry_run:true` 看一遍报告、跟用户确认后再用 `dry_run:false` 提交，不要一步到位直接写入** |\n| `force` | bool | ❌ | `false` | 重复导入默认会**自动判重**：某条 `anchors[].id` 如果 `text`/`chapterHint` 跟上次导入时一样，直接复用上次的定位结果，不会重新跑检索（响应里对应条目会带 `\"reused\": true`）。`force:true` 会跳过判重、强制重新定位所有条目——只有书籍文件本身被替换过这种场景才需要，**日常重复同步不要传这个参数**，判重本身就是为了处理\"微信读书上有新批注后再次同步\"这种情况设计的 |\n\n**再次同步（判重）说明**：微信读书没有增量接口，每次都会拿到全量划线/想法列表。直接把全量列表再传一遍给 `push_notes` 是安全且推荐的做法——服务端会按 `anchors[].id` 匹配上次导入的记录，`text`/`chapterHint` 没变的条目不会重新定位（省时间，也避免同一条批注每次定位到略有不同的位置），只有新增的、或者原文本身变了的条目才会真正重新检索。如果只是想法/评论内容改了但划线原文没变，也会被识别为\"位置没变、内容更新\"，只更新想法文本，不重新定位。\n\n**执行脚本**：\n```bash\n# 第一步：预览（默认 dry_run:true），不会写入任何数据\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ]\n}'\n\n# 第二步：跟用户确认预览报告无误后，正式写入\n<skill-installation-path>/scripts/mybooks_api.py push_notes '{\n  \"book_id\": 42,\n  \"anchors\": [\n    {\"id\": \"wx-bm-1001\", \"text\": \"他手里拿着两大块磁铁\", \"note\": \"开篇的魔幻现实主义笔法\"},\n    {\"id\": \"wx-review-2001\", \"chapterHint\": \"第一章\"}\n  ],\n  \"dry_run\": false\n}'\n```\n\n**响应示例**（预览，`dry_run:true`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": true,\n  \"results\": [\n    { \"id\": \"wx-bm-1001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/10!/4/4/2,/19:17,/21:4)\", \"matchCount\": 1 },\n    { \"id\": \"wx-review-2001\", \"status\": \"ok\", \"cfi\": \"epubcfi(/6/8!/4)\", \"degraded\": \"chapter_start\" }\n  ]\n}\n```\n\n**响应示例**（提交，`dry_run:false`，额外带 `pushed`）：\n```json\n{\n  \"err\": \"ok\",\n  \"book_id\": 42,\n  \"book_hash\": \"cloud-42-epub\",\n  \"dry_run\": false,\n  \"results\": [ /* 同上 */ ],\n  \"pushed\": { \"notes\": [ /* 写入后的最终记录，字段与 GET /api/sync 一致 */ ] }\n}\n```\n\n**`results[].status` 取值**：\n| 值 | 含义 | 建议处理 |\n|----|------|----------|\n| `\"ok\"` | 定位成功，`cfi` 有值 | 展示给用户确认；`degraded:\"chapter_start\"` 表示这是退化的章节\n\nArchive v1.0.3: 5 files, 24093 bytes\n\nFiles: scripts/mybooks_api.py (36073b), skill-card.md (2362b), skill.json (46b), SKILL.md (45606b), _meta.json (126b)\n\nArchive v1.0.2: 5 files, 22155 bytes\n\nFiles: scripts/mybooks_api.py (33555b), skill-card.md (2434b), skill.json (46b), SKILL.md (42174b), _meta.json (126b)\n\nArchive v1.0.1: 5 files, 13163 bytes\n\nFiles: scripts/mybooks_api.py (19619b), skill-card.md (2403b), skill.json (46b), SKILL.md (21789b), _meta.json (126b)\n\nArchive v1.0.0: 5 files, 12449 bytes\n\nFiles: scripts/mybooks_api.py (18901b), skill-card.md (2287b), skill.json (46b), SKILL.md (19807b), _meta.json (126b)","readmeExcerpt":"Skill: MyBooks Owner: poxenstudio Summary: MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取 Tags: latest:1.0.7 Version history: v1.0.7 | 2026-09-28T04:09:53.903Z | user","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n# 明文 http 仅允许回环/内网地址（如 192.168.x.x）；公网地址必须用 https\n# 确需对非内网地址使用明文 http 时：export MYBOOKS_ALLOW_INSECURE_HTTP=\"true\"\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'"},{"language":"json","snippet":"{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}"},{"language":"bash","snippet":"<skill-installation-path>/scripts/mybooks_api.py get_user_info '{}'"},{"language":"json","snippet":"{\n  \"err\": \"ok\",\n  \"user\": { \"is_login\": true, \"nickname\": \"管理员\", \"is_admin\": true },\n  \"sys\": { \"books\": 1280, \"authors\": 342, \"tags\": 86, \"mtime\": \"2025-03-01\" }\n}"},{"language":"bash","snippet":"<skill-installation-path>/scripts/mybooks_api.py library_stats '{}'"},{"language":"json","snippet":"{\n  \"err\": \"ok\",\n  \"stats\": {\n    \"total_books\": 1280,\n    \"ebook_count\": 1210,\n    \"physical_count\": 70,\n    \"month_ebook_count\": 12,\n    \"month_physical_count\": 3,\n    \"current_year\": 2025,\n    \"current_month\": 3\n  }\n}"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: mybooks\nhomepage: https://www.mybooks.top\nallowed-tools: Bash(python3:*)\nmetadata: {\"clawdbot\":{},\"openclaw\":{\"requires\":{\"bins\":[\"python3\"],\"env\":[\"MYBOOKS_HOST\",\"MYBOOKS_USER\",\"MYBOOKS_PASSWORD\"]},\"permissions\":{\"network\":{\"required\":true,\"scope\":\"user-configured MYBOOKS_HOST only\",\"protocols\":[\"http\",\"https\"]},\"filesystem\":{\"read\":\"only when uploading: ebook files (book_upload) and mp3/wav samples (tts_clone_upload) at paths the user gives\",\"write\":\"only tts_clone_audio save_to (.wav, never overwrites)\"}}}}\ndescription: \"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取原始数据）,以及MiMo TTS有声书功能（配置TTS API、EPUB转有声书、查询转换进度、克隆音色与语音提示词管理，需管理员权限）等\"\n---\n\n# MyBooks\n\n## Requirements\n```bash\n# 需要配置以下三个环境变量后方可使用\nexport MYBOOKS_HOST=\"http://127.0.0.1:8082\"\nexport MYBOOKS_USER=\"admin\"\nexport MYBOOKS_PASSWORD=\"your_password\"\nexport MYBOOKS_SSL_VERIFY=\"false\"   # 如服务器使用自签名证书，设为 false\n# 明文 http 仅允许回环/内网地址（如 192.168.x.x）；公网地址必须用 https\n# 确需对非内网地址使用明文 http 时：export MYBOOKS_ALLOW_INSECURE_HTTP=\"true\"\n\n然后按如下方式执行：\n<skill-installation-path>/scripts/mybooks_api.py <tool-name> '<json-args>'\n```\n\n> **安全提示**：请勿将凭据写入共享或全局配置文件（如 `~/.openclaw/.env`），以避免凭据被其他 agent 或进程意外读取。建议通过会话级环境变量或专用密钥管理工具传入凭据。\n\n## 权限与网络声明\n\n- **网络访问（必需）**：本 skill 是 MyBooks 服务器的 REST 客户端，所有工具都通过 HTTP(S) 访问**且仅访问**用户自己配置的 `MYBOOKS_HOST`，不连接任何其他地址，无遥测、无第三方回传。\n- **会修改数据的工具**：`edit_book`、`set_folder`、`rename_folder`、`push_notes`(`dry_run:false`)、`clear_imported_notes`、`book_fill`、`save_meta_to_file`、`book_upload`、`book_add_by_isbn`、`wants`/`favorite`/`reading`/`read_done`、`set_reading_time`、`delete_reading_time`、书单的创建/修改/删除/增删书/点赞、以及全部 `tts_*` 写操作。删除类工具（`delete_booklist`、`delete_reading_time`）脚本内强制 `confirm:true` 两步确认。\n- **本地文件读取**：仅 `book_upload`（限电子书扩展名 epub/mobi/azw/azw3/pdf/txt/lrf/rtf/djvu/docx）和 `tts_clone_upload`（限 mp3/wav，≤7MB）会读取用户明确给出路径的文件并上传到 `MYBOOKS_HOST`；agent **不得**自行挑选文件上传。\n- **本地文件写入**：仅 `tts_clone_audio` 的 `save_to`（必须 `.wav` 结尾，且不覆盖已存在文件）。\n- **凭据**：见下方\"认证方式\"。\n\n## 通用响应格式与认证方式\n\n### 通用 JSON 响应结构\n所有 API 均返回如下格式：\n```json\n{\n  \"err\": \"ok\",       // \"ok\" 表示成功，其他字符串表示错误码\n  \"msg\": \"...\",      // 可选，人类可读的成功/错误说明\n  \"data\": { }        // 可选，具体响应数据（因接口而异）\n}\n```\n\n常见错误码：\n| `err` 值 | 含义 |\n|----------|------|\n| `\"ok\"` | 操作成功 |\n| `\"user.need_login\"` | 未登录或登录态已过期 |\n| `\"permission\"` | 无权限执行该操作 |\n| `\"params.invalid\"` | 请求参数错误 |\n| `\"params.book.invalid\"` | 书籍不存在或 ID 错误 |\n| `\"task.running\"` | 后台任务正在进行中，稍后重试 |\n| `\"tts.converting\"` | TTS 转换任务正在运行 |\n| `\"tts.no_config\"` | 未配置 TTS API |\n| `\"clone.exists\"` | 克隆音色名称已存在 |\n| `\"clone.not_found\"` | 克隆音色不存在 |\n| `\"clone.too_large\"` | 文件超过 7MB 限制 |\n| `\"clone.invalid_format\"` | 仅支持 MP3/WAV 格式 |\n| `\"prompt.exists\"` | 提示词名称已存在 |\n| `\"prompt.not_found\"` | 提示词不存在 |\n\n### 认证方式\n- 脚本通过 `MYBOOKS_USER` / `MYBOOKS_PASSWORD` 环境变量自动调用 `/ap"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7efqfkfz4afhzzg8xd9bbcdh82drav\",\n  \"slug\": \"mybooks\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1790568593903\n}"},{"path":"skill-card.md","content":"## Description:\n\nHelps users manage a MyBooks library, reading activity, annotations, book transfers, and administrator-controlled audiobook conversion and voice settings.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[poxenstudio](https://clawhub.ai/user/poxenstudio)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nMyBooks users can ask an agent to find and organize books, track reading, import annotations, transfer ebooks, and manage audiobooks when authorized.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Credentials, book text, voice samples, or TTS keys may be processed by the configured MyBooks server or TTS provider.\n\nMitigation: Use a trusted server and HTTPS for non-local hosts, keep credentials session-scoped, and review TTS use before sharing sensitive content.\n\nRisk: Uploading an unintended local ebook or voice sample could expose private material.\n\nMitigation: Upload only files explicitly selected by the user and confirm their destination.\n\nRisk: Library edits, annotation imports, and deletions can change or remove user data.\n\nMitigation: Preview supported changes and obtain user confirmation before destructive actions.\n\n## Reference(s):\n\n- [MyBooks skill on ClawHub](https://clawhub.ai/poxenstudio/skills/mybooks)\n- [MyBooks website](https://www.mybooks.top)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration guidance]\n\n**Output Format:** [Natural-language responses based on MyBooks API results, with optional commands or configuration steps]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May save a requested voice recording as a WAV file.]\n\n## Skill Version(s):\n\n1.0.7 (source: ClawHub release evidence)\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":"skill.json","content":"{\n  \"name\": \"MyBooks\",\n  \"license\": \"MIT-0\"\n}"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取 Skill: MyBooks Owner: poxenstudio Summary: MyBooks是个人书库管理系统，提供电子书及实体书管理，包括存储、分类、搜索和元数据管理功能。你可以帮助用户：查询书库统计信息和阅读统计,搜索/浏览书籍,获取书籍详情,更新书籍元数据（书名、作者、标签、分类、简介等）,自动联网填充书籍信息,发送书籍到邮箱或阅读器设备,上传电子书或通过ISBN添加实体书,管理阅读状态（想读/在读/已读/收藏）,查询/手动更新某本书分格式的阅读时长与进度,按日期补录/修改/删除阅读时间（v4.3.0+）,管理书单（创建/浏览/加书/移书/点赞，v4.3.0+）,查看作者信息和分类信息,导入第三方阅读App的划线与想法（如微信读书，需配合微信读书 skill 读取 Tags: latest:1.0.7 Version history: v1.0.7 | 2026-09-28T04:09:53.903Z | user","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1171,"uniquenessScore":55,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T15:39:51.485Z","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-10T15:39:51.485Z","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-10T21:48:56.750Z","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"}]}}}