{"id":"90d4aca4-e67a-40f9-98c0-956d8517ff0c","entityType":"agent","slug":"clawhub-edwardwason-web-to-fim","name":"Web To Fim","canonicalUrl":"https://www.xpersona.co/agent/clawhub-edwardwason-web-to-fim","canonicalPath":"/agent/clawhub-edwardwason-web-to-fim","generatedAt":"2026-10-10T06:02:27.998Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:54:54.953Z","emptyReason":null},"description":"将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。 支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）； (3) 飞书...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s177q4wcvafq6fzfkhk2g3cwth83y01d:web-to-fim","sourceUrl":"https://clawhub.ai/edwardwason/web-to-fim","homepage":"https://clawhub.ai/edwardwason/skills/web-to-fim","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/edwardwason/web-to-fim","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/edwardwason/skills/web-to-fim","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":66,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Web To Fim technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:54:54.953Z","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-09T20:54:54.953Z","emptyReason":null},"stars":null,"forks":null,"downloads":2005,"packageName":null,"latestVersion":"3.7.0","tractionLabel":"2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:54:54.953Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T20:54:54.953Z","lastCrawledAt":"2026-10-09T20:54:54.953Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T20:54:54.953Z","lastVerifiedAt":null,"highlights":[{"version":"3.7.0","createdAt":"2026-07-18T15:05:55.458Z","changelog":"v3.7.0: Feishu wiki fetch via lark-cli docs +fetch (WebFetch truncation fix). Breaking change: Feishu wiki fetching migrated from WebFetch (severe truncation 200-1000 chars) to lark-cli docs +fetch (full content 3K-25K chars). Verified 33 articles all fetched completely.","fileCount":15,"zipByteSize":48713},{"version":"3.4.0","createdAt":"2026-07-12T07:44:44.888Z","changelog":"v3.4.0: ClawHub security fixes (MCP Least Privilege + User Warnings + trigger narrowing) + X link transcription flow fix","fileCount":16,"zipByteSize":43313},{"version":"3.3.0","createdAt":"2026-07-12T07:20:22.436Z","changelog":"v3.3.0: IMA routing refinement + original URL auto-extraction","fileCount":18,"zipByteSize":44504},{"version":"3.2.0","createdAt":"2026-07-12T03:59:24.482Z","changelog":"v3.2.0: Obsidian file naming convention (YYYYMMDD-title-source.md) + Feishu wiki original URL priority transcription + Do NOT scope declaration","fileCount":16,"zipByteSize":40144},{"version":"3.1.0","createdAt":"2026-07-11T11:12:04.374Z","changelog":"Critical: tweet_to_md hardcoded headers removed + subprocess timeout. Important: batch resume, frontmatter tags, wechat extraction improved. Minor: import cleanup, gitignore, title fallback.","fileCount":15,"zipByteSize":37354},{"version":"3.0.2","createdAt":"2026-07-11T03:28:42.638Z","changelog":"v3.0.2: Updated SKILL.md frontmatter description to include Feishu wiki source transcription and WeChat/web image-preserving IMA import. Updated source table to add Feishu wiki row.","fileCount":12,"zipByteSize":28732},{"version":"3.0.1","createdAt":"2026-07-11T03:22:24.541Z","changelog":"v3.0.1 doc update: Added Feishu wiki source transcription and WeChat/web image-preserving import to SKILL.md. v3.0.0 major upgrade with 12 key features: (1) Feishu wiki document source transcription via WebFetch; (2) WeChat/web articles preserve images via IMA import_urls server-side fetch; (3) IMA API migrated to OpenAPI v1.1.7 endpoints; (4) IMA storage changed from notebook to knowledge base two-step flow; (5) X/Twitter links forced to verbatim transcription; (6) Environment variables changed to IMA_OPENAPI_CLIENTID/IMA_OPENAPI_APIKEY; (7) Added --urls-file batch mode; (8) Added --dry-run preview mode; (9) WeChat anti-crawl fallback with mobile UA; (10) Feishu blocks batch insertion (50 limit); (11) Added feishu-blocks.md block_type reference; (12) Rewrote ima-setup.md with two-API-system docs","fileCount":12,"zipByteSize":28557},{"version":"3.0.0","createdAt":"2026-07-11T03:18:39.671Z","changelog":"v3.0.0 major upgrade: (1) IMA API migrated to OpenAPI v1.1.7 endpoints; (2) IMA storage changed from notebook to knowledge base two-step flow; (3) Added IMA import_urls for WeChat/web URL server-side fetch preserving images; (4) X/Twitter links forced to verbatim transcription; (5) Environment variables changed to IMA_OPENAPI_CLIENTID/IMA_OPENAPI_APIKEY; (6) Added --urls-file batch mode and --dry-run preview; (7) WeChat anti-crawl fallback with mobile UA; (8) Feishu blocks batch insertion (50 limit); (9) Added feishu-blocks.md reference; (10) Rewrote ima-setup.md","fileCount":12,"zipByteSize":28335}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s177q4wcvafq6fzfkhk2g3cwth83y01d:web-to-fim","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s177q4wcvafq6fzfkhk2g3cwth83y01d:web-to-fim` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/edwardwason/web-to-fim before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/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-10T06:02:27.995Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-web-to-fim/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:54:54.953Z","emptyReason":null},"readme":"Skill: Web To Fim\n\nOwner: edwardwason\n\nSummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。 支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）； (3) 飞书...\n\nTags: ai-information-management:3.7.0, latest:3.7.0, productivity:3.7.0\n\nVersion history:\n\nv3.7.0 | 2026-07-18T15:05:55.458Z | user\n\nv3.7.0: Feishu wiki fetch via lark-cli docs +fetch (WebFetch truncation fix). Breaking change: Feishu wiki fetching migrated from WebFetch (severe truncation 200-1000 chars) to lark-cli docs +fetch (full content 3K-25K chars). Verified 33 articles all fetched completely.\n\nv3.4.0 | 2026-07-12T07:44:44.888Z | user\n\nv3.4.0: ClawHub security fixes (MCP Least Privilege + User Warnings + trigger narrowing) + X link transcription flow fix\n\nv3.3.0 | 2026-07-12T07:20:22.436Z | user\n\nv3.3.0: IMA routing refinement + original URL auto-extraction\n\nv3.2.0 | 2026-07-12T03:59:24.482Z | user\n\nv3.2.0: Obsidian file naming convention (YYYYMMDD-title-source.md) + Feishu wiki original URL priority transcription + Do NOT scope declaration\n\nv3.1.0 | 2026-07-11T11:12:04.374Z | user\n\nCritical: tweet_to_md hardcoded headers removed + subprocess timeout. Important: batch resume, frontmatter tags, wechat extraction improved. Minor: import cleanup, gitignore, title fallback.\n\nv3.0.2 | 2026-07-11T03:28:42.638Z | user\n\nv3.0.2: Updated SKILL.md frontmatter description to include Feishu wiki source transcription and WeChat/web image-preserving IMA import. Updated source table to add Feishu wiki row.\n\nv3.0.1 | 2026-07-11T03:22:24.541Z | user\n\nv3.0.1 doc update: Added Feishu wiki source transcription and WeChat/web image-preserving import to SKILL.md. v3.0.0 major upgrade with 12 key features: (1) Feishu wiki document source transcription via WebFetch; (2) WeChat/web articles preserve images via IMA import_urls server-side fetch; (3) IMA API migrated to OpenAPI v1.1.7 endpoints; (4) IMA storage changed from notebook to knowledge base two-step flow; (5) X/Twitter links forced to verbatim transcription; (6) Environment variables changed to IMA_OPENAPI_CLIENTID/IMA_OPENAPI_APIKEY; (7) Added --urls-file batch mode; (8) Added --dry-run preview mode; (9) WeChat anti-crawl fallback with mobile UA; (10) Feishu blocks batch insertion (50 limit); (11) Added feishu-blocks.md block_type reference; (12) Rewrote ima-setup.md with two-API-system docs\n\nv3.0.0 | 2026-07-11T03:18:39.671Z | user\n\nv3.0.0 major upgrade: (1) IMA API migrated to OpenAPI v1.1.7 endpoints; (2) IMA storage changed from notebook to knowledge base two-step flow; (3) Added IMA import_urls for WeChat/web URL server-side fetch preserving images; (4) X/Twitter links forced to verbatim transcription; (5) Environment variables changed to IMA_OPENAPI_CLIENTID/IMA_OPENAPI_APIKEY; (6) Added --urls-file batch mode and --dry-run preview; (7) WeChat anti-crawl fallback with mobile UA; (8) Feishu blocks batch insertion (50 limit); (9) Added feishu-blocks.md reference; (10) Rewrote ima-setup.md\n\nv2.2.0 | 2026-04-19T01:14:05.702Z | user\n\n🔒 安全与合规增强：完善 ClawHub 元数据、跨平台 Obsidian 路径配置、完整依赖声明、安全声明章节\n\nv2.1.0 | 2026-04-18T01:20:42.431Z | user\n\n增强 Hermes Agent 支持，更新文档\n\nArchive index:\n\nArchive v3.7.0: 15 files, 48713 bytes\n\nFiles: _meta.json (129b), CHANGELOG.md (12130b), README.en.md (4145b), README.md (4836b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (9744b), scripts/ima_client.py (13813b), scripts/save_fetched.py (3964b), scripts/web_to_all.py (22928b), scripts/web_to_md.py (12245b), skill-card.md (2380b), SKILL.md (23166b)\n\nFile v3.7.0:SKILL.md\n\n---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.7.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云盘、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（v3.7.0 改用 lark-cli docs +fetch 抓取完整内容，WebFetch 截断严重已弃用）；\n  (4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云盘（.md 原文件，用户身份上传立即可见）+ IMA 知识库（FIM知识库，AI 原生）。\n  v3.7.0 飞书 wiki 抓取改造：从 WebFetch（截断严重，200-1000 字符）改为 lark-cli docs +fetch（完整内容，3K-25K 字符），实测 33 篇文章中 19 篇被 WebFetch 截断。\n  v3.6.0 飞书存储改造：从应用身份创建在线 docx 改为 lark-cli drive +upload 上传 .md 原文件到用户云盘，用户在飞书\"我的空间 > 云盘\"立即可见。\n  IMA 智能路由：公众号/普通网页 → import_urls 保留图片；X/Twitter/飞书/GitHub → 纯文本笔记逐字转录。\n  飞书 wiki 原文链接优先转录：检查文章头部\"原文链接\"，有则优先抓取原文内容作为最终产物存三处，IMA 只存原文链接地址自动识别。\n  X 链接转录流程：飞书 wiki 中发现 X 原文链接时，用 x-tweet-fetcher 抓取完整长文（10K-15K 字符），失败时降级到飞书 wiki 内容。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：抓网页存飞书、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户明确要求将 URL 或本地文件转存为文档并存储到 Obsidian/飞书/IMA 时触发。\n  Do NOT use for 创建文档内容、编辑飞书文档正文、代码开发、非文档转存任务、普通文档格式转换（非三处存放意图）。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📁 **飞书云盘** - .md 原文件，用户身份上传立即可见（v3.6.0）\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | **lark-cli docs +fetch**（v3.7.0 改造，完整内容） |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n> ⚠️ **v3.7.0 飞书 wiki 抓取方式变更**：\n> - **旧版本（v3.6.0 及更早）**：用 WebFetch 抓取飞书 wiki 内容，但实测会严重截断（200-1000 字符，完整文章应有 3K-25K 字符）。第十批 33 篇飞书 wiki 文章转录时，19 篇被 WebFetch 截断，导致飞书云盘上保存的内容大量丢失。\n> - **新版本（v3.7.0）**：改用 `lark-cli docs +fetch --doc <url> --doc-format markdown --scope full` 抓取完整内容。lark-cli 通过用户身份认证，可读取全文，实测 33 篇全部完整获取（800-24000 字符）。\n> - WebFetch 对飞书 wiki 的截断问题源于飞书 wiki 页面需 JS 渲染 + 登录认证，WebFetch 无法处理。lark-cli 通过官方 OpenAPI 直接获取结构化内容，无此问题。\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 依赖 | 说明 |\n|--------|------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` 环境变量 | 本地保存到指定目录，带 frontmatter（默认：`E:\\Obsidian-Vault\\00-Inbox`） |\n| 飞书云盘 | `lark-cli`（用户身份登录） | **v3.6.0 改造**：用 `lark-cli drive +upload` 上传 .md 原文件到用户云盘根目录，用户在飞书\"我的空间 > 云盘\"立即可见。无需 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | **云端 API v1.1.7**，两步流程存入知识库，参考 `references/ima-setup.md` |\n\n### 飞书云盘配置（v3.6.0）\n\n飞书存储改为依赖 `lark-cli`（用户身份），不再使用应用身份：\n\n```bash\n# 1. 安装 lark-cli（一次性）\nnpm i -g @larksuiteoapi/lark-cli\n\n# 2. 用户身份登录（一次性，浏览器授权）\nlark-cli auth login\n\n# 3. 验证身份\nlark-cli whoami\n# 应显示：identity: user, tokenStatus: ready\n```\n\n> **v3.6.0 变更说明**：旧版本用 `FEISHU_APP_ID`+`FEISHU_APP_SECRET`（应用身份 tenant_access_token）创建在线 docx，文档归属应用而非用户，用户在飞书\"我的空间\"看不到。v3.6.0 改用 lark-cli 用户身份上传 .md 原文件到云盘，立即可见。\n>\n> 旧的 `feishu_client.py` 已标记为废弃，保留供历史参考，新流程不再调用。\n\n### Obsidian Vault 路径配置\n跨平台支持，通过环境变量 `OBSIDIAN_VAULT_PATH` 配置：\n\n```bash\n# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian-Vault\\00-Inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian-Vault\\00-Inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian-Vault/00-Inbox\n```\n\n如果未设置，默认使用：\n- Windows: `E:\\Obsidian-Vault\\00-Inbox`\n- macOS/Linux: `~/Obsidian-Vault/00-Inbox`\n\n## 一键保存到所有目的地\n\n使用 `web_to_all.py` 一键转换并保存到 Obsidian/飞书/IMA：\n\n```bash\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian\n```\n\n## 安全配置\n\n⚠️ **凭证必须通过环境变量配置**，禁止硬编码：\n\n### 飞书配置\n\n飞书存储使用 `lark-cli`（用户身份），无需环境变量。配置方法见上方 [飞书云盘配置（v3.6.0）](#飞书云盘配置v360) 章节。\n\n> **v3.6.0 废弃**：旧的 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` 环境变量不再使用（应用身份创建的在线 docx 用户不可见）。`feishu_client.py` 保留但已废弃。\n\n### ima 配置\n\n```bash\n# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> ⚠️ **v3.0 变更**：环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`（旧名仍兼容回退）。IMA 存储从\"笔记本\"改为\"知识库\"两步流程。\n\n参考 [references/ima-setup.md](references/ima-setup.md) 获取凭证。\n\n## 工作流\n\n### 步骤 1：转换为 Markdown\n\n```bash\npython3 scripts/web_to_md.py --url \"<url_or_path>\" --output <output.md>\n```\n\n路由逻辑：\n- **X/Twitter** → x-tweet-fetcher 抓取 JSON → tweet_to_md.py 结构化转换（逐字转录）\n- **飞书 wiki**（`*.feishu.cn/wiki/`）→ **lark-cli docs +fetch** 抓取完整 Markdown（v3.7.0）→ 检查原文链接 → 有则尝试抓取原文（更长则覆盖）\n- **公众号**（`mp.weixin.qq.com`）→ markitdown 转换，反爬时自动 fallback 到移动端 UA\n- **其他网页/本地文件** → markitdown 直接转换\n\n> **v3.4.0 X 链接转录流程修正**：\n> - 飞书 wiki 中发现 X 原文链接时，用 **x-tweet-fetcher**（`web_to_md.py`）抓取完整长文（10K-15K 字符）\n> - **不用 WebFetch**（对 X 链接超时失败率高）\n> - x-tweet-fetcher 失败时降级到飞书 wiki 内容（降级机制）\n> - 全文完整性验证：转录后检查内容长度，<500 字符时警告可能不完整\n\n> **v3.3.0 飞书 wiki 原文链接优先转录**：\n> - 抓取飞书 wiki 后，检查文章头部是否有\"原文链接\"（如 `🔗 原文链接：[url]`）\n> - 有原文链接 → 优先抓取原文链接内容（公众号/X 等），获得更完整的正文和图片\n> - 无原文链接 → 用飞书 wiki 内容\n> - IMA 存放：有公众号原文链接 → import_urls（保留图片）；无 → 纯文本笔记\n\n> **v3.0 新增信源支持**：\n> - 飞书 wiki 文档：通过 WebFetch 转录飞书知识库文章全文\n> - 公众号反爬 fallback：markitdown 返回验证页时自动切换移动端 UA 重试\n\n> **v3.5.0 新增**：\n> - Obsidian 文件命名升级：`YYYYMMDD-标题-关键信息.md`（如 `20260718-数字人口播实战攻略-数字人、口播、heygen.md`）\n> - 关键信息由 AI 从标题和内容提取 2-4 个关键词，用顿号\"、\"分隔\n> - 未提供 keywords 时 fallback 到来源（waytoagi/wechat/x/github）\n> - CLI 新增 `--keywords` 参数；`save_fetched.py` JSON 配置新增 `keywords` 字段\n\n> **v3.6.0 飞书存储改造**：\n> - 飞书存储从应用身份（`FeishuClient.create_document` 创建在线 docx）改为用户身份（`lark-cli drive +upload` 上传 .md 原文件到云盘）\n> - 旧版本文档归属应用，用户在飞书\"我的空间\"看不到；新版文件归属用户，立即可见\n> - 不再需要 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` 环境变量，改用 `lark-cli auth login` 用户授权\n> - 飞书上传依赖 Obsidian 保存的 .md 文件路径，Obsidian 失败时飞书自动跳过\n> - `feishu_client.py` 标记为废弃，保留供历史参考\n> - `save_to_feishu()` 函数签名变更：`(content, title)` → `(md_file_path, title=None)`\n\n> **v3.7.0 飞书 wiki 抓取改造**：\n> - 飞书 wiki 抓取从 WebFetch（截断严重，200-1000 字符）改为 `lark-cli docs +fetch`（完整内容，3K-25K 字符）\n> - `web_to_md.py` 新增 `_convert_feishu_wiki()` 函数和 `feishu_wiki` source 类型\n> - `convert()` 函数新增 feishu_wiki 分支，自动调用 lark-cli\n> - 飞书 wiki 原文链接优先转录流程：lark-cli 抓取后检测原文链接，自动用 markitdown 或 x-tweet-fetcher 抓取原文（更长则覆盖）\n> - 实测数据：第十批 33 篇飞书 wiki 文章转录，v3.6.0 用 WebFetch 时 19 篇被截断，v3.7.0 用 lark-cli 后 33 篇全部完整\n\n> **v3.2.0 新增**：\n> - Obsidian 文件命名规范化：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n> - 来源自动提取：从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n> - 飞书 wiki 原文链接优先转录：抓取飞书 wiki 后检查原文链接，有则优先抓取原文内容（更完整）\n> - Windows 文件名安全：禁止字符替换为下划线，中文标点（含：）保留\n\n> **v3.1 新增**：\n> - 批量模式断点恢复：崩溃后重跑自动跳过已完成 URL（`.progress.json` 进度文件）\n> - Obsidian frontmatter 自动 tags：根据 URL 来源分类标签\n> - 推文结构化转换通用化：去硬编码，基于启发式规则识别段落标题\n> - subprocess 加 120 秒 timeout：防止网络异常永久挂起\n> - 公众号正文提取改进：保留图片、段落结构、引用块\n\n### 步骤 2：存入目的地\n\n#### Obsidian Vault\n\n文件名规则：`YYYYMMDD-标题-关键信息.md`（v3.5.0）\n- **关键信息**：AI 从标题和内容提取 2-4 个关键词，用顿号\"、\"分隔\n- 未提供关键词时 fallback 到来源（waytoagi/feishu/x/wechat 等）\n- 示例：`20260718-数字人口播实战攻略-数字人、口播、heygen.md`\n- 旧示例（v3.2.0）：`20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`\n\n```python\nfrom scripts.web_to_all import save_to_obsidian\nfilepath = save_to_obsidian(markdown_content, title, url, keywords=\"数字人、口播、heygen\")  # v3.5.0 keywords\n```\n\n#### 飞书云盘（v3.6.0）\n\n用 `lark-cli drive +upload` 上传 .md 原文件到用户云盘根目录。文件归属于用户身份，立即可见。\n\n```python\nfrom scripts.web_to_all import save_to_obsidian, save_to_feishu\n\n# v3.6.0 流程：先存 Obsidian 得到文件路径，再用该路径上传飞书\nobs_path = save_to_obsidian(markdown_content, title, url, keywords=\"关键词1、关键词2\")\nfeishu_result = save_to_feishu(obs_path, title)  # 上传 .md 文件到飞书云盘\nprint(f\"飞书云盘 URL: {feishu_result['url']}\")\n```\n\n或者直接命令行：\n\n```bash\n# 先用 web_to_all.py 一次性三处存放\npython3 scripts/web_to_all.py --url \"<url>\" --keywords \"关键词1、关键词2\"\n# 飞书会自动复用 Obsidian 保存的 .md 文件上传到云盘\n```\n\n> **v3.6.0 变更**：\n> - 旧版本用 `FeishuClient.create_document` 创建在线 docx（应用身份，用户不可见）\n> - 新版本用 `lark-cli drive +upload` 上传 .md 原文件（用户身份，立即可见）\n> - 必须先存 Obsidian 得到文件路径，飞书上传依赖该文件\n> - Obsidian 失败时飞书会自动跳过（输出 `Feishu skipped: Obsidian file not available`）\n\n#### 腾讯 ima（v3.0 — 知识库两步流程 + 图片保留）\n\nIMA 有**两套独立 API**，不可混用：\n- **Notes API**（`/openapi/note/v1/`）：管笔记、笔记本\n- **Knowledge Base API**（`/openapi/wiki/v1/`）：管知识库、知识条目\n\n「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。必须用两步流程。\n\n> **v3.0 核心功能 — 公众号/网页带图片转录**：\n> - 公众号和普通网页 URL 通过 `import_urls` 让 IMA 服务端抓取，**保留原文图片和排版**\n> - X/Twitter 和飞书 wiki 走纯文本笔记（逐字转录），因为 X 要求逐字转录、飞书需登录认证\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 方式1：直接用 save_to_ima（推荐，自动路由）\n# - 公众号/普通网页 URL → import_urls（服务端抓取，保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n\n# 方式2：手动两步流程\nfrom scripts.ima_client import IMAClient\nclient = IMAClient()\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\n# Step 2: 添加到知识库（Wiki API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(note_id=note[\"note_id\"], title=\"标题\", knowledge_base_id=kb_id)\n```\n\n**IMA 存放路由规则（v3.0）**：\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n### 验证连接\n\n```bash\n# 验证飞书（v3.6.0：lark-cli 用户身份）\nlark-cli whoami\n# 应显示：identity: user, tokenStatus: ready\n\n# 验证 ima\npython scripts/ima_client.py --action test\n```\n\n## 故障处理\n\n| 问题 | 解决方案 |\n|------|---------|\n| x.com SSL 超时 | x-tweet-fetcher 使用 FxTwitter API 中转 |\n| markitdown 模块丢失 | `pip install markitdown` |\n| 微信反爬拦截 | markitdown 返回72字符验证页，需 fallback 到 WebFetch 或移动端 UA |\n| 飞书 wiki 内容截断（v3.6.0 旧问题） | **v3.7.0 已修复**。旧版本用 WebFetch 截断严重，升级到 v3.7.0 后改用 `lark-cli docs +fetch` 抓取完整内容 |\n| 飞书 wiki 抓取报\"lark-cli 未安装\" | 运行 `npm i -g @larksuiteoapi/lark-cli` 安装，再 `lark-cli auth login` 用户授权 |\n| 飞书 wiki 抓取报\"lark-cli API 返回 ok=false\" | 1) `lark-cli whoami` 检查登录状态；2) 文档权限不足时联系飞书 wiki 管理员开通访问权限 |\n| 飞书云盘上传失败（v3.6.0） | 1) 运行 `lark-cli whoami` 检查登录状态；2) 未登录则 `lark-cli auth login`；3) lark-cli 未安装则 `npm i -g @larksuiteoapi/lark-cli` |\n| 飞书上传报\"unsafe file path\" | lark-cli `--file` 必须是 cwd 下的相对路径，代码会自动复制到 scripts 目录 |\n| 飞书存储跳过 | Obsidian 失败时飞书会跳过（提示 `Feishu skipped: Obsidian file not available`），先修复 Obsidian 写入权限 |\n| 飞书文档不可见（v3.5 旧版问题） | v3.6.0 已修复。旧版本用应用身份创建 docx 导致不可见，升级到 v3.6.0 后改用 lark-cli 用户身份上传云盘 |\n| 飞书 blocks 400 错误（v3.5 旧版） | v3.6.0 不再创建在线 docx，无 blocks 概念。如使用旧 feishu_client.py：单次最多 50 个 blocks，长文章需分批插入 |\n| ima 凭证无效 | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY`（v3.0） |\n| IMA 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| IMA import_urls 文件夹不存在 | folder_id 不等于 knowledge_base_id，需用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n\n## 依赖与安装\n\n### 完整依赖列表\n\n| 依赖 | 安装命令 | 说明 |\n|------|---------|------|\n| markitdown | `pip install markitdown` | 网页转 Markdown 核心库 |\n| requests | `pip install requests` | HTTP 请求 |\n| python-dotenv | `pip install python-dotenv` | 环境变量管理 |\n| lark-cli | `npm i -g @larksuiteoapi/lark-cli` | **v3.6.0 飞书云盘上传必需**，运行 `lark-cli auth login` 登录 |\n| x-tweet-fetcher | 克隆到 `~/.aily/workspace/skills/x-tweet-fetcher` | X/Twitter 专用抓取（可选） |\n\n### 一键安装所有依赖\n\n```bash\n# 安装 Python 依赖\npip install markitdown requests python-dotenv\n\n# 安装 lark-cli 并登录（v3.6.0 飞书存储必需）\nnpm i -g @larksuiteoapi/lark-cli\nlark-cli auth login\n```\n\n### x-tweet-fetcher（可选，仅用于 X/Twitter）\n```bash\n# 克隆到技能目录\ncd ~/.aily/workspace/skills\ngit clone https://github.com/EdwardWason/x-tweet-fetcher.git\n```\n\n如果不安装 x-tweet-fetcher，X/Twitter 链接将使用 markitdown 直接处理。\n\n---\n\n## 安全声明\n\n### 🔒 权限声明（MCP Least Privilege）\n\n本技能运行时需要以下权限：\n\n| 权限类型 | 具体内容 | 用途 |\n|---------|---------|------|\n| **文件读取** | 用户指定的 URL、本地输入文件、Obsidian 保存后的 .md 文件（飞书上传源） | 转换源内容、上传到飞书云盘 |\n| **文件写入** | Obsidian Vault 目录（`OBSIDIAN_VAULT_PATH`）、scripts 目录下的临时 .md 文件（上传后删除） | 存储转换结果、临时复制给 lark-cli 上传 |\n| **网络请求** | 用户提供的 URL（网页抓取）、腾讯 IMA OpenAPI | 抓取内容和存储到 IMA |\n| **subprocess** | `lark-cli`（v3.6.0 飞书云盘上传）、x-tweet-fetcher（可选，仅 X/Twitter 链接） | 飞书云盘上传、X 平台内容抓取 |\n| **环境变量** | `IMA_OPENAPI_CLIENTID`、`IMA_OPENAPI_APIKEY`、`OBSIDIAN_VAULT_PATH` | 凭证和路径配置 |\n\n> ⚠️ 本技能**不读取** Windows registry、不读取 GitHub token、不调用 GitHub API、不执行 git 操作。仅做文档转换和三处存放。\n>\n> **v3.6.0 变更**：不再需要 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` 环境变量，飞书凭证由 lark-cli 通过用户授权管理（`lark-cli auth login`）。\n\n### ⚠️ 用户警告（运行前必读）\n\n1. **数据外传**：运行本技能会将您提供的 URL 或本地文件内容上传到以下第三方云端服务：\n   - **飞书云盘**（v3.6.0：通过 lark-cli 用户身份上传，需预先 `lark-cli auth login`）\n   - **腾讯 IMA 知识库**（需 `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY`）\n   - 如果内容包含敏感、机密或受监管数据，请先确认是否允许上传到这些服务\n\n2. **本地写入**：默认会向 Obsidian Vault 目录写入 Markdown 文件。可通过 `--no-obsidian` 禁用本地写入\n\n3. **选择性禁用**：支持通过参数禁用特定存储目的地：\n   - `--no-feishu`：跳过飞书云盘\n   - `--no-ima`：跳过腾讯 IMA\n   - `--no-obsidian`：跳过本地 Obsidian\n\n4. **IMA URL 导入**：公众号/普通网页 URL 会通过 IMA `import_urls` 让 IMA 服务端抓取，URL 会被发送给腾讯服务器\n\n5. **飞书云盘文件归属**（v3.6.0 新增）：lark-cli 上传的文件归属于 lark-cli 当前登录用户，文件出现在用户飞书\"我的空间 > 云盘\"根目录\n\n### 🔒 安全设计原则\n\n1. **凭证安全**\n   - IMA 凭证通过环境变量配置，**无硬编码**\n   - 飞书凭证由 lark-cli 管理（用户授权），不再需要环境变量（v3.6.0）\n   - 支持 `IMA_OPENAPI_CLIENTID`, `IMA_OPENAPI_APIKEY`（v3.0）\n   - 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退\n   - 旧变量 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` 已废弃（v3.6.0），保留供 feishu_client.py 历史参考\n\n2. **文件操作**\n   - 默认写入 Obsidian Vault 目录（可通过 `OBSIDIAN_VAULT_PATH` 配置）\n   - 飞书上传前会临时复制 .md 文件到 scripts 目录（lark-cli 限制），上传后立即删除\n   - 支持通过 `--no-feishu` / `--no-ima` / `--no-obsidian` 选择性禁用功能\n   - 不扫描、不读取用户目录下的其他文件\n\n3. **隐私保护**\n   - 不读取任何未经授权的用户配置文件\n   - 所有网络请求仅针对用户提供的 URL\n   - 本地文件仅用于转换，不主动扫描\n\n4. **权限透明**\n   - 文件写入范围：Obsidian Vault 目录、临时 Markdown 文件（上传后删除）\n   - 文件读取范围：用户指定的 URL、本地输入文件、Obsidian 保存后的 .md 文件\n\nFile v3.7.0:README.md\n\n[English](./README.en.md) | 中文\n\n# web-to-FIM\n\n> 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 核心功能\n\n### 支持的信源（7 类 URL + 本地文件）\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | **lark-cli docs +fetch**（v3.7.0，完整内容） |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n本地文件支持：PDF、Word、PPT、Excel、图片、音频、CSV/JSON/XML 等。\n\n### 三处存放\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地 Markdown + frontmatter + tags（默认 `E:\\Obsidian-Vault\\00-Inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端团队协作 |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI 原生知识库（FIM知识库） |\n\n## 快速开始\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## 环境变量配置\n\n```bash\n# Obsidian Vault path (optional, has default)\n$env:OBSIDIAN_VAULT_PATH = \"E:\\Obsidian-Vault\\00-Inbox\"\n\n# Feishu credentials\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> 凭证必须通过环境变量配置，禁止硬编码。旧变量名 `IMA_CLIENT_ID` / `IMA_API_KEY` 仍兼容回退。\n\n## 使用示例\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## 触发词\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\n当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n\n## 验证连接\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA 智能路由（v3.0）\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号 / 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| X/Twitter | 纯文本笔记（逐字转录） | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n\n## 版本历史\n\n- **v3.7.0**：飞书 wiki 抓取改造——从 WebFetch（截断严重，200-1000 字符）改为 `lark-cli docs +fetch`（完整内容，3K-25K 字符）；实测 33 篇文章全部完整获取\n- **v3.6.0**：飞书存储改造——从应用身份创建在线 docx 改为 `lark-cli drive +upload` 上传 .md 原文件到用户云盘，立即可见\n- **v3.5.0**：Obsidian 文件命名升级为 `YYYYMMDD-标题-关键信息.md`（AI 提取 2-4 个关键词）\n- **v3.4.0**：X 链接转录流程修正——用 x-tweet-fetcher 替代 WebFetch；安全修复（ClawHub SkillSpector v3.3.0 findings）\n- **v3.3.0**：原文链接自动提取；IMA 路由精细化；飞书 wiki 自动路由函数\n- **v3.2.0**：Obsidian 文件命名规范化；飞书 wiki 原文链接优先转录；Windows 文件名安全\n- **v3.1.0**：批量模式断点恢复；Obsidian frontmatter 自动 tags；推文结构化转换通用化；subprocess 120 秒 timeout；公众号正文提取改进\n- **v3.0.0**：IMA 改用知识库两步流程；公众号/网页带图片转录（import_urls）；新增飞书 wiki 信源；公众号反爬 fallback\n- **v2.x**：基础三处存放功能；X/Twitter 逐字转录；飞书云文档集成\n\n详见 [CHANGELOG.md](./CHANGELOG.md)。\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.7.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"web-to-fim\",\n  \"version\": \"3.7.0\",\n  \"publishedAt\": 1784387155458\n}\n\nFile v3.7.0:references/feishu-blocks.md\n\n# 飞书云文档 Block 类型映射表\n\n> 飞书 Docx API 的 block_type 枚举值。创建文档 blocks 时必须使用正确的 block_type，否则返回 400 Bad Request。\n\n## block_type 完整映射\n\n| block_type | 名称 | Markdown 对应 | block 字段名 |\n|-----------|------|-------------|------------|\n| 1 | Page（页面根块） | — | `page` |\n| 2 | Text（文本） | 普通段落 | `text` |\n| 3 | Heading1（一级标题） | `# ` | `heading1` |\n| 4 | Heading2（二级标题） | `## ` | `heading2` |\n| 5 | Heading3（三级标题） | `### ` | `heading3` |\n| 6 | Heading4（四级标题） | `#### ` | `heading4` |\n| 7 | Heading5（五级标题） | `##### ` | `heading5` |\n| 8 | Heading6（六级标题） | `###### ` | `heading6` |\n| 9 | Heading7（七级标题） | — | `heading7` |\n| 10 | Heading8（八级标题） | — | `heading8` |\n| 11 | Heading9（九级标题） | — | `heading9` |\n| 12 | Bullet（无序列表） | `- ` 或 `* ` | `bullet` |\n| 13 | Ordered（有序列表） | `1. ` | `ordered` |\n| 14 | Code（代码块） | ` ``` ` | `code` |\n| 15 | Quote（引用） | `> ` | `quote` |\n\n## 常见错误\n\n| 错误 | 正确值 | 说明 |\n|------|-------|------|\n| Code 用 block_type=2 | **block_type=14** | 2 是 Text，不是 Code |\n| Quote 用 block_type=11 | **block_type=15** | 11 是 Heading9，不是 Quote |\n\n## Block 结构示例\n\n### Text（block_type=2）\n\n```json\n{\n    \"block_type\": 2,\n    \"text\": {\n        \"elements\": [{\"text_run\": {\"content\": \"文本内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Heading1（block_type=3）\n\n```json\n{\n    \"block_type\": 3,\n    \"heading1\": {\n        \"elements\": [{\"text_run\": {\"content\": \"标题内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Bullet（block_type=12）\n\n```json\n{\n    \"block_type\": 12,\n    \"bullet\": {\n        \"elements\": [{\"text_run\": {\"content\": \"列表项\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Code（block_type=14）\n\n```json\n{\n    \"block_type\": 14,\n    \"code\": {\n        \"elements\": [{\"text_run\": {\"content\": \"code content\"}}],\n        \"style\": {\"language\": 1}\n    }\n}\n```\n\n### Quote（block_type=15）\n\n```json\n{\n    \"block_type\": 15,\n    \"quote\": {\n        \"elements\": [{\"text_run\": {\"content\": \"引用内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n## 关键约束\n\n### 1. elements 中不要加多余字段\n\n```json\n// ❌ 错误 — 多了 \"type\" 字段\n{\"text_run\": {\"type\": \"text_run\", \"content\": \"文本\"}}\n\n// ✅ 正确\n{\"text_run\": {\"content\": \"文本\"}}\n```\n\n### 2. 空行不要创建空文本块\n\n```python\n# ❌ 错误 — 空行创建空块会导致 400\nif not stripped:\n    blocks.append({\"block_type\": 2, \"text\": {\"elements\": [{\"text_run\": {\"content\": \"\"}}]}})\n\n# ✅ 正确 — 空行直接跳过\nif not stripped:\n    continue\n```\n\n### 3. 图片块需要预上传 token\n\n图片不能直接用 URL，必须先通过飞书上传 API 获取 `file_token`，再创建图片块。当前实现暂时跳过图片。\n\n### 4. 单次请求最多 50 个 blocks\n\n```\nPOST /docx/v1/documents/{document_id}/blocks/{document_id}/children\n```\n\n**payload 中 `children` 数组最多 50 个 block**。长文章必须分批插入：\n\n```python\nfor i in range(0, len(blocks), 50):\n    batch = blocks[i:i+50]\n    requests.post(url, headers=headers, json={\"children\": batch})\n```\n\n### 5. payload 中不要传 index\n\n```json\n// ❌ 错误 — index=-1 可能导致问题\n{\"children\": blocks, \"index\": -1}\n\n// ✅ 正确 — 不传 index，默认追加到末尾\n{\"children\": blocks}\n```\n\n## API 端点\n\n| 操作 | 方法 | URL |\n|------|------|-----|\n| 创建文档 | POST | `/docx/v1/documents` |\n| 插入 blocks | POST | `/docx/v1/documents/{document_id}/blocks/{document_id}/children` |\n| 获取文档信息 | GET | `/docx/v1/documents/{document_id}` |\n\n## 认证\n\n```\nAuthorization: Bearer {tenant_access_token}\nContent-Type: application/json\n```\n\n获取 token：`POST /auth/v3/tenant_access_token/internal`，payload 为 `{\"app_id\": \"...\", \"app_secret\": \"...\"}`。\n\nFile v3.7.0:references/feishu-setup.md\n\n# 飞书云文档 API 配置指南\n\n## 获取凭证\n\n### 步骤 1: 创建飞书应用\n\n1. 访问 [飞书开放平台](https://open.feishu.cn/)\n2. 登录后进入「开发者后台」\n3. 点击「创建应用」，填写应用名称和描述\n4. 获取 **App ID** 和 **App Secret**\n\n### 步骤 2: 配置权限\n\n在应用后台开启以下权限：\n\n| 权限名称 | 权限说明 | 必要性 |\n|---------|---------|--------|\n| `docx.document:readonly` | 读取云文档 | 可选 |\n| `docx.document:write` | 创建/编辑云文档 | 必须 |\n| `drive:drive:folder` | 云文档文件夹操作 | 必须 |\n| `sheets:Spreadsheet:readonly` | 读取表格 | 可选 |\n\n### 步骤 3: 发布应用\n\n1. 在「版本管理与发布」中创建版本\n2. 选择「发布」并等待审核（或自建企业直接通过）\n\n## 本地配置\n\n### 设置环境变量\n\n```bash\n# Windows PowerShell\n$env:FEISHU_APP_ID=\"your_app_id\"\n$env:FEISHU_APP_SECRET=\"your_app_secret\"\n\n# Linux/macOS\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n```\n\n### 验证配置\n\n```python\nfrom feishu_client import FeishuClient\n\nclient = FeishuClient()\nif client.test_connection():\n    print(\"✅ 飞书连接成功\")\nelse:\n    print(\"❌ 飞书连接失败，请检查凭证\")\n```\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **永远不要**将 `.env` 文件或包含真实凭证的文件提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 生产环境建议使用密钥管理服务（如 AWS Secrets Manager）\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `invalid_app_id` | 检查 App ID 是否正确 |\n| `app_secret` 错误 | 在飞书开放平台重置 App Secret |\n| 权限不足 | 在应用后台添加所需权限并重新发布 |\n| 签名校验失败 | 确保使用 HTTPS，检查时间戳是否正确 |\n\nFile v3.7.0:references/ima-setup.md\n\n# 腾讯 IMA 知识库 API 配置指南（v3.0 — IMA OpenAPI v1.1.7）\n\n> ⚠️ **v3.0 重大变更**：\n> - API 端点从 `/v1/note/create` 迁移到 `/openapi/note/v1/import_doc`\n> - Base URL 从 `https://ima.im.qq.com/openapi` 改为 `https://ima.qq.com`\n> - 环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`\n> - 存储模式从\"笔记本\"改为\"知识库\"两步流程\n\n## 两套 API 系统（不可混用）\n\nIMA 有两套完全独立的 API，对应 UI 中两个不同的标签页：\n\n| API 系统 | 路径前缀 | 管理对象 | UI 对应 |\n|---------|---------|---------|---------|\n| **Notes API** | `/openapi/note/v1/` | 笔记、笔记本 | IMA「笔记本」标签页 |\n| **Knowledge Base API** | `/openapi/wiki/v1/` | 知识库、知识条目 | IMA「知识库」标签页 |\n\n**关键区别**：「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。\n\n## 获取凭证\n\n### 步骤 1: 访问 IMA 开放平台\n\n打开 [ima.qq.com/agent-interface](https://ima.qq.com/agent-interface)\n\n### 步骤 2: 登录并获取凭证\n\n1. 使用 QQ 或微信扫码登录\n2. 在「Agent 接口」页面获取凭证：\n   - **Client ID**: 应用标识\n   - **Api Key**: API 密钥\n\n### 步骤 3: 复制凭证\n\n```text\nClient ID: your_client_id_here\nApi Key: your_api_key_here\n```\n\n## 本地配置\n\n### 设置环境变量（v3.0）\n\n```bash\n# Windows PowerShell — 持久化设置\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_CLIENTID\", \"your_client_id\", \"User\")\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_APIKEY\", \"your_api_key\", \"User\")\n\n# Windows PowerShell — 临时设置（当前会话）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Linux/macOS\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n```\n\n> 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退，但建议迁移到新名。\n\n### 可选：指定知识库\n\n```bash\n$env:IMA_KB_NAME = \"FIM知识库\"  # 默认值\n```\n\n### 验证配置\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nif client.test_connection():\n    print(\"✅ IMA 连接成功\")\nelse:\n    print(\"❌ IMA 连接失败，请检查凭证\")\n```\n\n## API 基础信息（v1.1.7）\n\n- **Base URL**: `https://ima.qq.com`\n- **认证方式**: Header `ima-openapi-clientid` + `ima-openapi-apikey`\n- **数据格式**: JSON\n- **无需本地客户端**: 所有操作通过云端 API 完成\n\n### Notes API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 创建笔记 | `POST /openapi/note/v1/import_doc` | 从 Markdown 创建笔记 |\n| 追加内容 | `POST /openapi/note/v1/append_doc` | 向现有笔记追加内容 |\n| 获取笔记内容 | `POST /openapi/note/v1/get_doc_content` | 读取笔记纯文本/JSON |\n| 列出笔记 | `POST /openapi/note/v1/list_note` | 列出笔记本中的笔记 |\n| 搜索笔记 | `POST /openapi/note/v1/search_note` | 按标题/正文搜索 |\n| 列出笔记本 | `POST /openapi/note/v1/list_notebook` | 列出所有笔记本 |\n\n### Knowledge Base API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 搜索知识库 | `POST /openapi/wiki/v1/search_knowledge_base` | 按名称搜索，返回 `kb_id` |\n| 可添加知识库列表 | `POST /openapi/wiki/v1/get_addable_knowledge_base_list` | 列出可添加内容的知识库 |\n| 添加知识 | `POST /openapi/wiki/v1/add_knowledge` | 添加笔记/网页/文件到知识库 |\n| 浏览知识库 | `POST /openapi/wiki/v1/get_knowledge_list` | 浏览知识库内容 |\n| 导入 URL | `POST /openapi/wiki/v1/import_urls` | 服务端抓取 URL（保留图片） |\n\n## 存储流程\n\n### 流程 1：纯文本笔记（X/Twitter/飞书/手动内容）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\n\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\nnote_id = note[\"note_id\"]\n\n# Step 2: 添加到知识库（Knowledge Base API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(\n    note_id=note_id,\n    title=\"标题\",\n    knowledge_base_id=kb_id,  # media_type=11, note_info.content_id=note_id\n)\n```\n\n### 流程 2：URL 导入（公众号/普通网页 — 保留图片）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\n\n# IMA 服务端抓取 URL，保留图片和排版\nresults = client.import_urls(\n    knowledge_base_id=kb_id,\n    urls=[\"https://mp.weixin.qq.com/s/xxxxx\"],\n)\n```\n\n### 智能路由（推荐用 save_to_ima）\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 自动路由：\n# - 公众号/网页 URL → import_urls（保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n```\n\n## add_knowledge 的 media_type 枚举\n\n| media_type | 类型 | note_info/web_info 字段 |\n|-----------|------|------------------------|\n| 2 | 网页 | `web_info.content_id=<url>` |\n| 6 | 公众号文章 | 同上，URL 匹配 `mp.weixin.qq.com/s` |\n| 11 | 笔记 | `note_info.content_id=<note_id>` |\n| 7 | Markdown | 需先 create_media + COS 上传 |\n\n## IMA 存放路由规则\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **Api Key 等同于密码**，不要泄露给他人\n- 永远不要将真实凭证提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 定期轮换 Api Key\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `401 Unauthorized` | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY` 是否正确 |\n| `404 Not Found` | API 端点已变更，确认用 `/openapi/note/v1/import_doc`（非 `/v1/note/create`） |\n| 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| `import_urls` 文件夹不存在 | folder_id 不等于 knowledge_base_id，用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n| `code=210001` 参数错误 | 检查请求体 JSON 格式，`content_format` 必须为 1（MARKDOWN） |\n\nFile v3.7.0:CHANGELOG.md\n\n# Changelog\n\n本文件记录 web-to-fim 技能的版本演进。版本号遵循 [语义化版本](https://semver.org/)。\n\n## [3.7.0] - 2026-07-18\n\n### 🚨 破坏性变更（飞书 wiki 抓取方式改造）\n\n**问题根因**：v3.6.0 及更早版本抓取飞书 wiki（`*.feishu.cn/wiki/`）内容时使用 WebFetch，但 WebFetch 对飞书 wiki 页面抓取不稳定，常返回 200-1000 字符截断内容（完整文章应有 3K-25K 字符）。\n\n**实测数据**：第十批 33 篇飞书 wiki 文章批量转录任务中，19 篇被 WebFetch 截断，导致飞书云盘上保存的 .md 文件内容大量丢失，用户反馈\"多个文件都只转录了一小点，很多文章都没有转录完成\"。\n\n**修复方案**：飞书 wiki 抓取改用 `lark-cli docs +fetch --doc <url> --doc-format markdown --scope full` 获取完整内容。lark-cli 通过用户身份认证，直接调用飞书 OpenAPI 读取结构化文档内容，无 JS 渲染或登录认证问题。实测 33 篇文章全部完整获取（800-24000 字符，部分短文如活动公告本身即短）。\n\n### 变更\n- **`web_to_md.py` 新增 `_convert_feishu_wiki()` 函数**：调用 lark-cli docs +fetch 获取飞书 wiki 完整 Markdown 内容\n- **`_detect_source()` 新增 `feishu_wiki` source 类型**：识别 `feishu.cn/wiki` 和 `larkoffice.com/wiki` URL\n- **`convert()` 函数新增 feishu_wiki 分支**：自动路由到 `_convert_feishu_wiki()`\n- **`web_to_all.py` `_process_single()` 飞书 wiki 原文链接优先转录流程更新**：\n  - 飞书 wiki 内容已通过 lark-cli 完整获取（不再依赖 WebFetch）\n  - 检测到原文链接时，自动用 markitdown 或 x-tweet-fetcher 抓取原文\n  - 原文比飞书 wiki 内容长则覆盖，否则保留飞书 wiki 内容\n  - 公众号/普通网页原文：v3.7.0 改为自动 markitdown 抓取（v3.6.0 是仅打印提示让 AI 调用 WebFetch）\n\n### 弃用\n- **WebFetch 抓取飞书 wiki**：v3.7.0 起弃用。`_fetch_feishu_wiki_via_webfetch()` 保留但不再调用，仅作历史参考。AI 流程中遇到飞书 wiki URL 不应再调用 WebFetch，应让 `web_to_md.py convert()` 自动路由到 lark-cli。\n\n### 验证\n- ✅ 第十批 33 篇飞书 wiki 文章全部完整转录（v3.6.0 时 19 篇截断）\n- ✅ 飞书云盘 33 个 .md 文件内容完整（抽查 5 篇 19007/24247/1080/17160/10010 字符）\n- ✅ Obsidian `E:\\Obsidian-Vault\\00-Inbox\\` 33 个 20260718-*.md 文件全部完整\n- ✅ lark-cli docs +fetch 对各种长度飞书 wiki 都稳定（最短 793 字符，最长 23931 字符）\n\n## [3.6.0] - 2026-07-18\n\n### 🚨 破坏性变更（飞书存储方式改造）\n\n**问题根因**：v3.5.0 及更早版本飞书存储用 `FeishuClient.create_document` 创建在线 docx，使用应用身份（tenant_access_token），文档归属应用而非用户。用户反馈\"这几天转换的文档一篇都没有看到\"——文档创建成功但用户在飞书\"我的空间\"完全不可见。\n\n**修复方案**：飞书存储改用 `lark-cli drive +upload` 上传 .md 原文件到用户云盘根目录（用户身份，user_access_token），文件归属于用户，立即可见。参考 transcript-crafter 技能的存放方式。\n\n### 变更\n- **`save_to_feishu()` 函数签名变更**：`(content: str, title: str)` → `(md_file_path: str, title: str = None)`\n  - 不再接收 markdown content，改为接收本地 .md 文件路径\n  - 飞书上传依赖 Obsidian 保存的 .md 文件作为源\n- **`web_to_all.py` 不再 import `FeishuClient`**：避免触发 deprecation warning\n- **`_process_single()` 调用顺序变更**：先存 Obsidian 得到文件路径，再上传飞书。Obsidian 失败时飞书自动跳过（提示 `Feishu skipped: Obsidian file not available`）\n- **`save_fetched.py` 调用变更**：传 `obs_path` 给 `save_to_feishu()`，不再传 content\n- **`feishu_client.py` 标记为废弃**：保留供历史参考，主流程不再调用。导入时触发 `DeprecationWarning`\n\n### 新增\n- **lark-cli 依赖**：飞书存储改为依赖 `lark-cli`（npm 全局包），需预先 `lark-cli auth login` 用户授权\n- **临时文件复制机制**：lark-cli `--file` 限制必须是 cwd 下相对路径，代码会自动把 Obsidian .md 文件复制到 scripts 目录上传，上传后立即删除\n- **JSON 输出解析**：lark-cli 输出多行 JSON（含 `Uploading:` 提示行），用 `find('{')` 到 `rfind('}')` 提取完整 JSON 段\n\n### 废弃\n- **`FEISHU_APP_ID` / `FEISHU_APP_SECRET` 环境变量**：不再使用，飞书凭证由 lark-cli 管理\n- **`feishu_client.py`**：保留但已废弃，详见文件头 DEPRECATED 注释\n\n### 验证\n- ✅ 测试上传成功：文件 URL `https://aipeanut.feishu.cn/file/ZZ4ibHqj2obC4wxzxNgcY5znnPf`\n- ✅ 文件归属用户身份，飞书\"我的空间 > 云盘\"立即可见\n- ✅ Obsidian 失败时飞书正确跳过，不影响其他存储\n\n## [3.5.0] - 2026-07-18\n\n### 新增\n- **Obsidian 文件命名升级**：从 `YYYYMMDD-标题-来源.md` 升级为 `YYYYMMDD-标题-关键信息.md`\n  - 关键信息由 AI 从标题和内容提取 2-4 个关键词，用顿号\"、\"分隔\n  - 示例：`20260718-数字人口播实战攻略-数字人、口播、heygen.md`\n  - 未提供 keywords 时 fallback 到来源（waytoagi/wechat/x/github）\n- **CLI 新增 `--keywords` 参数**：`python web_to_all.py --url <url> --keywords \"数字人、口播、heygen\"`\n- **`save_fetched.py` JSON 配置新增 `keywords` 字段**：批量模式支持每篇文章独立关键词\n- **`save_to_obsidian()` 新增 `keywords` 参数**：编程接口支持\n- **默认 Obsidian Vault 路径变更**：`E:\\Obsidian\\md\\inbox` → `E:\\Obsidian\\md\\00-Inbox`（与 Obsidian Vault 结构对齐）\n\n### 兼容性\n- 未传 `keywords` 参数时 fallback 到原\"来源\"逻辑，向后兼容\n- 已存在的旧命名文件不强制改名（遵循 NAMING-CONVENTIONS.md \"已存在的文件不强制改名\"原则）\n\n## [3.4.0] - 2026-07-12\n\n### 安全修复（ClawHub SkillSpector v3.3.0 findings）\n- **删除误上传的临时脚本**：`_gh_push.py` 和 `_gh_release.py`（v3.3.0 发布时误上传，含 GitHub token 读取和 API 调用，被标记为 MCP Tool Poisoning / Context-Inappropriate Capability）\n- **新增权限声明段落**：MCP Least Privilege — 明确声明文件读取/写入/网络请求/环境变量/subprocess 权限\n- **新增用户警告段落**：Missing User Warnings — 明确告知数据外传到飞书/IMA、本地写入、选择性禁用参数\n- **修正安全声明**：Intent-Code Divergence — 移除\"仅在用户明确指定时写入文件\"的错误描述，改为\"默认写入 Obsidian Vault\"\n- **触发词收窄**：Vague Triggers — 移除过于宽泛的\"转文档\"、\"网页转文档\"，改为更明确的\"抓网页存飞书\"、\"web to feishu\"等\n- **Do NOT 范围扩展**：新增\"普通文档格式转换（非三处存放意图）\"\n\n### 功能修复（X 链接转录流程）\n- **X 链接转录流程修正**：飞书 wiki 中发现 X 原文链接时，用 x-tweet-fetcher 抓取完整长文（10K-15K 字符），不用 WebFetch（超时失败率高）\n- **降级机制**：x-tweet-fetcher 失败时降级到飞书 wiki 内容\n- **全文完整性验证**：转录后检查内容长度，<500 字符时警告可能不完整\n- **内容长度对比**：X 原文内容比飞书 wiki 内容长时才替换，否则保留飞书 wiki 内容\n\n## [3.3.0] - 2026-07-12\n\n### 新增\n- **原文链接自动提取**：`extract_original_url()` 函数从 Markdown 前 800 字符自动识别\"原文链接\"/\"转载自\"/\"本文首发\"等关键词\n- **IMA 路由精细化**：GitHub URL 改为纯文本笔记（IMA 抓取 HTML 页面效果差），不再走 import_urls\n- **飞书 wiki 自动路由函数**：`_is_feishu_wiki()` 和 `_fetch_feishu_wiki_via_webfetch()` 新增\n\n### 修复\n- **IMA 路由规则修正**：原文链接为 GitHub 时，原逻辑走 import_urls 导致 IMA 抓取 HTML 页面内容混乱。改为纯文本笔记存转录 MD\n- **路由规则文档化**：IMA 路由规则精细化（公众号/普通网页→import_urls；X/Twitter/飞书/GitHub→纯文本笔记）\n\n## [3.2.0] - 2026-07-12\n\n### 新增\n- **Obsidian 文件命名规范化**：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n- **来源自动提取**：`_extract_source_name()` 函数从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n- **飞书 wiki 原文链接优先转录**：抓取飞书 wiki 后检查文章头部\"原文链接\"，有则优先抓取原文内容（公众号/X 等），获得更完整的正文和图片\n- **IMA 智能路由优化**：飞书 wiki 有公众号原文链接 → import_urls（保留图片）；无原文链接 → 纯文本笔记\n\n### 修复\n- Windows 文件名安全：禁止字符（`\\ / : * ? \" < > |`）替换为下划线，中文标点（含 `：`）保留\n- 文件名长度限制：标题超过 60 字符自动截断，避免文件名过长\n\n## [3.1.0] - 2026-07-11\n\n### 新增\n- 批量模式断点恢复：自动生成 `.progress.json` 进度文件，崩溃后重跑自动跳过已完成 URL，全部成功后自动清理\n- Obsidian frontmatter 增加 `tags` 字段：根据 URL 来源自动分类标签（x-twitter/wechat/weibo/xiaohongshu/github/youtube/webpage/local-file）\n- `save_to_obsidian` 三级 fallback 机制：重试 3 次 → ASCII 文件名 → 脚本目录 `saved/`\n- `_process_single` 每个存储操作独立 try/except：一处失败不阻断其他存储\n\n### 修复\n- **Critical**: `tweet_to_md.py` 去掉硬编码的段落标题列表，改为通用启发式规则（Emoji 模式匹配 + 数字编号 + 短行特征 + 技术名词后缀）\n- **Critical**: `web_to_md.py` `_run()` 函数加 120 秒 timeout，防止 x-tweet-fetcher 网络异常时永久挂起\n- **Important**: `_fetch_wechat_mobile()` 改进正文提取：保留图片（data-src）、段落结构（`<p>`/`<section>`）、引用块（blockquote），不再丢失内容\n- **Minor**: 标题提取改进：支持从 frontmatter `title:` 提取，fallback 到 URL 域名生成标题，不再出现 `Untitled`\n- **Minor**: `import time` / `import json` 移到文件顶部\n- **Minor**: `.gitignore` 补充 `saved/`、`batch_urls.txt`、`*.progress.json`、`batch_run.log` 等临时文件\n\n## [3.0.2] - 2026-07-11\n\n### 修复\n- 同步本地版本号与 ClawHub 线上版本（本地从 3.0.1 对齐到 3.0.2）\n- 修复 SKILL.md 安全声明章节的 Markdown 语法瑕疵：\n  - 第 261 行 `--no-ima` 反引号缺失\n  - 第 258 / 263 / 268 行 `**文件操作` / `**隐私保护` / `**权限透明` 加粗未闭合\n\n### 文档\n- 新增 CHANGELOG.md，补齐版本演进记录\n\n## [3.0.1] - 2026-07-11\n\n### 修复\n- 更新 ClawHub 页面 Short summary，反映 v3.0 的信源与存储能力\n  - frontmatter description 增加公众号/网页图片保留、飞书 wiki 转录说明\n  - 信源表标注 IMA 存储路由（IMA 笔记 → IMA 知识库）\n\n## [3.0.0] - 2026-07-10\n\n### 新增\n- **IMA 智能路由**：公众号/普通网页 → `import_urls` 服务端抓取，保留原文图片和排版\n- **飞书 wiki 信源**：通过 WebFetch 转录飞书知识库文章全文\n- **公众号反爬 fallback**：markitdown 返回验证页时自动切换移动端 UA 重试\n- **批量模式**：`--urls-file` 参数支持从文件逐行读取 URL 批量处理\n- **试运行模式**：`--dry-run` 参数仅转 Markdown 不入库\n\n### 变更\n- **IMA API 迁移到 v1.1.7**：创建笔记改用 `/openapi/note/v1/import_doc`\n- **IMA 存储从\"笔记本\"改为\"知识库\"两步流程**：\n  1. `create_note` 创建笔记（Notes API）\n  2. `add_note_to_knowledge_base` 添加到知识库（Wiki API）\n- **环境变量更名**：`IMA_CLIENT_ID` / `IMA_API_KEY` → `IMA_OPENAPI_CLIENTID` / `IMA_OPENAPI_APIKEY`（旧名仍兼容回退）\n- X/Twitter 链接强制走纯文本笔记逐字转录，不使用 `import_urls`\n\n### 安全\n- 凭证全部通过环境变量配置，无硬编码\n- 清理临时脚本中的真实 IMA 凭证\n- 完善 .gitignore 排除规则\n\nFile v3.7.0:README.en.md\n\nEnglish | [中文](./README.md)\n\n# web-to-FIM\n\n> Convert any web link or local file into structured Markdown, and store it in three destinations: Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base.\n\n## Core Features\n\n### Supported Sources (7 URL Types + Local Files)\n\n| Source | URL Pattern | Fetch Method |\n|--------|------------|-------------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher (verbatim transcript) |\n| WeChat Article | `mp.weixin.qq.com` | markitdown + mobile UA fallback |\n| Feishu Wiki | `*.feishu.cn/wiki/` | WebFetch full transcript |\n| Xiaohongshu | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| Weibo | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| Any Webpage | other `http(s)://` URLs | markitdown |\n\nLocal file support: PDF, Word, PPT, Excel, images, audio, CSV/JSON/XML, etc.\n\n### Three Destinations\n\n| Destination | Environment Variable | Description |\n|-------------|---------------------|-------------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | Local Markdown + frontmatter + tags |\n| Feishu Cloud Docs | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | Cloud team collaboration |\n| Tencent IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI-native knowledge base (FIM) |\n\n## Quick Start\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"Custom Title\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## Environment Variables\n\n```bash\n# Obsidian Vault path (optional, has default)\nexport OBSIDIAN_VAULT_PATH=~/Obsidian-Vault/00-Inbox\n\n# Feishu credentials\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\nexport IMA_KB_NAME=\"FIM知识库\"\n```\n\n> Credentials must be configured via environment variables, never hardcoded. Legacy variable names `IMA_CLIENT_ID` / `IMA_API_KEY` are still supported as fallback.\n\n## Usage Examples\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## Trigger Words\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\nTriggered when the user provides any URL or local file and requests conversion to a document.\n\n## Verify Connections\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA Smart Routing (v3.0)\n\n| source_url Type | IMA Storage Method | Reason |\n|----------------|-------------------|--------|\n| WeChat / General webpage | `import_urls` (server-side fetch) | Preserve images and layout |\n| X/Twitter | Plain text note (verbatim transcript) | Skill rule requires verbatim |\n| Feishu wiki | Plain text note (verbatim transcript) | Requires login, IMA cannot fetch |\n\n## Version History\n\n- **v3.1.0**: Batch mode checkpoint recovery; Obsidian frontmatter auto tags; generalized tweet structured conversion; subprocess 120s timeout; improved WeChat content extraction\n- **v3.0.0**: IMA switched to knowledge base two-step flow; WeChat/webpage with images (import_urls); added Feishu wiki source; WeChat anti-scraping fallback\n- **v2.x**: Basic three-destination storage; X/Twitter verbatim transcript; Feishu Cloud Docs integration\n\nSee [CHANGELOG.md](./CHANGELOG.md) for details.\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.7.0:skill-card.md\n\n## Description:\n\nWeb To Fim converts web links or local files into structured Markdown and stores the result in an Obsidian vault, Feishu Drive, and Tencent IMA knowledge base.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[edwardwason](https://clawhub.ai/user/edwardwason)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and knowledge workers use this skill to archive web pages, social posts, Feishu wiki pages, and local documents as Markdown while optionally syncing the same material to personal or team knowledge stores.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Selected URLs or local files may be written locally and transferred to Feishu or Tencent IMA.\n\nMitigation: Use --no-feishu and --no-ima unless cloud storage is explicitly required, and avoid processing sensitive or regulated documents.\n\nRisk: Feishu wiki processing may follow content-derived original links.\n\nMitigation: Review Feishu wiki original links before processing and confirm that each linked source is intended for conversion.\n\nRisk: Dependencies and command-line tools affect fetching and cloud upload behavior.\n\nMitigation: Pin and review Python dependencies and external tools before use in sensitive environments.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/edwardwason/skills/web-to-fim)\n- [Feishu setup guide](references/feishu-setup.md)\n- [Feishu block type mapping](references/feishu-blocks.md)\n- [Tencent IMA setup guide](references/ima-setup.md)\n- [Feishu Open Platform](https://open.feishu.cn/)\n- [Tencent IMA agent interface](https://ima.qq.com/agent-interface)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown, local files, cloud-upload actions, and command-line guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Can write converted Markdown locally and upload selected content to Feishu and Tencent IMA when configured.]\n\n## Skill Version(s):\n\n3.7.0 (source: frontmatter, CHANGELOG, server 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 v3.7.0:requirements.txt\n\nrequests\npython-dotenv\n\nArchive v3.4.0: 16 files, 43313 bytes\n\nFiles: _meta.json (129b), CHANGELOG.md (6324b), README.en.md (4142b), README.md (3967b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/save_fetched.py (3424b), scripts/tweet_to_md.py (7319b), scripts/web_to_all.py (18028b), scripts/web_to_md.py (9308b), skill-card.md (2593b), SKILL.md (15592b)\n\nFile v3.4.0:SKILL.md\n\n---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.4.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云文档、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（WebFetch 全文转录 + 原文链接优先转录）；(4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云文档（团队协作）+ IMA 知识库（FIM知识库，AI 原生）。\n  IMA 智能路由：公众号/普通网页 → import_urls 保留图片；X/Twitter/飞书/GitHub → 纯文本笔记逐字转录。\n  飞书 wiki 原文链接优先转录：检查文章头部\"原文链接\"，有则优先抓取原文内容作为最终产物存三处，IMA 只存原文链接地址自动识别。\n  X 链接转录流程：飞书 wiki 中发现 X 原文链接时，用 x-tweet-fetcher 抓取完整长文（10K-15K 字符），失败时降级到飞书 wiki 内容。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：抓网页存飞书、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户明确要求将 URL 或本地文件转存为文档并存储到 Obsidian/飞书/IMA 时触发。\n  Do NOT use for 创建文档内容、编辑飞书文档正文、代码开发、非文档转存任务、普通文档格式转换（非三处存放意图）。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📚 **飞书云文档** - 云端团队协作\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地保存到指定目录，带 frontmatter（默认：`E:\\Obsidian\\md\\inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端服务，参考 `references/feishu-setup.md` |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | **云端 API v1.1.7**，两步流程存入知识库，参考 `references/ima-setup.md` |\n\n### Obsidian Vault 路径配置\n跨平台支持，通过环境变量 `OBSIDIAN_VAULT_PATH` 配置：\n\n```bash\n# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian\\Vault\\inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n```\n\n如果未设置，默认使用：\n- Windows: `E:\\Obsidian\\md\\inbox`\n- macOS/Linux: `~/Obsidian/inbox`\n\n## 一键保存到所有目的地\n\n使用 `web_to_all.py` 一键转换并保存到 Obsidian/飞书/IMA：\n\n```bash\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian\n```\n\n## 安全配置\n\n⚠️ **凭证必须通过环境变量配置**，禁止硬编码：\n\n### 飞书配置\n\n```bash\n# 设置环境变量\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n```\n\n参考 [references/feishu-setup.md](references/feishu-setup.md) 获取凭证。\n\n### ima 配置\n\n```bash\n# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> ⚠️ **v3.0 变更**：环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`（旧名仍兼容回退）。IMA 存储从\"笔记本\"改为\"知识库\"两步流程。\n\n参考 [references/ima-setup.md](references/ima-setup.md) 获取凭证。\n\n## 工作流\n\n### 步骤 1：转换为 Markdown\n\n```bash\npython3 scripts/web_to_md.py --url \"<url_or_path>\" --output <output.md>\n```\n\n路由逻辑：\n- **X/Twitter** → x-tweet-fetcher 抓取 JSON → tweet_to_md.py 结构化转换（逐字转录）\n- **飞书 wiki**（`*.feishu.cn/wiki/`）→ WebFetch 抓取全文 → 检查原文链接 → 有则优先抓取原文（v3.2.0）\n- **公众号**（`mp.weixin.qq.com`）→ markitdown 转换，反爬时自动 fallback 到移动端 UA\n- **其他网页/本地文件** → markitdown 直接转换\n\n> **v3.4.0 X 链接转录流程修正**：\n> - 飞书 wiki 中发现 X 原文链接时，用 **x-tweet-fetcher**（`web_to_md.py`）抓取完整长文（10K-15K 字符）\n> - **不用 WebFetch**（对 X 链接超时失败率高）\n> - x-tweet-fetcher 失败时降级到飞书 wiki 内容（降级机制）\n> - 全文完整性验证：转录后检查内容长度，<500 字符时警告可能不完整\n\n> **v3.3.0 飞书 wiki 原文链接优先转录**：\n> - 抓取飞书 wiki 后，检查文章头部是否有\"原文链接\"（如 `🔗 原文链接：[url]`）\n> - 有原文链接 → 优先抓取原文链接内容（公众号/X 等），获得更完整的正文和图片\n> - 无原文链接 → 用飞书 wiki 内容\n> - IMA 存放：有公众号原文链接 → import_urls（保留图片）；无 → 纯文本笔记\n\n> **v3.0 新增信源支持**：\n> - 飞书 wiki 文档：通过 WebFetch 转录飞书知识库文章全文\n> - 公众号反爬 fallback：markitdown 返回验证页时自动切换移动端 UA 重试\n\n> **v3.2.0 新增**：\n> - Obsidian 文件命名规范化：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n> - 来源自动提取：从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n> - 飞书 wiki 原文链接优先转录：抓取飞书 wiki 后检查原文链接，有则优先抓取原文内容（更完整）\n> - Windows 文件名安全：禁止字符替换为下划线，中文标点（含：）保留\n\n> **v3.1 新增**：\n> - 批量模式断点恢复：崩溃后重跑自动跳过已完成 URL（`.progress.json` 进度文件）\n> - Obsidian frontmatter 自动 tags：根据 URL 来源分类标签\n> - 推文结构化转换通用化：去硬编码，基于启发式规则识别段落标题\n> - subprocess 加 120 秒 timeout：防止网络异常永久挂起\n> - 公众号正文提取改进：保留图片、段落结构、引用块\n\n### 步骤 2：存入目的地\n\n#### Obsidian Vault\n\n文件名规则：`YYYYMMDD-标题-来源.md`（v3.2.0）\n- 来源从 URL 自动提取（waytoagi/feishu/x/wechat 等）\n- 示例：`20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`\n\n```python\nfrom scripts.web_to_all import save_to_obsidian\nfilepath = save_to_obsidian(markdown_content, title, url)\n```\n\n#### 飞书云文档\n\n```python\nfrom scripts.feishu_client import FeishuClient\n\nclient = FeishuClient()\nresult = client.create_document(title=\"文档标题\", content_md=markdown_content)\nprint(f\"文档 URL: {result['url']}\")\n```\n\n#### 腾讯 ima（v3.0 — 知识库两步流程 + 图片保留）\n\nIMA 有**两套独立 API**，不可混用：\n- **Notes API**（`/openapi/note/v1/`）：管笔记、笔记本\n- **Knowledge Base API**（`/openapi/wiki/v1/`）：管知识库、知识条目\n\n「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。必须用两步流程。\n\n> **v3.0 核心功能 — 公众号/网页带图片转录**：\n> - 公众号和普通网页 URL 通过 `import_urls` 让 IMA 服务端抓取，**保留原文图片和排版**\n> - X/Twitter 和飞书 wiki 走纯文本笔记（逐字转录），因为 X 要求逐字转录、飞书需登录认证\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 方式1：直接用 save_to_ima（推荐，自动路由）\n# - 公众号/普通网页 URL → import_urls（服务端抓取，保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n\n# 方式2：手动两步流程\nfrom scripts.ima_client import IMAClient\nclient = IMAClient()\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\n# Step 2: 添加到知识库（Wiki API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(note_id=note[\"note_id\"], title=\"标题\", knowledge_base_id=kb_id)\n```\n\n**IMA 存放路由规则（v3.0）**：\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n### 验证连接\n\n```bash\n# 验证飞书\npython scripts/feishu_client.py --action test\n\n# 验证 ima\npython scripts/ima_client.py --action test\n```\n\n## 故障处理\n\n| 问题 | 解决方案 |\n|------|---------|\n| x.com SSL 超时 | x-tweet-fetcher 使用 FxTwitter API 中转 |\n| markitdown 模块丢失 | `pip install markitdown` |\n| 微信反爬拦截 | markitdown 返回72字符验证页，需 fallback 到 WebFetch 或移动端 UA |\n| 飞书凭证无效 | 检查 `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` |\n| 飞书 blocks 400 错误 | 单次最多 50 个 blocks，长文章需分批插入（见 `references/feishu-blocks.md`） |\n| 飞书 block_type 错误 | Code=14、Quote=15、Text=2、Heading1-3=3-5、Bullet=12（见 `references/feishu-blocks.md`） |\n| ima 凭证无效 | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY`（v3.0） |\n| IMA 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| IMA import_urls 文件夹不存在 | folder_id 不等于 knowledge_base_id，需用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n\n## 依赖与安装\n\n### 完整依赖列表\n\n| 依赖 | 安装命令 | 说明 |\n|------|---------|------|\n| markitdown | `pip install markitdown` | 网页转 Markdown 核心库 |\n| requests | `pip install requests` | HTTP 请求 |\n| python-dotenv | `pip install python-dotenv` | 环境变量管理 |\n| x-tweet-fetcher | 克隆到 `~/.aily/workspace/skills/x-tweet-fetcher` | X/Twitter 专用抓取（可选） |\n\n### 一键安装所有依赖\n\n```bash\n# 安装 Python 依赖\npip install markitdown requests python-dotenv\n```\n\n### x-tweet-fetcher（可选，仅用于 X/Twitter）\n```bash\n# 克隆到技能目录\ncd ~/.aily/workspace/skills\ngit clone https://github.com/EdwardWason/x-tweet-fetcher.git\n```\n\n如果不安装 x-tweet-fetcher，X/Twitter 链接将使用 markitdown 直接处理。\n\n---\n\n## 安全声明\n\n### 🔒 权限声明（MCP Least Privilege）\n\n本技能运行时需要以下权限：\n\n| 权限类型 | 具体内容 | 用途 |\n|---------|---------|------|\n| **文件读取** | 用户指定的 URL、本地输入文件 | 转换源内容 |\n| **文件写入** | Obsidian Vault 目录（`OBSIDIAN_VAULT_PATH`）、临时 Markdown 文件 | 存储转换结果 |\n| **网络请求** | 用户提供的 URL（网页抓取）、飞书 OpenAPI、腾讯 IMA OpenAPI | 抓取内容和存储到云端 |\n| **环境变量** | `FEISHU_APP_ID`、`FEISHU_APP_SECRET`、`IMA_OPENAPI_CLIENTID`、`IMA_OPENAPI_APIKEY`、`OBSIDIAN_VAULT_PATH` | 凭证和路径配置 |\n| **subprocess** | x-tweet-fetcher（可选，仅 X/Twitter 链接） | X 平台内容抓取 |\n\n> ⚠️ 本技能**不读取** Windows registry、不读取 GitHub token、不调用 GitHub API、不执行 git 操作。仅做文档转换和三处存放。\n\n### ⚠️ 用户警告（运行前必读）\n\n1. **数据外传**：运行本技能会将您提供的 URL 或本地文件内容上传到以下第三方云端服务：\n   - **飞书云文档**（需 `FEISHU_APP_ID` + `FEISHU_APP_SECRET`）\n   - **腾讯 IMA 知识库**（需 `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY`）\n   - 如果内容包含敏感、机密或受监管数据，请先确认是否允许上传到这些服务\n\n2. **本地写入**：默认会向 Obsidian Vault 目录写入 Markdown 文件。可通过 `--no-obsidian` 禁用本地写入\n\n3. **选择性禁用**：支持通过参数禁用特定存储目的地：\n   - `--no-feishu`：跳过飞书云文档\n   - `--no-ima`：跳过腾讯 IMA\n   - `--no-obsidian`：跳过本地 Obsidian\n\n4. **IMA URL 导入**：公众号/普通网页 URL 会通过 IMA `import_urls` 让 IMA 服务端抓取，URL 会被发送给腾讯服务器\n\n### 🔒 安全设计原则\n\n1. **凭证安全**\n   - 所有 API 凭证通过环境变量配置，**无硬编码**\n   - 支持 `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `IMA_OPENAPI_CLIENTID`, `IMA_OPENAPI_APIKEY`（v3.0）\n   - 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退\n\n2. **文件操作**\n   - 默认写入 Obsidian Vault 目录（可通过 `OBSIDIAN_VAULT_PATH` 配置）\n   - 支持通过 `--no-feishu` / `--no-ima` / `--no-obsidian` 选择性禁用功能\n   - 不扫描、不读取用户目录下的其他文件\n\n3. **隐私保护**\n   - 不读取任何未经授权的用户配置文件\n   - 所有网络请求仅针对用户提供的 URL\n   - 本地文件仅用于转换，不主动扫描\n\n4. **权限透明**\n   - 文件写入范围：Obsidian Vault 目录、临时 Markdown 文件\n   - 文件读取范围：用户指定的 URL、本地输入文件\n\nFile v3.4.0:README.md\n\n[English](./README.en.md) | 中文\n\n# web-to-FIM\n\n> 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 核心功能\n\n### 支持的信源（7 类 URL + 本地文件）\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n本地文件支持：PDF、Word、PPT、Excel、图片、音频、CSV/JSON/XML 等。\n\n### 三处存放\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地 Markdown + frontmatter + tags |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端团队协作 |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI 原生知识库（FIM知识库） |\n\n## 快速开始\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## 环境变量配置\n\n```bash\n# Obsidian Vault path (optional, has default)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Feishu credentials\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> 凭证必须通过环境变量配置，禁止硬编码。旧变量名 `IMA_CLIENT_ID` / `IMA_API_KEY` 仍兼容回退。\n\n## 使用示例\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## 触发词\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\n当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n\n## 验证连接\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA 智能路由（v3.0）\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号 / 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| X/Twitter | 纯文本笔记（逐字转录） | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n\n## 版本历史\n\n- **v3.1.0**：批量模式断点恢复；Obsidian frontmatter 自动 tags；推文结构化转换通用化；subprocess 120 秒 timeout；公众号正文提取改进\n- **v3.0.0**：IMA 改用知识库两步流程；公众号/网页带图片转录（import_urls）；新增飞书 wiki 信源；公众号反爬 fallback\n- **v2.x**：基础三处存放功能；X/Twitter 逐字转录；飞书云文档集成\n\n详见 [CHANGELOG.md](./CHANGELOG.md)。\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.4.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"web-to-fim\",\n  \"version\": \"3.4.0\",\n  \"publishedAt\": 1783842284888\n}\n\nFile v3.4.0:references/feishu-blocks.md\n\n# 飞书云文档 Block 类型映射表\n\n> 飞书 Docx API 的 block_type 枚举值。创建文档 blocks 时必须使用正确的 block_type，否则返回 400 Bad Request。\n\n## block_type 完整映射\n\n| block_type | 名称 | Markdown 对应 | block 字段名 |\n|-----------|------|-------------|------------|\n| 1 | Page（页面根块） | — | `page` |\n| 2 | Text（文本） | 普通段落 | `text` |\n| 3 | Heading1（一级标题） | `# ` | `heading1` |\n| 4 | Heading2（二级标题） | `## ` | `heading2` |\n| 5 | Heading3（三级标题） | `### ` | `heading3` |\n| 6 | Heading4（四级标题） | `#### ` | `heading4` |\n| 7 | Heading5（五级标题） | `##### ` | `heading5` |\n| 8 | Heading6（六级标题） | `###### ` | `heading6` |\n| 9 | Heading7（七级标题） | — | `heading7` |\n| 10 | Heading8（八级标题） | — | `heading8` |\n| 11 | Heading9（九级标题） | — | `heading9` |\n| 12 | Bullet（无序列表） | `- ` 或 `* ` | `bullet` |\n| 13 | Ordered（有序列表） | `1. ` | `ordered` |\n| 14 | Code（代码块） | ` ``` ` | `code` |\n| 15 | Quote（引用） | `> ` | `quote` |\n\n## 常见错误\n\n| 错误 | 正确值 | 说明 |\n|------|-------|------|\n| Code 用 block_type=2 | **block_type=14** | 2 是 Text，不是 Code |\n| Quote 用 block_type=11 | **block_type=15** | 11 是 Heading9，不是 Quote |\n\n## Block 结构示例\n\n### Text（block_type=2）\n\n```json\n{\n    \"block_type\": 2,\n    \"text\": {\n        \"elements\": [{\"text_run\": {\"content\": \"文本内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Heading1（block_type=3）\n\n```json\n{\n    \"block_type\": 3,\n    \"heading1\": {\n        \"elements\": [{\"text_run\": {\"content\": \"标题内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Bullet（block_type=12）\n\n```json\n{\n    \"block_type\": 12,\n    \"bullet\": {\n        \"elements\": [{\"text_run\": {\"content\": \"列表项\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Code（block_type=14）\n\n```json\n{\n    \"block_type\": 14,\n    \"code\": {\n        \"elements\": [{\"text_run\": {\"content\": \"code content\"}}],\n        \"style\": {\"language\": 1}\n    }\n}\n```\n\n### Quote（block_type=15）\n\n```json\n{\n    \"block_type\": 15,\n    \"quote\": {\n        \"elements\": [{\"text_run\": {\"content\": \"引用内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n## 关键约束\n\n### 1. elements 中不要加多余字段\n\n```json\n// ❌ 错误 — 多了 \"type\" 字段\n{\"text_run\": {\"type\": \"text_run\", \"content\": \"文本\"}}\n\n// ✅ 正确\n{\"text_run\": {\"content\": \"文本\"}}\n```\n\n### 2. 空行不要创建空文本块\n\n```python\n# ❌ 错误 — 空行创建空块会导致 400\nif not stripped:\n    blocks.append({\"block_type\": 2, \"text\": {\"elements\": [{\"text_run\": {\"content\": \"\"}}]}})\n\n# ✅ 正确 — 空行直接跳过\nif not stripped:\n    continue\n```\n\n### 3. 图片块需要预上传 token\n\n图片不能直接用 URL，必须先通过飞书上传 API 获取 `file_token`，再创建图片块。当前实现暂时跳过图片。\n\n### 4. 单次请求最多 50 个 blocks\n\n```\nPOST /docx/v1/documents/{document_id}/blocks/{document_id}/children\n```\n\n**payload 中 `children` 数组最多 50 个 block**。长文章必须分批插入：\n\n```python\nfor i in range(0, len(blocks), 50):\n    batch = blocks[i:i+50]\n    requests.post(url, headers=headers, json={\"children\": batch})\n```\n\n### 5. payload 中不要传 index\n\n```json\n// ❌ 错误 — index=-1 可能导致问题\n{\"children\": blocks, \"index\": -1}\n\n// ✅ 正确 — 不传 index，默认追加到末尾\n{\"children\": blocks}\n```\n\n## API 端点\n\n| 操作 | 方法 | URL |\n|------|------|-----|\n| 创建文档 | POST | `/docx/v1/documents` |\n| 插入 blocks | POST | `/docx/v1/documents/{document_id}/blocks/{document_id}/children` |\n| 获取文档信息 | GET | `/docx/v1/documents/{document_id}` |\n\n## 认证\n\n```\nAuthorization: Bearer {tenant_access_token}\nContent-Type: application/json\n```\n\n获取 token：`POST /auth/v3/tenant_access_token/internal`，payload 为 `{\"app_id\": \"...\", \"app_secret\": \"...\"}`。\n\nFile v3.4.0:references/feishu-setup.md\n\n# 飞书云文档 API 配置指南\n\n## 获取凭证\n\n### 步骤 1: 创建飞书应用\n\n1. 访问 [飞书开放平台](https://open.feishu.cn/)\n2. 登录后进入「开发者后台」\n3. 点击「创建应用」，填写应用名称和描述\n4. 获取 **App ID** 和 **App Secret**\n\n### 步骤 2: 配置权限\n\n在应用后台开启以下权限：\n\n| 权限名称 | 权限说明 | 必要性 |\n|---------|---------|--------|\n| `docx.document:readonly` | 读取云文档 | 可选 |\n| `docx.document:write` | 创建/编辑云文档 | 必须 |\n| `drive:drive:folder` | 云文档文件夹操作 | 必须 |\n| `sheets:Spreadsheet:readonly` | 读取表格 | 可选 |\n\n### 步骤 3: 发布应用\n\n1. 在「版本管理与发布」中创建版本\n2. 选择「发布」并等待审核（或自建企业直接通过）\n\n## 本地配置\n\n### 设置环境变量\n\n```bash\n# Windows PowerShell\n$env:FEISHU_APP_ID=\"your_app_id\"\n$env:FEISHU_APP_SECRET=\"your_app_secret\"\n\n# Linux/macOS\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n```\n\n### 验证配置\n\n```python\nfrom feishu_client import FeishuClient\n\nclient = FeishuClient()\nif client.test_connection():\n    print(\"✅ 飞书连接成功\")\nelse:\n    print(\"❌ 飞书连接失败，请检查凭证\")\n```\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **永远不要**将 `.env` 文件或包含真实凭证的文件提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 生产环境建议使用密钥管理服务（如 AWS Secrets Manager）\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `invalid_app_id` | 检查 App ID 是否正确 |\n| `app_secret` 错误 | 在飞书开放平台重置 App Secret |\n| 权限不足 | 在应用后台添加所需权限并重新发布 |\n| 签名校验失败 | 确保使用 HTTPS，检查时间戳是否正确 |\n\nFile v3.4.0:references/ima-setup.md\n\n# 腾讯 IMA 知识库 API 配置指南（v3.0 — IMA OpenAPI v1.1.7）\n\n> ⚠️ **v3.0 重大变更**：\n> - API 端点从 `/v1/note/create` 迁移到 `/openapi/note/v1/import_doc`\n> - Base URL 从 `https://ima.im.qq.com/openapi` 改为 `https://ima.qq.com`\n> - 环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`\n> - 存储模式从\"笔记本\"改为\"知识库\"两步流程\n\n## 两套 API 系统（不可混用）\n\nIMA 有两套完全独立的 API，对应 UI 中两个不同的标签页：\n\n| API 系统 | 路径前缀 | 管理对象 | UI 对应 |\n|---------|---------|---------|---------|\n| **Notes API** | `/openapi/note/v1/` | 笔记、笔记本 | IMA「笔记本」标签页 |\n| **Knowledge Base API** | `/openapi/wiki/v1/` | 知识库、知识条目 | IMA「知识库」标签页 |\n\n**关键区别**：「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。\n\n## 获取凭证\n\n### 步骤 1: 访问 IMA 开放平台\n\n打开 [ima.qq.com/agent-interface](https://ima.qq.com/agent-interface)\n\n### 步骤 2: 登录并获取凭证\n\n1. 使用 QQ 或微信扫码登录\n2. 在「Agent 接口」页面获取凭证：\n   - **Client ID**: 应用标识\n   - **Api Key**: API 密钥\n\n### 步骤 3: 复制凭证\n\n```text\nClient ID: your_client_id_here\nApi Key: your_api_key_here\n```\n\n## 本地配置\n\n### 设置环境变量（v3.0）\n\n```bash\n# Windows PowerShell — 持久化设置\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_CLIENTID\", \"your_client_id\", \"User\")\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_APIKEY\", \"your_api_key\", \"User\")\n\n# Windows PowerShell — 临时设置（当前会话）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Linux/macOS\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n```\n\n> 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退，但建议迁移到新名。\n\n### 可选：指定知识库\n\n```bash\n$env:IMA_KB_NAME = \"FIM知识库\"  # 默认值\n```\n\n### 验证配置\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nif client.test_connection():\n    print(\"✅ IMA 连接成功\")\nelse:\n    print(\"❌ IMA 连接失败，请检查凭证\")\n```\n\n## API 基础信息（v1.1.7）\n\n- **Base URL**: `https://ima.qq.com`\n- **认证方式**: Header `ima-openapi-clientid` + `ima-openapi-apikey`\n- **数据格式**: JSON\n- **无需本地客户端**: 所有操作通过云端 API 完成\n\n### Notes API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 创建笔记 | `POST /openapi/note/v1/import_doc` | 从 Markdown 创建笔记 |\n| 追加内容 | `POST /openapi/note/v1/append_doc` | 向现有笔记追加内容 |\n| 获取笔记内容 | `POST /openapi/note/v1/get_doc_content` | 读取笔记纯文本/JSON |\n| 列出笔记 | `POST /openapi/note/v1/list_note` | 列出笔记本中的笔记 |\n| 搜索笔记 | `POST /openapi/note/v1/search_note` | 按标题/正文搜索 |\n| 列出笔记本 | `POST /openapi/note/v1/list_notebook` | 列出所有笔记本 |\n\n### Knowledge Base API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 搜索知识库 | `POST /openapi/wiki/v1/search_knowledge_base` | 按名称搜索，返回 `kb_id` |\n| 可添加知识库列表 | `POST /openapi/wiki/v1/get_addable_knowledge_base_list` | 列出可添加内容的知识库 |\n| 添加知识 | `POST /openapi/wiki/v1/add_knowledge` | 添加笔记/网页/文件到知识库 |\n| 浏览知识库 | `POST /openapi/wiki/v1/get_knowledge_list` | 浏览知识库内容 |\n| 导入 URL | `POST /openapi/wiki/v1/import_urls` | 服务端抓取 URL（保留图片） |\n\n## 存储流程\n\n### 流程 1：纯文本笔记（X/Twitter/飞书/手动内容）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\n\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\nnote_id = note[\"note_id\"]\n\n# Step 2: 添加到知识库（Knowledge Base API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(\n    note_id=note_id,\n    title=\"标题\",\n    knowledge_base_id=kb_id,  # media_type=11, note_info.content_id=note_id\n)\n```\n\n### 流程 2：URL 导入（公众号/普通网页 — 保留图片）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\n\n# IMA 服务端抓取 URL，保留图片和排版\nresults = client.import_urls(\n    knowledge_base_id=kb_id,\n    urls=[\"https://mp.weixin.qq.com/s/xxxxx\"],\n)\n```\n\n### 智能路由（推荐用 save_to_ima）\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 自动路由：\n# - 公众号/网页 URL → import_urls（保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n```\n\n## add_knowledge 的 media_type 枚举\n\n| media_type | 类型 | note_info/web_info 字段 |\n|-----------|------|------------------------|\n| 2 | 网页 | `web_info.content_id=<url>` |\n| 6 | 公众号文章 | 同上，URL 匹配 `mp.weixin.qq.com/s` |\n| 11 | 笔记 | `note_info.content_id=<note_id>` |\n| 7 | Markdown | 需先 create_media + COS 上传 |\n\n## IMA 存放路由规则\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **Api Key 等同于密码**，不要泄露给他人\n- 永远不要将真实凭证提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 定期轮换 Api Key\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `401 Unauthorized` | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY` 是否正确 |\n| `404 Not Found` | API 端点已变更，确认用 `/openapi/note/v1/import_doc`（非 `/v1/note/create`） |\n| 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| `import_urls` 文件夹不存在 | folder_id 不等于 knowledge_base_id，用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n| `code=210001` 参数错误 | 检查请求体 JSON 格式，`content_format` 必须为 1（MARKDOWN） |\n\nFile v3.4.0:CHANGELOG.md\n\n# Changelog\n\n本文件记录 web-to-fim 技能的版本演进。版本号遵循 [语义化版本](https://semver.org/)。\n\n## [3.4.0] - 2026-07-12\n\n### 安全修复（ClawHub SkillSpector v3.3.0 findings）\n- **删除误上传的临时脚本**：`_gh_push.py` 和 `_gh_release.py`（v3.3.0 发布时误上传，含 GitHub token 读取和 API 调用，被标记为 MCP Tool Poisoning / Context-Inappropriate Capability）\n- **新增权限声明段落**：MCP Least Privilege — 明确声明文件读取/写入/网络请求/环境变量/subprocess 权限\n- **新增用户警告段落**：Missing User Warnings — 明确告知数据外传到飞书/IMA、本地写入、选择性禁用参数\n- **修正安全声明**：Intent-Code Divergence — 移除\"仅在用户明确指定时写入文件\"的错误描述，改为\"默认写入 Obsidian Vault\"\n- **触发词收窄**：Vague Triggers — 移除过于宽泛的\"转文档\"、\"网页转文档\"，改为更明确的\"抓网页存飞书\"、\"web to feishu\"等\n- **Do NOT 范围扩展**：新增\"普通文档格式转换（非三处存放意图）\"\n\n### 功能修复（X 链接转录流程）\n- **X 链接转录流程修正**：飞书 wiki 中发现 X 原文链接时，用 x-tweet-fetcher 抓取完整长文（10K-15K 字符），不用 WebFetch（超时失败率高）\n- **降级机制**：x-tweet-fetcher 失败时降级到飞书 wiki 内容\n- **全文完整性验证**：转录后检查内容长度，<500 字符时警告可能不完整\n- **内容长度对比**：X 原文内容比飞书 wiki 内容长时才替换，否则保留飞书 wiki 内容\n\n## [3.3.0] - 2026-07-12\n\n### 新增\n- **原文链接自动提取**：`extract_original_url()` 函数从 Markdown 前 800 字符自动识别\"原文链接\"/\"转载自\"/\"本文首发\"等关键词\n- **IMA 路由精细化**：GitHub URL 改为纯文本笔记（IMA 抓取 HTML 页面效果差），不再走 import_urls\n- **飞书 wiki 自动路由函数**：`_is_feishu_wiki()` 和 `_fetch_feishu_wiki_via_webfetch()` 新增\n\n### 修复\n- **IMA 路由规则修正**：原文链接为 GitHub 时，原逻辑走 import_urls 导致 IMA 抓取 HTML 页面内容混乱。改为纯文本笔记存转录 MD\n- **路由规则文档化**：IMA 路由规则精细化（公众号/普通网页→import_urls；X/Twitter/飞书/GitHub→纯文本笔记）\n\n## [3.2.0] - 2026-07-12\n\n### 新增\n- **Obsidian 文件命名规范化**：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n- **来源自动提取**：`_extract_source_name()` 函数从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n- **飞书 wiki 原文链接优先转录**：抓取飞书 wiki 后检查文章头部\"原文链接\"，有则优先抓取原文内容（公众号/X 等），获得更完整的正文和图片\n- **IMA 智能路由优化**：飞书 wiki 有公众号原文链接 → import_urls（保留图片）；无原文链接 → 纯文本笔记\n\n### 修复\n- Windows 文件名安全：禁止字符（`\\ / : * ? \" < > |`）替换为下划线，中文标点（含 `：`）保留\n- 文件名长度限制：标题超过 60 字符自动截断，避免文件名过长\n\n## [3.1.0] - 2026-07-11\n\n### 新增\n- 批量模式断点恢复：自动生成 `.progress.json` 进度文件，崩溃后重跑自动跳过已完成 URL，全部成功后自动清理\n- Obsidian frontmatter 增加 `tags` 字段：根据 URL 来源自动分类标签（x-twitter/wechat/weibo/xiaohongshu/github/youtube/webpage/local-file）\n- `save_to_obsidian` 三级 fallback 机制：重试 3 次 → ASCII 文件名 → 脚本目录 `saved/`\n- `_process_single` 每个存储操作独立 try/except：一处失败不阻断其他存储\n\n### 修复\n- **Critical**: `tweet_to_md.py` 去掉硬编码的段落标题列表，改为通用启发式规则（Emoji 模式匹配 + 数字编号 + 短行特征 + 技术名词后缀）\n- **Critical**: `web_to_md.py` `_run()` 函数加 120 秒 timeout，防止 x-tweet-fetcher 网络异常时永久挂起\n- **Important**: `_fetch_wechat_mobile()` 改进正文提取：保留图片（data-src）、段落结构（`<p>`/`<section>`）、引用块（blockquote），不再丢失内容\n- **Minor**: 标题提取改进：支持从 frontmatter `title:` 提取，fallback 到 URL 域名生成标题，不再出现 `Untitled`\n- **Minor**: `import time` / `import json` 移到文件顶部\n- **Minor**: `.gitignore` 补充 `saved/`、`batch_urls.txt`、`*.progress.json`、`batch_run.log` 等临时文件\n\n## [3.0.2] - 2026-07-11\n\n### 修复\n- 同步本地版本号与 ClawHub 线上版本（本地从 3.0.1 对齐到 3.0.2）\n- 修复 SKILL.md 安全声明章节的 Markdown 语法瑕疵：\n  - 第 261 行 `--no-ima` 反引号缺失\n  - 第 258 / 263 / 268 行 `**文件操作` / `**隐私保护` / `**权限透明` 加粗未闭合\n\n### 文档\n- 新增 CHANGELOG.md，补齐版本演进记录\n\n## [3.0.1] - 2026-07-11\n\n### 修复\n- 更新 ClawHub 页面 Short summary，反映 v3.0 的信源与存储能力\n  - frontmatter description 增加公众号/网页图片保留、飞书 wiki 转录说明\n  - 信源表标注 IMA 存储路由（IMA 笔记 → IMA 知识库）\n\n## [3.0.0] - 2026-07-10\n\n### 新增\n- **IMA 智能路由**：公众号/普通网页 → `import_urls` 服务端抓取，保留原文图片和排版\n- **飞书 wiki 信源**：通过 WebFetch 转录飞书知识库文章全文\n- **公众号反爬 fallback**：markitdown 返回验证页时自动切换移动端 UA 重试\n- **批量模式**：`--urls-file` 参数支持从文件逐行读取 URL 批量处理\n- **试运行模式**：`--dry-run` 参数仅转 Markdown 不入库\n\n### 变更\n- **IMA API 迁移到 v1.1.7**：创建笔记改用 `/openapi/note/v1/import_doc`\n- **IMA 存储从\"笔记本\"改为\"知识库\"两步流程**：\n  1. `create_note` 创建笔记（Notes API）\n  2. `add_note_to_knowledge_base` 添加到知识库（Wiki API）\n- **环境变量更名**：`IMA_CLIENT_ID` / `IMA_API_KEY` → `IMA_OPENAPI_CLIENTID` / `IMA_OPENAPI_APIKEY`（旧名仍兼容回退）\n- X/Twitter 链接强制走纯文本笔记逐字转录，不使用 `import_urls`\n\n### 安全\n- 凭证全部通过环境变量配置，无硬编码\n- 清理临时脚本中的真实 IMA 凭证\n- 完善 .gitignore 排除规则\n\nFile v3.4.0:README.en.md\n\nEnglish | [中文](./README.md)\n\n# web-to-FIM\n\n> Convert any web link or local file into structured Markdown, and store it in three destinations: Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base.\n\n## Core Features\n\n### Supported Sources (7 URL Types + Local Files)\n\n| Source | URL Pattern | Fetch Method |\n|--------|------------|-------------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher (verbatim transcript) |\n| WeChat Article | `mp.weixin.qq.com` | markitdown + mobile UA fallback |\n| Feishu Wiki | `*.feishu.cn/wiki/` | WebFetch full transcript |\n| Xiaohongshu | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| Weibo | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| Any Webpage | other `http(s)://` URLs | markitdown |\n\nLocal file support: PDF, Word, PPT, Excel, images, audio, CSV/JSON/XML, etc.\n\n### Three Destinations\n\n| Destination | Environment Variable | Description |\n|-------------|---------------------|-------------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | Local Markdown + frontmatter + tags |\n| Feishu Cloud Docs | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | Cloud team collaboration |\n| Tencent IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI-native knowledge base (FIM) |\n\n## Quick Start\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"Custom Title\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## Environment Variables\n\n```bash\n# Obsidian Vault path (optional, has default)\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n\n# Feishu credentials\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\nexport IMA_KB_NAME=\"FIM知识库\"\n```\n\n> Credentials must be configured via environment variables, never hardcoded. Legacy variable names `IMA_CLIENT_ID` / `IMA_API_KEY` are still supported as fallback.\n\n## Usage Examples\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## Trigger Words\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\nTriggered when the user provides any URL or local file and requests conversion to a document.\n\n## Verify Connections\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA Smart Routing (v3.0)\n\n| source_url Type | IMA Storage Method | Reason |\n|----------------|-------------------|--------|\n| WeChat / General webpage | `import_urls` (server-side fetch) | Preserve images and layout |\n| X/Twitter | Plain text note (verbatim transcript) | Skill rule requires verbatim |\n| Feishu wiki | Plain text note (verbatim transcript) | Requires login, IMA cannot fetch |\n\n## Version History\n\n- **v3.1.0**: Batch mode checkpoint recovery; Obsidian frontmatter auto tags; generalized tweet structured conversion; subprocess 120s timeout; improved WeChat content extraction\n- **v3.0.0**: IMA switched to knowledge base two-step flow; WeChat/webpage with images (import_urls); added Feishu wiki source; WeChat anti-scraping fallback\n- **v2.x**: Basic three-destination storage; X/Twitter verbatim transcript; Feishu Cloud Docs integration\n\nSee [CHANGELOG.md](./CHANGELOG.md) for details.\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.4.0:skill-card.md\n\n## Description: <br>\nConverts web links or local files into structured Markdown and saves the result to Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[edwardwason](https://clawhub.ai/user/edwardwason) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to capture chosen URLs or local files as Markdown knowledge artifacts and store them locally or in approved Feishu and Tencent IMA destinations. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Selected URLs or local file contents may be uploaded to Feishu Cloud Docs or Tencent IMA. <br>\nMitigation: Use the skill only with content approved for those services, and disable cloud destinations with --no-feishu or --no-ima when cloud upload is not approved. <br>\nRisk: The skill writes Markdown output to the configured Obsidian Vault by default. <br>\nMitigation: Set OBSIDIAN_VAULT_PATH intentionally, use --no-obsidian to skip local vault writes, or use --dry-run for conversion-only checks. <br>\nRisk: Credentials for Feishu and IMA are required for cloud storage. <br>\nMitigation: Provide credentials only through environment variables and rotate or remove them if they may have been exposed. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/edwardwason/skills/web-to-fim) <br>\n- [Feishu setup guide](references/feishu-setup.md) <br>\n- [Feishu block type mapping](references/feishu-blocks.md) <br>\n- [Tencent IMA setup guide](references/ima-setup.md) <br>\n- [Feishu Open Platform](https://open.feishu.cn/) <br>\n- [Tencent IMA OpenAPI](https://ima.qq.com/agent-interface) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [markdown, files, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown files with frontmatter, cloud document records, API-created knowledge base entries, and command-line status output.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Supports destination-limiting flags for Obsidian, Feishu, and IMA, plus dry-run conversion without storage.] <br>\n\n## Skill Version(s): <br>\n3.4.0 (source: frontmatter, CHANGELOG, server release evidence) <br>\n\n## Ethical Considerations: <br>\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. <br>\n\nFile v3.4.0:requirements.txt\n\nrequests\npython-dotenv\n\nArchive v3.3.0: 18 files, 44504 bytes\n\nFiles: _meta.json (129b), CHANGELOG.md (4852b), README.en.md (4142b), README.md (3967b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/_gh_push.py (3463b), scripts/_gh_release.py (1580b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/save_fetched.py (3424b), scripts/tweet_to_md.py (7319b), scripts/web_to_all.py (16494b), scripts/web_to_md.py (9308b), skill-card.md (3237b), SKILL.md (13097b)\n\nFile v3.3.0:SKILL.md\n\n---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.3.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云文档、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（WebFetch 全文转录 + 原文链接优先转录）；(4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云文档（团队协作）+ IMA 知识库（FIM知识库，AI 原生）。\n  IMA 智能路由：公众号/普通网页 → import_urls 保留图片；X/Twitter/飞书/GitHub → 纯文本笔记逐字转录。\n  飞书 wiki 原文链接优先转录：检查文章头部\"原文链接\"，有则优先抓取原文内容作为最终产物存三处，IMA 只存原文链接地址自动识别。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n  Do NOT use for 创建文档内容、编辑飞书文档正文、代码开发、非文档转存任务。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📚 **飞书云文档** - 云端团队协作\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地保存到指定目录，带 frontmatter（默认：`E:\\Obsidian\\md\\inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端服务，参考 `references/feishu-setup.md` |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | **云端 API v1.1.7**，两步流程存入知识库，参考 `references/ima-setup.md` |\n\n### Obsidian Vault 路径配置\n跨平台支持，通过环境变量 `OBSIDIAN_VAULT_PATH` 配置：\n\n```bash\n# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian\\Vault\\inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n```\n\n如果未设置，默认使用：\n- Windows: `E:\\Obsidian\\md\\inbox`\n- macOS/Linux: `~/Obsidian/inbox`\n\n## 一键保存到所有目的地\n\n使用 `web_to_all.py` 一键转换并保存到 Obsidian/飞书/IMA：\n\n```bash\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian\n```\n\n## 安全配置\n\n⚠️ **凭证必须通过环境变量配置**，禁止硬编码：\n\n### 飞书配置\n\n```bash\n# 设置环境变量\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n```\n\n参考 [references/feishu-setup.md](references/feishu-setup.md) 获取凭证。\n\n### ima 配置\n\n```bash\n# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> ⚠️ **v3.0 变更**：环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`（旧名仍兼容回退）。IMA 存储从\"笔记本\"改为\"知识库\"两步流程。\n\n参考 [references/ima-setup.md](references/ima-setup.md) 获取凭证。\n\n## 工作流\n\n### 步骤 1：转换为 Markdown\n\n```bash\npython3 scripts/web_to_md.py --url \"<url_or_path>\" --output <output.md>\n```\n\n路由逻辑：\n- **X/Twitter** → x-tweet-fetcher 抓取 JSON → tweet_to_md.py 结构化转换（逐字转录）\n- **飞书 wiki**（`*.feishu.cn/wiki/`）→ WebFetch 抓取全文 → 检查原文链接 → 有则优先抓取原文（v3.2.0）\n- **公众号**（`mp.weixin.qq.com`）→ markitdown 转换，反爬时自动 fallback 到移动端 UA\n- **其他网页/本地文件** → markitdown 直接转换\n\n> **v3.2.0 飞书 wiki 原文链接优先转录**：\n> - 抓取飞书 wiki 后，检查文章头部是否有\"原文链接\"（如 `🔗 原文链接：[url]`）\n> - 有原文链接 → 优先抓取原文链接内容（公众号/X 等），获得更完整的正文和图片\n> - 无原文链接 → 用飞书 wiki 内容\n> - IMA 存放：有公众号原文链接 → import_urls（保留图片）；无 → 纯文本笔记\n\n> **v3.0 新增信源支持**：\n> - 飞书 wiki 文档：通过 WebFetch 转录飞书知识库文章全文\n> - 公众号反爬 fallback：markitdown 返回验证页时自动切换移动端 UA 重试\n\n> **v3.2.0 新增**：\n> - Obsidian 文件命名规范化：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n> - 来源自动提取：从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n> - 飞书 wiki 原文链接优先转录：抓取飞书 wiki 后检查原文链接，有则优先抓取原文内容（更完整）\n> - Windows 文件名安全：禁止字符替换为下划线，中文标点（含：）保留\n\n> **v3.1 新增**：\n> - 批量模式断点恢复：崩溃后重跑自动跳过已完成 URL（`.progress.json` 进度文件）\n> - Obsidian frontmatter 自动 tags：根据 URL 来源分类标签\n> - 推文结构化转换通用化：去硬编码，基于启发式规则识别段落标题\n> - subprocess 加 120 秒 timeout：防止网络异常永久挂起\n> - 公众号正文提取改进：保留图片、段落结构、引用块\n\n### 步骤 2：存入目的地\n\n#### Obsidian Vault\n\n文件名规则：`YYYYMMDD-标题-来源.md`（v3.2.0）\n- 来源从 URL 自动提取（waytoagi/feishu/x/wechat 等）\n- 示例：`20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`\n\n```python\nfrom scripts.web_to_all import save_to_obsidian\nfilepath = save_to_obsidian(markdown_content, title, url)\n```\n\n#### 飞书云文档\n\n```python\nfrom scripts.feishu_client import FeishuClient\n\nclient = FeishuClient()\nresult = client.create_document(title=\"文档标题\", content_md=markdown_content)\nprint(f\"文档 URL: {result['url']}\")\n```\n\n#### 腾讯 ima（v3.0 — 知识库两步流程 + 图片保留）\n\nIMA 有**两套独立 API**，不可混用：\n- **Notes API**（`/openapi/note/v1/`）：管笔记、笔记本\n- **Knowledge Base API**（`/openapi/wiki/v1/`）：管知识库、知识条目\n\n「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。必须用两步流程。\n\n> **v3.0 核心功能 — 公众号/网页带图片转录**：\n> - 公众号和普通网页 URL 通过 `import_urls` 让 IMA 服务端抓取，**保留原文图片和排版**\n> - X/Twitter 和飞书 wiki 走纯文本笔记（逐字转录），因为 X 要求逐字转录、飞书需登录认证\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 方式1：直接用 save_to_ima（推荐，自动路由）\n# - 公众号/普通网页 URL → import_urls（服务端抓取，保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n\n# 方式2：手动两步流程\nfrom scripts.ima_client import IMAClient\nclient = IMAClient()\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\n# Step 2: 添加到知识库（Wiki API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(note_id=note[\"note_id\"], title=\"标题\", knowledge_base_id=kb_id)\n```\n\n**IMA 存放路由规则（v3.0）**：\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n### 验证连接\n\n```bash\n# 验证飞书\npython scripts/feishu_client.py --action test\n\n# 验证 ima\npython scripts/ima_client.py --action test\n```\n\n## 故障处理\n\n| 问题 | 解决方案 |\n|------|---------|\n| x.com SSL 超时 | x-tweet-fetcher 使用 FxTwitter API 中转 |\n| markitdown 模块丢失 | `pip install markitdown` |\n| 微信反爬拦截 | markitdown 返回72字符验证页，需 fallback 到 WebFetch 或移动端 UA |\n| 飞书凭证无效 | 检查 `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` |\n| 飞书 blocks 400 错误 | 单次最多 50 个 blocks，长文章需分批插入（见 `references/feishu-blocks.md`） |\n| 飞书 block_type 错误 | Code=14、Quote=15、Text=2、Heading1-3=3-5、Bullet=12（见 `references/feishu-blocks.md`） |\n| ima 凭证无效 | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY`（v3.0） |\n| IMA 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| IMA import_urls 文件夹不存在 | folder_id 不等于 knowledge_base_id，需用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n\n## 依赖与安装\n\n### 完整依赖列表\n\n| 依赖 | 安装命令 | 说明 |\n|------|---------|------|\n| markitdown | `pip install markitdown` | 网页转 Markdown 核心库 |\n| requests | `pip install requests` | HTTP 请求 |\n| python-dotenv | `pip install python-dotenv` | 环境变量管理 |\n| x-tweet-fetcher | 克隆到 `~/.aily/workspace/skills/x-tweet-fetcher` | X/Twitter 专用抓取（可选） |\n\n### 一键安装所有依赖\n\n```bash\n# 安装 Python 依赖\npip install markitdown requests python-dotenv\n```\n\n### x-tweet-fetcher（可选，仅用于 X/Twitter）\n```bash\n# 克隆到技能目录\ncd ~/.aily/workspace/skills\ngit clone https://github.com/EdwardWason/x-tweet-fetcher.git\n```\n\n如果不安装 x-tweet-fetcher，X/Twitter 链接将使用 markitdown 直接处理。\n\n---\n\n## 安全声明\n\n### 🔒 安全设计原则\n\n1. **凭证安全**\n   - 所有 API 凭证通过环境变量配置，**无硬编码**\n   - 支持 `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `IMA_OPENAPI_CLIENTID`, `IMA_OPENAPI_APIKEY`（v3.0）\n   - 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退\n\n2. **文件操作**\n   - 仅在用户明确指定时写入文件\n   - Obsidian Vault 路径完全可控\n   - 支持通过 `--no-feishu` / `--no-ima` 选择性禁用功能\n\n3. **隐私保护**\n   - 不读取任何未经授权的用户配置文件\n   - 所有网络请求仅针对用户提供的 URL\n   - 本地文件仅用于转换，不主动扫描\n\n4. **权限透明**\n   - 文件写入范围：Obsidian Vault 目录、临时 Markdown 文件\n   - 文件读取范围：用户指定的 URL、本地输入文件\n\nFile v3.3.0:README.md\n\n[English](./README.en.md) | 中文\n\n# web-to-FIM\n\n> 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 核心功能\n\n### 支持的信源（7 类 URL + 本地文件）\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n本地文件支持：PDF、Word、PPT、Excel、图片、音频、CSV/JSON/XML 等。\n\n### 三处存放\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地 Markdown + frontmatter + tags |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端团队协作 |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI 原生知识库（FIM知识库） |\n\n## 快速开始\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## 环境变量配置\n\n```bash\n# Obsidian Vault path (optional, has default)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Feishu credentials\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> 凭证必须通过环境变量配置，禁止硬编码。旧变量名 `IMA_CLIENT_ID` / `IMA_API_KEY` 仍兼容回退。\n\n## 使用示例\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## 触发词\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\n当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n\n## 验证连接\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA 智能路由（v3.0）\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号 / 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| X/Twitter | 纯文本笔记（逐字转录） | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n\n## 版本历史\n\n- **v3.1.0**：批量模式断点恢复；Obsidian frontmatter 自动 tags；推文结构化转换通用化；subprocess 120 秒 timeout；公众号正文提取改进\n- **v3.0.0**：IMA 改用知识库两步流程；公众号/网页带图片转录（import_urls）；新增飞书 wiki 信源；公众号反爬 fallback\n- **v2.x**：基础三处存放功能；X/Twitter 逐字转录；飞书云文档集成\n\n详见 [CHANGELOG.md](./CHANGELOG.md)。\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.3.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"web-to-fim\",\n  \"version\": \"3.3.0\",\n  \"publishedAt\": 1783840822436\n}\n\nFile v3.3.0:references/feishu-blocks.md\n\n# 飞书云文档 Block 类型映射表\n\n> 飞书 Docx API 的 block_type 枚举值。创建文档 blocks 时必须使用正确的 block_type，否则返回 400 Bad Request。\n\n## block_type 完整映射\n\n| block_type | 名称 | Markdown 对应 | block 字段名 |\n|-----------|------|-------------|------------|\n| 1 | Page（页面根块） | — | `page` |\n| 2 | Text（文本） | 普通段落 | `text` |\n| 3 | Heading1（一级标题） | `# ` | `heading1` |\n| 4 | Heading2（二级标题） | `## ` | `heading2` |\n| 5 | Heading3（三级标题） | `### ` | `heading3` |\n| 6 | Heading4（四级标题） | `#### ` | `heading4` |\n| 7 | Heading5（五级标题） | `##### ` | `heading5` |\n| 8 | Heading6（六级标题） | `###### ` | `heading6` |\n| 9 | Heading7（七级标题） | — | `heading7` |\n| 10 | Heading8（八级标题） | — | `heading8` |\n| 11 | Heading9（九级标题） | — | `heading9` |\n| 12 | Bullet（无序列表） | `- ` 或 `* ` | `bullet` |\n| 13 | Ordered（有序列表） | `1. ` | `ordered` |\n| 14 | Code（代码块） | ` ``` ` | `code` |\n| 15 | Quote（引用） | `> ` | `quote` |\n\n## 常见错误\n\n| 错误 | 正确值 | 说明 |\n|------|-------|------|\n| Code 用 block_type=2 | **block_type=14** | 2 是 Text，不是 Code |\n| Quote 用 block_type=11 | **block_type=15** | 11 是 Heading9，不是 Quote |\n\n## Block 结构示例\n\n### Text（block_type=2）\n\n```json\n{\n    \"block_type\": 2,\n    \"text\": {\n        \"elements\": [{\"text_run\": {\"content\": \"文本内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Heading1（block_type=3）\n\n```json\n{\n    \"block_type\": 3,\n    \"heading1\": {\n        \"elements\": [{\"text_run\": {\"content\": \"标题内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Bullet（block_type=12）\n\n```json\n{\n    \"block_type\": 12,\n    \"bullet\": {\n        \"elements\": [{\"text_run\": {\"content\": \"列表项\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Code（block_type=14）\n\n```json\n{\n    \"block_type\": 14,\n    \"code\": {\n        \"elements\": [{\"text_run\": {\"content\": \"code content\"}}],\n        \"style\": {\"language\": 1}\n    }\n}\n```\n\n### Quote（block_type=15）\n\n```json\n{\n    \"block_type\": 15,\n    \"quote\": {\n        \"elements\": [{\"text_run\": {\"content\": \"引用内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n## 关键约束\n\n### 1. elements 中不要加多余字段\n\n```json\n// ❌ 错误 — 多了 \"type\" 字段\n{\"text_run\": {\"type\": \"text_run\", \"content\": \"文本\"}}\n\n// ✅ 正确\n{\"text_run\": {\"content\": \"文本\"}}\n```\n\n### 2. 空行不要创建空文本块\n\n```python\n# ❌ 错误 — 空行创建空块会导致 400\nif not stripped:\n    blocks.append({\"block_type\": 2, \"text\": {\"elements\": [{\"text_run\": {\"content\": \"\"}}]}})\n\n# ✅ 正确 — 空行直接跳过\nif not stripped:\n    continue\n```\n\n### 3. 图片块需要预上传 token\n\n图片不能直接用 URL，必须先通过飞书上传 API 获取 `file_token`，再创建图片块。当前实现暂时跳过图片。\n\n### 4. 单次请求最多 50 个 blocks\n\n```\nPOST /docx/v1/documents/{document_id}/blocks/{document_id}/children\n```\n\n**payload 中 `children` 数组最多 50 个 block**。长文章必须分批插入：\n\n```python\nfor i in range(0, len(blocks), 50):\n    batch = blocks[i:i+50]\n    requests.post(url, headers=headers, json={\"children\": batch})\n```\n\n### 5. payload 中不要传 index\n\n```json\n// ❌ 错误 — index=-1 可能导致问题\n{\"children\": blocks, \"index\": -1}\n\n// ✅ 正确 — 不传 index，默认追加到末尾\n{\"children\": blocks}\n```\n\n## API 端点\n\n| 操作 | 方法 | URL |\n|------|------|-----|\n| 创建文档 | POST | `/docx/v1/documents` |\n| 插入 blocks | POST | `/docx/v1/documents/{document_id}/blocks/{document_id}/children` |\n| 获取文档信息 | GET | `/docx/v1/documents/{document_id}` |\n\n## 认证\n\n```\nAuthorization: Bearer {tenant_access_token}\nContent-Type: application/json\n```\n\n获取 token：`POST /auth/v3/tenant_access_token/internal`，payload 为 `{\"app_id\": \"...\", \"app_secret\": \"...\"}`。\n\nFile v3.3.0:references/feishu-setup.md\n\n# 飞书云文档 API 配置指南\n\n## 获取凭证\n\n### 步骤 1: 创建飞书应用\n\n1. 访问 [飞书开放平台](https://open.feishu.cn/)\n2. 登录后进入「开发者后台」\n3. 点击「创建应用」，填写应用名称和描述\n4. 获取 **App ID** 和 **App Secret**\n\n### 步骤 2: 配置权限\n\n在应用后台开启以下权限：\n\n| 权限名称 | 权限说明 | 必要性 |\n|---------|---------|--------|\n| `docx.document:readonly` | 读取云文档 | 可选 |\n| `docx.document:write` | 创建/编辑云文档 | 必须 |\n| `drive:drive:folder` | 云文档文件夹操作 | 必须 |\n| `sheets:Spreadsheet:readonly` | 读取表格 | 可选 |\n\n### 步骤 3: 发布应用\n\n1. 在「版本管理与发布」中创建版本\n2. 选择「发布」并等待审核（或自建企业直接通过）\n\n## 本地配置\n\n### 设置环境变量\n\n```bash\n# Windows PowerShell\n$env:FEISHU_APP_ID=\"your_app_id\"\n$env:FEISHU_APP_SECRET=\"your_app_secret\"\n\n# Linux/macOS\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n```\n\n### 验证配置\n\n```python\nfrom feishu_client import FeishuClient\n\nclient = FeishuClient()\nif client.test_connection():\n    print(\"✅ 飞书连接成功\")\nelse:\n    print(\"❌ 飞书连接失败，请检查凭证\")\n```\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **永远不要**将 `.env` 文件或包含真实凭证的文件提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 生产环境建议使用密钥管理服务（如 AWS Secrets Manager）\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `invalid_app_id` | 检查 App ID 是否正确 |\n| `app_secret` 错误 | 在飞书开放平台重置 App Secret |\n| 权限不足 | 在应用后台添加所需权限并重新发布 |\n| 签名校验失败 | 确保使用 HTTPS，检查时间戳是否正确 |\n\nFile v3.3.0:references/ima-setup.md\n\n# 腾讯 IMA 知识库 API 配置指南（v3.0 — IMA OpenAPI v1.1.7）\n\n> ⚠️ **v3.0 重大变更**：\n> - API 端点从 `/v1/note/create` 迁移到 `/openapi/note/v1/import_doc`\n> - Base URL 从 `https://ima.im.qq.com/openapi` 改为 `https://ima.qq.com`\n> - 环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`\n> - 存储模式从\"笔记本\"改为\"知识库\"两步流程\n\n## 两套 API 系统（不可混用）\n\nIMA 有两套完全独立的 API，对应 UI 中两个不同的标签页：\n\n| API 系统 | 路径前缀 | 管理对象 | UI 对应 |\n|---------|---------|---------|---------|\n| **Notes API** | `/openapi/note/v1/` | 笔记、笔记本 | IMA「笔记本」标签页 |\n| **Knowledge Base API** | `/openapi/wiki/v1/` | 知识库、知识条目 | IMA「知识库」标签页 |\n\n**关键区别**：「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。\n\n## 获取凭证\n\n### 步骤 1: 访问 IMA 开放平台\n\n打开 [ima.qq.com/agent-interface](https://ima.qq.com/agent-interface)\n\n### 步骤 2: 登录并获取凭证\n\n1. 使用 QQ 或微信扫码登录\n2. 在「Agent 接口」页面获取凭证：\n   - **Client ID**: 应用标识\n   - **Api Key**: API 密钥\n\n### 步骤 3: 复制凭证\n\n```text\nClient ID: your_client_id_here\nApi Key: your_api_key_here\n```\n\n## 本地配置\n\n### 设置环境变量（v3.0）\n\n```bash\n# Windows PowerShell — 持久化设置\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_CLIENTID\", \"your_client_id\", \"User\")\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_APIKEY\", \"your_api_key\", \"User\")\n\n# Windows PowerShell — 临时设置（当前会话）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Linux/macOS\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n```\n\n> 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退，但建议迁移到新名。\n\n### 可选：指定知识库\n\n```bash\n$env:IMA_KB_NAME = \"FIM知识库\"  # 默认值\n```\n\n### 验证配置\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nif client.test_connection():\n    print(\"✅ IMA 连接成功\")\nelse:\n    print(\"❌ IMA 连接失败，请检查凭证\")\n```\n\n## API 基础信息（v1.1.7）\n\n- **Base URL**: `https://ima.qq.com`\n- **认证方式**: Header `ima-openapi-clientid` + `ima-openapi-apikey`\n- **数据格式**: JSON\n- **无需本地客户端**: 所有操作通过云端 API 完成\n\n### Notes API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 创建笔记 | `POST /openapi/note/v1/import_doc` | 从 Markdown 创建笔记 |\n| 追加内容 | `POST /openapi/note/v1/append_doc` | 向现有笔记追加内容 |\n| 获取笔记内容 | `POST /openapi/note/v1/get_doc_content` | 读取笔记纯文本/JSON |\n| 列出笔记 | `POST /openapi/note/v1/list_note` | 列出笔记本中的笔记 |\n| 搜索笔记 | `POST /openapi/note/v1/search_note` | 按标题/正文搜索 |\n| 列出笔记本 | `POST /openapi/note/v1/list_notebook` | 列出所有笔记本 |\n\n### Knowledge Base API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 搜索知识库 | `POST /openapi/wiki/v1/search_knowledge_base` | 按名称搜索，返回 `kb_id` |\n| 可添加知识库列表 | `POST /openapi/wiki/v1/get_addable_knowledge_base_list` | 列出可添加内容的知识库 |\n| 添加知识 | `POST /openapi/wiki/v1/add_knowledge` | 添加笔记/网页/文件到知识库 |\n| 浏览知识库 | `POST /openapi/wiki/v1/get_knowledge_list` | 浏览知识库内容 |\n| 导入 URL | `POST /openapi/wiki/v1/import_urls` | 服务端抓取 URL（保留图片） |\n\n## 存储流程\n\n### 流程 1：纯文本笔记（X/Twitter/飞书/手动内容）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\n\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\nnote_id = note[\"note_id\"]\n\n# Step 2: 添加到知识库（Knowledge Base API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(\n    note_id=note_id,\n    title=\"标题\",\n    knowledge_base_id=kb_id,  # media_type=11, note_info.content_id=note_id\n)\n```\n\n### 流程 2：URL 导入（公众号/普通网页 — 保留图片）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\n\n# IMA 服务端抓取 URL，保留图片和排版\nresults = client.import_urls(\n    knowledge_base_id=kb_id,\n    urls=[\"https://mp.weixin.qq.com/s/xxxxx\"],\n)\n```\n\n### 智能路由（推荐用 save_to_ima）\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 自动路由：\n# - 公众号/网页 URL → import_urls（保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n```\n\n## add_knowledge 的 media_type 枚举\n\n| media_type | 类型 | note_info/web_info 字段 |\n|-----------|------|------------------------|\n| 2 | 网页 | `web_info.content_id=<url>` |\n| 6 | 公众号文章 | 同上，URL 匹配 `mp.weixin.qq.com/s` |\n| 11 | 笔记 | `note_info.content_id=<note_id>` |\n| 7 | Markdown | 需先 create_media + COS 上传 |\n\n## IMA 存放路由规则\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **Api Key 等同于密码**，不要泄露给他人\n- 永远不要将真实凭证提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 定期轮换 Api Key\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `401 Unauthorized` | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY` 是否正确 |\n| `404 Not Found` | API 端点已变更，确认用 `/openapi/note/v1/import_doc`（非 `/v1/note/create`） |\n| 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| `import_urls` 文件夹不存在 | folder_id 不等于 knowledge_base_id，用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n| `code=210001` 参数错误 | 检查请求体 JSON 格式，`content_format` 必须为 1（MARKDOWN） |\n\nFile v3.3.0:CHANGELOG.md\n\n# Changelog\n\n本文件记录 web-to-fim 技能的版本演进。版本号遵循 [语义化版本](https://semver.org/)。\n\n## [3.3.0] - 2026-07-12\n\n### 新增\n- **原文链接自动提取**：`extract_original_url()` 函数从 Markdown 前 800 字符自动识别\"原文链接\"/\"转载自\"/\"本文首发\"等关键词\n- **IMA 路由精细化**：GitHub URL 改为纯文本笔记（IMA 抓取 HTML 页面效果差），不再走 import_urls\n- **飞书 wiki 自动路由函数**：`_is_feishu_wiki()` 和 `_fetch_feishu_wiki_via_webfetch()` 新增\n\n### 修复\n- **IMA 路由规则修正**：原文链接为 GitHub 时，原逻辑走 import_urls 导致 IMA 抓取 HTML 页面内容混乱。改为纯文本笔记存转录 MD\n- **路由规则文档化**：IMA 路由规则精细化（公众号/普通网页→import_urls；X/Twitter/飞书/GitHub→纯文本笔记）\n\n## [3.2.0] - 2026-07-12\n\n### 新增\n- **Obsidian 文件命名规范化**：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n- **来源自动提取**：`_extract_source_name()` 函数从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n- **飞书 wiki 原文链接优先转录**：抓取飞书 wiki 后检查文章头部\"原文链接\"，有则优先抓取原文内容（公众号/X 等），获得更完整的正文和图片\n- **IMA 智能路由优化**：飞书 wiki 有公众号原文链接 → import_urls（保留图片）；无原文链接 → 纯文本笔记\n\n### 修复\n- Windows 文件名安全：禁止字符（`\\ / : * ? \" < > |`）替换为下划线，中文标点（含 `：`）保留\n- 文件名长度限制：标题超过 60 字符自动截断，避免文件名过长\n\n## [3.1.0] - 2026-07-11\n\n### 新增\n- 批量模式断点恢复：自动生成 `.progress.json` 进度文件，崩溃后重跑自动跳过已完成 URL，全部成功后自动清理\n- Obsidian frontmatter 增加 `tags` 字段：根据 URL 来源自动分类标签（x-twitter/wechat/weibo/xiaohongshu/github/youtube/webpage/local-file）\n- `save_to_obsidian` 三级 fallback 机制：重试 3 次 → ASCII 文件名 → 脚本目录 `saved/`\n- `_process_single` 每个存储操作独立 try/except：一处失败不阻断其他存储\n\n### 修复\n- **Critical**: `tweet_to_md.py` 去掉硬编码的段落标题列表，改为通用启发式规则（Emoji 模式匹配 + 数字编号 + 短行特征 + 技术名词后缀）\n- **Critical**: `web_to_md.py` `_run()` 函数加 120 秒 timeout，防止 x-tweet-fetcher 网络异常时永久挂起\n- **Important**: `_fetch_wechat_mobile()` 改进正文提取：保留图片（data-src）、段落结构（`<p>`/`<section>`）、引用块（blockquote），不再丢失内容\n- **Minor**: 标题提取改进：支持从 frontmatter `title:` 提取，fallback 到 URL 域名生成标题，不再出现 `Untitled`\n- **Minor**: `import time` / `import json` 移到文件顶部\n- **Minor**: `.gitignore` 补充 `saved/`、`batch_urls.txt`、`*.progress.json`、`batch_run.log` 等临时文件\n\n## [3.0.2] - 2026-07-11\n\n### 修复\n- 同步本地版本号与 ClawHub 线上版本（本地从 3.0.1 对齐到 3.0.2）\n- 修复 SKILL.md 安全声明章节的 Markdown 语法瑕疵：\n  - 第 261 行 `--no-ima` 反引号缺失\n  - 第 258 / 263 / 268 行 `**文件操作` / `**隐私保护` / `**权限透明` 加粗未闭合\n\n### 文档\n- 新增 CHANGELOG.md，补齐版本演进记录\n\n## [3.0.1] - 2026-07-11\n\n### 修复\n- 更新 ClawHub 页面 Short summary，反映 v3.0 的信源与存储能力\n  - frontmatter description 增加公众号/网页图片保留、飞书 wiki 转录说明\n  - 信源表标注 IMA 存储路由（IMA 笔记 → IMA 知识库）\n\n## [3.0.0] - 2026-07-10\n\n### 新增\n- **IMA 智能路由**：公众号/普通网页 → `import_urls` 服务端抓取，保留原文图片和排版\n- **飞书 wiki 信源**：通过 WebFetch 转录飞书知识库文章全文\n- **公众号反爬 fallback**：markitdown 返回验证页时自动切换移动端 UA 重试\n- **批量模式**：`--urls-file` 参数支持从文件逐行读取 URL 批量处理\n- **试运行模式**：`--dry-run` 参数仅转 Markdown 不入库\n\n### 变更\n- **IMA API 迁移到 v1.1.7**：创建笔记改用 `/openapi/note/v1/import_doc`\n- **IMA 存储从\"笔记本\"改为\"知识库\"两步流程**：\n  1. `create_note` 创建笔记（Notes API）\n  2. `add_note_to_knowledge_base` 添加到知识库（Wiki API）\n- **环境变量更名**：`IMA_CLIENT_ID` / `IMA_API_KEY` → `IMA_OPENAPI_CLIENTID` / `IMA_OPENAPI_APIKEY`（旧名仍兼容回退）\n- X/Twitter 链接强制走纯文本笔记逐字转录，不使用 `import_urls`\n\n### 安全\n- 凭证全部通过环境变量配置，无硬编码\n- 清理临时脚本中的真实 IMA 凭证\n- 完善 .gitignore 排除规则\n\nFile v3.3.0:README.en.md\n\nEnglish | [中文](./README.md)\n\n# web-to-FIM\n\n> Convert any web link or local file into structured Markdown, and store it in three destinations: Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base.\n\n## Core Features\n\n### Supported Sources (7 URL Types + Local Files)\n\n| Source | URL Pattern | Fetch Method |\n|--------|------------|-------------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher (verbatim transcript) |\n| WeChat Article | `mp.weixin.qq.com` | markitdown + mobile UA fallback |\n| Feishu Wiki | `*.feishu.cn/wiki/` | WebFetch full transcript |\n| Xiaohongshu | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| Weibo | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| Any Webpage | other `http(s)://` URLs | markitdown |\n\nLocal file support: PDF, Word, PPT, Excel, images, audio, CSV/JSON/XML, etc.\n\n### Three Destinations\n\n| Destination | Environment Variable | Description |\n|-------------|---------------------|-------------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | Local Markdown + frontmatter + tags |\n| Feishu Cloud Docs | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | Cloud team collaboration |\n| Tencent IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI-native knowledge base (FIM) |\n\n## Quick Start\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"Custom Title\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## Environment Variables\n\n```bash\n# Obsidian Vault path (optional, has default)\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n\n# Feishu credentials\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\nexport IMA_KB_NAME=\"FIM知识库\"\n```\n\n> Credentials must be configured via environment variables, never hardcoded. Legacy variable names `IMA_CLIENT_ID` / `IMA_API_KEY` are still supported as fallback.\n\n## Usage Examples\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## Trigger Words\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\nTriggered when the user provides any URL or local file and requests conversion to a document.\n\n## Verify Connections\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA Smart Routing (v3.0)\n\n| source_url Type | IMA Storage Method | Reason |\n|----------------|-------------------|--------|\n| WeChat / General webpage | `import_urls` (server-side fetch) | Preserve images and layout |\n| X/Twitter | Plain text note (verbatim transcript) | Skill rule requires verbatim |\n| Feishu wiki | Plain text note (verbatim transcript) | Requires login, IMA cannot fetch |\n\n## Version History\n\n- **v3.1.0**: Batch mode checkpoint recovery; Obsidian frontmatter auto tags; generalized tweet structured conversion; subprocess 120s timeout; improved WeChat content extraction\n- **v3.0.0**: IMA switched to knowledge base two-step flow; WeChat/webpage with images (import_urls); added Feishu wiki source; WeChat anti-scraping fallback\n- **v2.x**: Basic three-destination storage; X/Twitter verbatim transcript; Feishu Cloud Docs integration\n\nSee [CHANGELOG.md](./CHANGELOG.md) for details.\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.3.0:skill-card.md\n\n## Description: <br>\nConverts user-provided URLs or local files into structured Markdown and can save the result to Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[edwardwason](https://clawhub.ai/user/edwardwason) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers, knowledge workers, and external users use this skill to ingest web pages, social posts, Feishu wiki pages, and local documents into Markdown-based knowledge workflows. It is intended for document conversion and storage, not for authoring new document content or editing Feishu document bodies. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Input URLs and local files may be saved locally and uploaded to Feishu or Tencent IMA. <br>\nMitigation: Process only content intended for those destinations, and use --no-feishu, --no-ima, --no-obsidian, or --dry-run when storage or upload is not desired. <br>\nRisk: Unrelated GitHub publishing helpers can read GH_TOKEN and modify a remote repository if executed. <br>\nMitigation: Review or remove scripts/_gh_push.py and scripts/_gh_release.py before use, and avoid running underscored helper scripts in normal document-conversion workflows. <br>\nRisk: Feishu, Tencent IMA, and GitHub credentials may grant access to external services. <br>\nMitigation: Store credentials only in environment variables or a secrets manager, use least-privilege credentials where available, and rotate or revoke credentials if exposure is suspected. <br>\nRisk: Private URLs, signed links, and sensitive local files may be sent to cloud services during conversion or import. <br>\nMitigation: Do not process private or sensitive sources unless cloud upload is intentional and approved for the use case. <br>\n\n\n## Reference(s): <br>\n- [README.en.md](README.en.md) <br>\n- [CHANGELOG.md](CHANGELOG.md) <br>\n- [Feishu setup guide](references/feishu-setup.md) <br>\n- [Tencent IMA setup guide](references/ima-setup.md) <br>\n- [Feishu block mapping](references/feishu-blocks.md) <br>\n- [Feishu Open Platform](https://open.feishu.cn/) <br>\n- [Tencent IMA Agent Interface](https://ima.qq.com/agent-interface) <br>\n- [x-tweet-fetcher optional dependency](https://github.com/EdwardWason/x-tweet-fetcher.git) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance] <br>\n**Output Format:** [Markdown documents with frontmatter, Feishu document blocks, IMA knowledge entries, CLI status text, and setup guidance.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Can write local Markdown files and call Feishu or Tencent IMA cloud APIs when configured; supports batch URL processing and dry-run conversion.] <br>\n\n## Skill Version(s): <br>\n3.3.0 (source: server release, SKILL.md frontmatter, CHANGELOG.md) <br>\n\n## Ethical Considerations: <br>\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. <br>\n\nFile v3.3.0:requirements.txt\n\nrequests\npython-dotenv\n\nArchive v3.2.0: 16 files, 40144 bytes\n\nFiles: _meta.json (129b), CHANGELOG.md (4113b), README.en.md (4142b), README.md (3967b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/save_fetched.py (3424b), scripts/tweet_to_md.py (7319b), scripts/web_to_all.py (15028b), scripts/web_to_md.py (8091b), skill-card.md (2772b), SKILL.md (12877b)\n\nFile v3.2.0:SKILL.md\n\n---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.2.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云文档、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（WebFetch 全文转录）；(4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云文档（团队协作）+ IMA 知识库（FIM知识库，AI 原生）。\n  IMA 智能路由：公众号/网页 → import_urls 保留图片；X/Twitter/飞书 → 纯文本笔记逐字转录。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n  Do NOT use for 创建文档内容、编辑飞书文档正文、代码开发、非文档转存任务。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📚 **飞书云文档** - 云端团队协作\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地保存到指定目录，带 frontmatter（默认：`E:\\Obsidian\\md\\inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端服务，参考 `references/feishu-setup.md` |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | **云端 API v1.1.7**，两步流程存入知识库，参考 `references/ima-setup.md` |\n\n### Obsidian Vault 路径配置\n跨平台支持，通过环境变量 `OBSIDIAN_VAULT_PATH` 配置：\n\n```bash\n# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian\\Vault\\inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n```\n\n如果未设置，默认使用：\n- Windows: `E:\\Obsidian\\md\\inbox`\n- macOS/Linux: `~/Obsidian/inbox`\n\n## 一键保存到所有目的地\n\n使用 `web_to_all.py` 一键转换并保存到 Obsidian/飞书/IMA：\n\n```bash\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian\n```\n\n## 安全配置\n\n⚠️ **凭证必须通过环境变量配置**，禁止硬编码：\n\n### 飞书配置\n\n```bash\n# 设置环境变量\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n```\n\n参考 [references/feishu-setup.md](references/feishu-setup.md) 获取凭证。\n\n### ima 配置\n\n```bash\n# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> ⚠️ **v3.0 变更**：环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`（旧名仍兼容回退）。IMA 存储从\"笔记本\"改为\"知识库\"两步流程。\n\n参考 [references/ima-setup.md](references/ima-setup.md) 获取凭证。\n\n## 工作流\n\n### 步骤 1：转换为 Markdown\n\n```bash\npython3 scripts/web_to_md.py --url \"<url_or_path>\" --output <output.md>\n```\n\n路由逻辑：\n- **X/Twitter** → x-tweet-fetcher 抓取 JSON → tweet_to_md.py 结构化转换（逐字转录）\n- **飞书 wiki**（`*.feishu.cn/wiki/`）→ WebFetch 抓取全文 → 检查原文链接 → 有则优先抓取原文（v3.2.0）\n- **公众号**（`mp.weixin.qq.com`）→ markitdown 转换，反爬时自动 fallback 到移动端 UA\n- **其他网页/本地文件** → markitdown 直接转换\n\n> **v3.2.0 飞书 wiki 原文链接优先转录**：\n> - 抓取飞书 wiki 后，检查文章头部是否有\"原文链接\"（如 `🔗 原文链接：[url]`）\n> - 有原文链接 → 优先抓取原文链接内容（公众号/X 等），获得更完整的正文和图片\n> - 无原文链接 → 用飞书 wiki 内容\n> - IMA 存放：有公众号原文链接 → import_urls（保留图片）；无 → 纯文本笔记\n\n> **v3.0 新增信源支持**：\n> - 飞书 wiki 文档：通过 WebFetch 转录飞书知识库文章全文\n> - 公众号反爬 fallback：markitdown 返回验证页时自动切换移动端 UA 重试\n\n> **v3.2.0 新增**：\n> - Obsidian 文件命名规范化：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n> - 来源自动提取：从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n> - 飞书 wiki 原文链接优先转录：抓取飞书 wiki 后检查原文链接，有则优先抓取原文内容（更完整）\n> - Windows 文件名安全：禁止字符替换为下划线，中文标点（含：）保留\n\n> **v3.1 新增**：\n> - 批量模式断点恢复：崩溃后重跑自动跳过已完成 URL（`.progress.json` 进度文件）\n> - Obsidian frontmatter 自动 tags：根据 URL 来源分类标签\n> - 推文结构化转换通用化：去硬编码，基于启发式规则识别段落标题\n> - subprocess 加 120 秒 timeout：防止网络异常永久挂起\n> - 公众号正文提取改进：保留图片、段落结构、引用块\n\n### 步骤 2：存入目的地\n\n#### Obsidian Vault\n\n文件名规则：`YYYYMMDD-标题-来源.md`（v3.2.0）\n- 来源从 URL 自动提取（waytoagi/feishu/x/wechat 等）\n- 示例：`20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`\n\n```python\nfrom scripts.web_to_all import save_to_obsidian\nfilepath = save_to_obsidian(markdown_content, title, url)\n```\n\n#### 飞书云文档\n\n```python\nfrom scripts.feishu_client import FeishuClient\n\nclient = FeishuClient()\nresult = client.create_document(title=\"文档标题\", content_md=markdown_content)\nprint(f\"文档 URL: {result['url']}\")\n```\n\n#### 腾讯 ima（v3.0 — 知识库两步流程 + 图片保留）\n\nIMA 有**两套独立 API**，不可混用：\n- **Notes API**（`/openapi/note/v1/`）：管笔记、笔记本\n- **Knowledge Base API**（`/openapi/wiki/v1/`）：管知识库、知识条目\n\n「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。必须用两步流程。\n\n> **v3.0 核心功能 — 公众号/网页带图片转录**：\n> - 公众号和普通网页 URL 通过 `import_urls` 让 IMA 服务端抓取，**保留原文图片和排版**\n> - X/Twitter 和飞书 wiki 走纯文本笔记（逐字转录），因为 X 要求逐字转录、飞书需登录认证\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 方式1：直接用 save_to_ima（推荐，自动路由）\n# - 公众号/普通网页 URL → import_urls（服务端抓取，保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n\n# 方式2：手动两步流程\nfrom scripts.ima_client import IMAClient\nclient = IMAClient()\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\n# Step 2: 添加到知识库（Wiki API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(note_id=note[\"note_id\"], title=\"标题\", knowledge_base_id=kb_id)\n```\n\n**IMA 存放路由规则（v3.0）**：\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n### 验证连接\n\n```bash\n# 验证飞书\npython scripts/feishu_client.py --action test\n\n# 验证 ima\npython scripts/ima_client.py --action test\n```\n\n## 故障处理\n\n| 问题 | 解决方案 |\n|------|---------|\n| x.com SSL 超时 | x-tweet-fetcher 使用 FxTwitter API 中转 |\n| markitdown 模块丢失 | `pip install markitdown` |\n| 微信反爬拦截 | markitdown 返回72字符验证页，需 fallback 到 WebFetch 或移动端 UA |\n| 飞书凭证无效 | 检查 `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` |\n| 飞书 blocks 400 错误 | 单次最多 50 个 blocks，长文章需分批插入（见 `references/feishu-blocks.md`） |\n| 飞书 block_type 错误 | Code=14、Quote=15、Text=2、Heading1-3=3-5、Bullet=12（见 `references/feishu-blocks.md`） |\n| ima 凭证无效 | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY`（v3.0） |\n| IMA 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| IMA import_urls 文件夹不存在 | folder_id 不等于 knowledge_base_id，需用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n\n## 依赖与安装\n\n### 完整依赖列表\n\n| 依赖 | 安装命令 | 说明 |\n|------|---------|------|\n| markitdown | `pip install markitdown` | 网页转 Markdown 核心库 |\n| requests | `pip install requests` | HTTP 请求 |\n| python-dotenv | `pip install python-dotenv` | 环境变量管理 |\n| x-tweet-fetcher | 克隆到 `~/.aily/workspace/skills/x-tweet-fetcher` | X/Twitter 专用抓取（可选） |\n\n### 一键安装所有依赖\n\n```bash\n# 安装 Python 依赖\npip install markitdown requests python-dotenv\n```\n\n### x-tweet-fetcher（可选，仅用于 X/Twitter）\n```bash\n# 克隆到技能目录\ncd ~/.aily/workspace/skills\ngit clone https://github.com/EdwardWason/x-tweet-fetcher.git\n```\n\n如果不安装 x-tweet-fetcher，X/Twitter 链接将使用 markitdown 直接处理。\n\n---\n\n## 安全声明\n\n### 🔒 安全设计原则\n\n1. **凭证安全**\n   - 所有 API 凭证通过环境变量配置，**无硬编码**\n   - 支持 `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `IMA_OPENAPI_CLIENTID`, `IMA_OPENAPI_APIKEY`（v3.0）\n   - 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退\n\n2. **文件操作**\n   - 仅在用户明确指定时写入文件\n   - Obsidian Vault 路径完全可控\n   - 支持通过 `--no-feishu` / `--no-ima` 选择性禁用功能\n\n3. **隐私保护**\n   - 不读取任何未经授权的用户配置文件\n   - 所有网络请求仅针对用户提供的 URL\n   - 本地文件仅用于转换，不主动扫描\n\n4. **权限透明**\n   - 文件写入范围：Obsidian Vault 目录、临时 Markdown 文件\n   - 文件读取范围：用户指定的 URL、本地输入文件\n\nFile v3.2.0:README.md\n\n[English](./README.en.md) | 中文\n\n# web-to-FIM\n\n> 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 核心功能\n\n### 支持的信源（7 类 URL + 本地文件）\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n本地文件支持：PDF、Word、PPT、Excel、图片、音频、CSV/JSON/XML 等。\n\n### 三处存放\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地 Markdown + frontmatter + tags |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端团队协作 |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI 原生知识库（FIM知识库） |\n\n## 快速开始\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## 环境变量配置\n\n```bash\n# Obsidian Vault path (optional, has default)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Feishu credentials\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> 凭证必须通过环境变量配置，禁止硬编码。旧变量名 `IMA_CLIENT_ID` / `IMA_API_KEY` 仍兼容回退。\n\n## 使用示例\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## 触发词\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\n当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n\n## 验证连接\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA 智能路由（v3.0）\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号 / 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| X/Twitter | 纯文本笔记（逐字转录） | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n\n## 版本历史\n\n- **v3.1.0**：批量模式断点恢复；Obsidian frontmatter 自动 tags；推文结构化转换通用化；subprocess 120 秒 timeout；公众号正文提取改进\n- **v3.0.0**：IMA 改用知识库两步流程；公众号/网页带图片转录（import_urls）；新增飞书 wiki 信源；公众号反爬 fallback\n- **v2.x**：基础三处存放功能；X/Twitter 逐字转录；飞书云文档集成\n\n详见 [CHANGELOG.md](./CHANGELOG.md)。\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"web-to-fim\",\n  \"version\": \"3.2.0\",\n  \"publishedAt\": 1783828764482\n}\n\nFile v3.2.0:references/feishu-blocks.md\n\n# 飞书云文档 Block 类型映射表\n\n> 飞书 Docx API 的 block_type 枚举值。创建文档 blocks 时必须使用正确的 block_type，否则返回 400 Bad Request。\n\n## block_type 完整映射\n\n| block_type | 名称 | Markdown 对应 | block 字段名 |\n|-----------|------|-------------|------------|\n| 1 | Page（页面根块） | — | `page` |\n| 2 | Text（文本） | 普通段落 | `text` |\n| 3 | Heading1（一级标题） | `# ` | `heading1` |\n| 4 | Heading2（二级标题） | `## ` | `heading2` |\n| 5 | Heading3（三级标题） | `### ` | `heading3` |\n| 6 | Heading4（四级标题） | `#### ` | `heading4` |\n| 7 | Heading5（五级标题） | `##### ` | `heading5` |\n| 8 | Heading6（六级标题） | `###### ` | `heading6` |\n| 9 | Heading7（七级标题） | — | `heading7` |\n| 10 | Heading8（八级标题） | — | `heading8` |\n| 11 | Heading9（九级标题） | — | `heading9` |\n| 12 | Bullet（无序列表） | `- ` 或 `* ` | `bullet` |\n| 13 | Ordered（有序列表） | `1. ` | `ordered` |\n| 14 | Code（代码块） | ` ``` ` | `code` |\n| 15 | Quote（引用） | `> ` | `quote` |\n\n## 常见错误\n\n| 错误 | 正确值 | 说明 |\n|------|-------|------|\n| Code 用 block_type=2 | **block_type=14** | 2 是 Text，不是 Code |\n| Quote 用 block_type=11 | **block_type=15** | 11 是 Heading9，不是 Quote |\n\n## Block 结构示例\n\n### Text（block_type=2）\n\n```json\n{\n    \"block_type\": 2,\n    \"text\": {\n        \"elements\": [{\"text_run\": {\"content\": \"文本内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Heading1（block_type=3）\n\n```json\n{\n    \"block_type\": 3,\n    \"heading1\": {\n        \"elements\": [{\"text_run\": {\"content\": \"标题内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Bullet（block_type=12）\n\n```json\n{\n    \"block_type\": 12,\n    \"bullet\": {\n        \"elements\": [{\"text_run\": {\"content\": \"列表项\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Code（block_type=14）\n\n```json\n{\n    \"block_type\": 14,\n    \"code\": {\n        \"elements\": [{\"text_run\": {\"content\": \"code content\"}}],\n        \"style\": {\"language\": 1}\n    }\n}\n```\n\n### Quote（block_type=15）\n\n```json\n{\n    \"block_type\": 15,\n    \"quote\": {\n        \"elements\": [{\"text_run\": {\"content\": \"引用内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n## 关键约束\n\n### 1. elements 中不要加多余字段\n\n```json\n// ❌ 错误 — 多了 \"type\" 字段\n{\"text_run\": {\"type\": \"text_run\", \"content\": \"文本\"}}\n\n// ✅ 正确\n{\"text_run\": {\"content\": \"文本\"}}\n```\n\n### 2. 空行不要创建空文本块\n\n```python\n# ❌ 错误 — 空行创建空块会导致 400\nif not stripped:\n    blocks.append({\"block_type\": 2, \"text\": {\"elements\": [{\"text_run\": {\"content\": \"\"}}]}})\n\n# ✅ 正确 — 空行直接跳过\nif not stripped:\n    continue\n```\n\n### 3. 图片块需要预上传 token\n\n图片不能直接用 URL，必须先通过飞书上传 API 获取 `file_token`，再创建图片块。当前实现暂时跳过图片。\n\n### 4. 单次请求最多 50 个 blocks\n\n```\nPOST /docx/v1/documents/{document_id}/blocks/{document_id}/children\n```\n\n**payload 中 `children` 数组最多 50 个 block**。长文章必须分批插入：\n\n```python\nfor i in range(0, len(blocks), 50):\n    batch = blocks[i:i+50]\n    requests.post(url, headers=headers, json={\"children\": batch})\n```\n\n### 5. payload 中不要传 index\n\n```json\n// ❌ 错误 — index=-1 可能导致问题\n{\"children\": blocks, \"index\": -1}\n\n// ✅ 正确 — 不传 index，默认追加到末尾\n{\"children\": blocks}\n```\n\n## API 端点\n\n| 操作 | 方法 | URL |\n|------|------|-----|\n| 创建文档 | POST | `/docx/v1/documents` |\n| 插入 blocks | POST | `/docx/v1/documents/{document_id}/blocks/{document_id}/children` |\n| 获取文档信息 | GET | `/docx/v1/documents/{document_id}` |\n\n## 认证\n\n```\nAuthorization: Bearer {tenant_access_token}\nContent-Type: application/json\n```\n\n获取 token：`POST /auth/v3/tenant_access_token/internal`，payload 为 `{\"app_id\": \"...\", \"app_secret\": \"...\"}`。\n\nFile v3.2.0:references/feishu-setup.md\n\n# 飞书云文档 API 配置指南\n\n## 获取凭证\n\n### 步骤 1: 创建飞书应用\n\n1. 访问 [飞书开放平台](https://open.feishu.cn/)\n2. 登录后进入「开发者后台」\n3. 点击「创建应用」，填写应用名称和描述\n4. 获取 **App ID** 和 **App Secret**\n\n### 步骤 2: 配置权限\n\n在应用后台开启以下权限：\n\n| 权限名称 | 权限说明 | 必要性 |\n|---------|---------|--------|\n| `docx.document:readonly` | 读取云文档 | 可选 |\n| `docx.document:write` | 创建/编辑云文档 | 必须 |\n| `drive:drive:folder` | 云文档文件夹操作 | 必须 |\n| `sheets:Spreadsheet:readonly` | 读取表格 | 可选 |\n\n### 步骤 3: 发布应用\n\n1. 在「版本管理与发布」中创建版本\n2. 选择「发布」并等待审核（或自建企业直接通过）\n\n## 本地配置\n\n### 设置环境变量\n\n```bash\n# Windows PowerShell\n$env:FEISHU_APP_ID=\"your_app_id\"\n$env:FEISHU_APP_SECRET=\"your_app_secret\"\n\n# Linux/macOS\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n```\n\n### 验证配置\n\n```python\nfrom feishu_client import FeishuClient\n\nclient = FeishuClient()\nif client.test_connection():\n    print(\"✅ 飞书连接成功\")\nelse:\n    print(\"❌ 飞书连接失败，请检查凭证\")\n```\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **永远不要**将 `.env` 文件或包含真实凭证的文件提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 生产环境建议使用密钥管理服务（如 AWS Secrets Manager）\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `invalid_app_id` | 检查 App ID 是否正确 |\n| `app_secret` 错误 | 在飞书开放平台重置 App Secret |\n| 权限不足 | 在应用后台添加所需权限并重新发布 |\n| 签名校验失败 | 确保使用 HTTPS，检查时间戳是否正确 |\n\nFile v3.2.0:references/ima-setup.md\n\n# 腾讯 IMA 知识库 API 配置指南（v3.0 — IMA OpenAPI v1.1.7）\n\n> ⚠️ **v3.0 重大变更**：\n> - API 端点从 `/v1/note/create` 迁移到 `/openapi/note/v1/import_doc`\n> - Base URL 从 `https://ima.im.qq.com/openapi` 改为 `https://ima.qq.com`\n> - 环境变量从 `IMA_CLIENT_ID`/`IMA_API_KEY` 改为 `IMA_OPENAPI_CLIENTID`/`IMA_OPENAPI_APIKEY`\n> - 存储模式从\"笔记本\"改为\"知识库\"两步流程\n\n## 两套 API 系统（不可混用）\n\nIMA 有两套完全独立的 API，对应 UI 中两个不同的标签页：\n\n| API 系统 | 路径前缀 | 管理对象 | UI 对应 |\n|---------|---------|---------|---------|\n| **Notes API** | `/openapi/note/v1/` | 笔记、笔记本 | IMA「笔记本」标签页 |\n| **Knowledge Base API** | `/openapi/wiki/v1/` | 知识库、知识条目 | IMA「知识库」标签页 |\n\n**关键区别**：「FIM知识库」是**知识库**（wiki API），不是笔记本（note API）。\n\n## 获取凭证\n\n### 步骤 1: 访问 IMA 开放平台\n\n打开 [ima.qq.com/agent-interface](https://ima.qq.com/agent-interface)\n\n### 步骤 2: 登录并获取凭证\n\n1. 使用 QQ 或微信扫码登录\n2. 在「Agent 接口」页面获取凭证：\n   - **Client ID**: 应用标识\n   - **Api Key**: API 密钥\n\n### 步骤 3: 复制凭证\n\n```text\nClient ID: your_client_id_here\nApi Key: your_api_key_here\n```\n\n## 本地配置\n\n### 设置环境变量（v3.0）\n\n```bash\n# Windows PowerShell — 持久化设置\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_CLIENTID\", \"your_client_id\", \"User\")\n[System.Environment]::SetEnvironmentVariable(\"IMA_OPENAPI_APIKEY\", \"your_api_key\", \"User\")\n\n# Windows PowerShell — 临时设置（当前会话）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Linux/macOS\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n```\n\n> 旧变量名 `IMA_CLIENT_ID`/`IMA_API_KEY` 仍兼容回退，但建议迁移到新名。\n\n### 可选：指定知识库\n\n```bash\n$env:IMA_KB_NAME = \"FIM知识库\"  # 默认值\n```\n\n### 验证配置\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nif client.test_connection():\n    print(\"✅ IMA 连接成功\")\nelse:\n    print(\"❌ IMA 连接失败，请检查凭证\")\n```\n\n## API 基础信息（v1.1.7）\n\n- **Base URL**: `https://ima.qq.com`\n- **认证方式**: Header `ima-openapi-clientid` + `ima-openapi-apikey`\n- **数据格式**: JSON\n- **无需本地客户端**: 所有操作通过云端 API 完成\n\n### Notes API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 创建笔记 | `POST /openapi/note/v1/import_doc` | 从 Markdown 创建笔记 |\n| 追加内容 | `POST /openapi/note/v1/append_doc` | 向现有笔记追加内容 |\n| 获取笔记内容 | `POST /openapi/note/v1/get_doc_content` | 读取笔记纯文本/JSON |\n| 列出笔记 | `POST /openapi/note/v1/list_note` | 列出笔记本中的笔记 |\n| 搜索笔记 | `POST /openapi/note/v1/search_note` | 按标题/正文搜索 |\n| 列出笔记本 | `POST /openapi/note/v1/list_notebook` | 列出所有笔记本 |\n\n### Knowledge Base API 端点\n\n| 功能 | 端点 | 说明 |\n|------|------|------|\n| 搜索知识库 | `POST /openapi/wiki/v1/search_knowledge_base` | 按名称搜索，返回 `kb_id` |\n| 可添加知识库列表 | `POST /openapi/wiki/v1/get_addable_knowledge_base_list` | 列出可添加内容的知识库 |\n| 添加知识 | `POST /openapi/wiki/v1/add_knowledge` | 添加笔记/网页/文件到知识库 |\n| 浏览知识库 | `POST /openapi/wiki/v1/get_knowledge_list` | 浏览知识库内容 |\n| 导入 URL | `POST /openapi/wiki/v1/import_urls` | 服务端抓取 URL（保留图片） |\n\n## 存储流程\n\n### 流程 1：纯文本笔记（X/Twitter/飞书/手动内容）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\n\n# Step 1: 创建笔记（Notes API）\nnote = client.create_note(title=\"标题\", content=markdown_content)\nnote_id = note[\"note_id\"]\n\n# Step 2: 添加到知识库（Knowledge Base API）\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\nclient.add_note_to_knowledge_base(\n    note_id=note_id,\n    title=\"标题\",\n    knowledge_base_id=kb_id,  # media_type=11, note_info.content_id=note_id\n)\n```\n\n### 流程 2：URL 导入（公众号/普通网页 — 保留图片）\n\n```python\nfrom scripts.ima_client import IMAClient\n\nclient = IMAClient()\nkb_id = client.find_knowledge_base_by_name(\"FIM知识库\")\n\n# IMA 服务端抓取 URL，保留图片和排版\nresults = client.import_urls(\n    knowledge_base_id=kb_id,\n    urls=[\"https://mp.weixin.qq.com/s/xxxxx\"],\n)\n```\n\n### 智能路由（推荐用 save_to_ima）\n\n```python\nfrom scripts.web_to_all import save_to_ima\n\n# 自动路由：\n# - 公众号/网页 URL → import_urls（保留图片）\n# - X/Twitter/飞书 URL → 纯文本笔记（逐字转录）\nresult = save_to_ima(content, title, knowledge_base=\"FIM知识库\", source_url=url)\n```\n\n## add_knowledge 的 media_type 枚举\n\n| media_type | 类型 | note_info/web_info 字段 |\n|-----------|------|------------------------|\n| 2 | 网页 | `web_info.content_id=<url>` |\n| 6 | 公众号文章 | 同上，URL 匹配 `mp.weixin.qq.com/s` |\n| 11 | 笔记 | `note_info.content_id=<note_id>` |\n| 7 | Markdown | 需先 create_media + COS 上传 |\n\n## IMA 存放路由规则\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号（`mp.weixin.qq.com`） | `import_urls`（服务端抓取） | 保留图片和排版 |\n| 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| **X/Twitter** | **纯文本笔记（逐字转录）** | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n| 无 URL | 纯文本笔记 | 手动内容/飞书转录 |\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **Api Key 等同于密码**，不要泄露给他人\n- 永远不要将真实凭证提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 定期轮换 Api Key\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `401 Unauthorized` | 检查 `IMA_OPENAPI_CLIENTID` 和 `IMA_OPENAPI_APIKEY` 是否正确 |\n| `404 Not Found` | API 端点已变更，确认用 `/openapi/note/v1/import_doc`（非 `/v1/note/create`） |\n| 笔记不在知识库中 | 知识库≠笔记本，必须用两步流程：create_note → add_knowledge |\n| `import_urls` 文件夹不存在 | folder_id 不等于 knowledge_base_id，用 `get_root_folder_id()` 获取 |\n| X 链接 IMA 存储错误 | X/Twitter 必须逐字转录（纯文本笔记），不可用 import_urls |\n| `code=210001` 参数错误 | 检查请求体 JSON 格式，`content_format` 必须为 1（MARKDOWN） |\n\nFile v3.2.0:CHANGELOG.md\n\n# Changelog\n\n本文件记录 web-to-fim 技能的版本演进。版本号遵循 [语义化版本](https://semver.org/)。\n\n## [3.2.0] - 2026-07-12\n\n### 新增\n- **Obsidian 文件命名规范化**：`YYYYMMDD-标题-来源.md`（如 `20260712-歸藏：GPT-5.6 Sol 帮我做了个小工具-waytoagi.md`）\n- **来源自动提取**：`_extract_source_name()` 函数从 URL 域名提取来源标识（waytoagi/feishu/x/wechat/weibo/xiaohongshu/github/youtube/webpage）\n- **飞书 wiki 原文链接优先转录**：抓取飞书 wiki 后检查文章头部\"原文链接\"，有则优先抓取原文内容（公众号/X 等），获得更完整的正文和图片\n- **IMA 智能路由优化**：飞书 wiki 有公众号原文链接 → import_urls（保留图片）；无原文链接 → 纯文本笔记\n\n### 修复\n- Windows 文件名安全：禁止字符（`\\ / : * ? \" < > |`）替换为下划线，中文标点（含 `：`）保留\n- 文件名长度限制：标题超过 60 字符自动截断，避免文件名过长\n\n## [3.1.0] - 2026-07-11\n\n### 新增\n- 批量模式断点恢复：自动生成 `.progress.json` 进度文件，崩溃后重跑自动跳过已完成 URL，全部成功后自动清理\n- Obsidian frontmatter 增加 `tags` 字段：根据 URL 来源自动分类标签（x-twitter/wechat/weibo/xiaohongshu/github/youtube/webpage/local-file）\n- `save_to_obsidian` 三级 fallback 机制：重试 3 次 → ASCII 文件名 → 脚本目录 `saved/`\n- `_process_single` 每个存储操作独立 try/except：一处失败不阻断其他存储\n\n### 修复\n- **Critical**: `tweet_to_md.py` 去掉硬编码的段落标题列表，改为通用启发式规则（Emoji 模式匹配 + 数字编号 + 短行特征 + 技术名词后缀）\n- **Critical**: `web_to_md.py` `_run()` 函数加 120 秒 timeout，防止 x-tweet-fetcher 网络异常时永久挂起\n- **Important**: `_fetch_wechat_mobile()` 改进正文提取：保留图片（data-src）、段落结构（`<p>`/`<section>`）、引用块（blockquote），不再丢失内容\n- **Minor**: 标题提取改进：支持从 frontmatter `title:` 提取，fallback 到 URL 域名生成标题，不再出现 `Untitled`\n- **Minor**: `import time` / `import json` 移到文件顶部\n- **Minor**: `.gitignore` 补充 `saved/`、`batch_urls.txt`、`*.progress.json`、`batch_run.log` 等临时文件\n\n## [3.0.2] - 2026-07-11\n\n### 修复\n- 同步本地版本号与 ClawHub 线上版本（本地从 3.0.1 对齐到 3.0.2）\n- 修复 SKILL.md 安全声明章节的 Markdown 语法瑕疵：\n  - 第 261 行 `--no-ima` 反引号缺失\n  - 第 258 / 263 / 268 行 `**文件操作` / `**隐私保护` / `**权限透明` 加粗未闭合\n\n### 文档\n- 新增 CHANGELOG.md，补齐版本演进记录\n\n## [3.0.1] - 2026-07-11\n\n### 修复\n- 更新 ClawHub 页面 Short summary，反映 v3.0 的信源与存储能力\n  - frontmatter description 增加公众号/网页图片保留、飞书 wiki 转录说明\n  - 信源表标注 IMA 存储路由（IMA 笔记 → IMA 知识库）\n\n## [3.0.0] - 2026-07-10\n\n### 新增\n- **IMA 智能路由**：公众号/普通网页 → `import_urls` 服务端抓取，保留原文图片和排版\n- **飞书 wiki 信源**：通过 WebFetch 转录飞书知识库文章全文\n- **公众号反爬 fallback**：markitdown 返回验证页时自动切换移动端 UA 重试\n- **批量模式**：`--urls-file` 参数支持从文件逐行读取 URL 批量处理\n- **试运行模式**：`--dry-run` 参数仅转 Markdown 不入库\n\n### 变更\n- **IMA API 迁移到 v1.1.7**：创建笔记改用 `/openapi/note/v1/import_doc`\n- **IMA 存储从\"笔记本\"改为\"知识库\"两步流程**：\n  1. `create_note` 创建笔记（Notes API）\n  2. `add_note_to_knowledge_base` 添加到知识库（Wiki API）\n- **环境变量更名**：`IMA_CLIENT_ID` / `IMA_API_KEY` → `IMA_OPENAPI_CLIENTID` / `IMA_OPENAPI_APIKEY`（旧名仍兼容回退）\n- X/Twitter 链接强制走纯文本笔记逐字转录，不使用 `import_urls`\n\n### 安全\n- 凭证全部通过环境变量配置，无硬编码\n- 清理临时脚本中的真实 IMA 凭证\n- 完善 .gitignore 排除规则\n\nFile v3.2.0:README.en.md\n\nEnglish | [中文](./README.md)\n\n# web-to-FIM\n\n> Convert any web link or local file into structured Markdown, and store it in three destinations: Obsidian Vault, Feishu Cloud Docs, and Tencent IMA Knowledge Base.\n\n## Core Features\n\n### Supported Sources (7 URL Types + Local Files)\n\n| Source | URL Pattern | Fetch Method |\n|--------|------------|-------------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher (verbatim transcript) |\n| WeChat Article | `mp.weixin.qq.com` | markitdown + mobile UA fallback |\n| Feishu Wiki | `*.feishu.cn/wiki/` | WebFetch full transcript |\n| Xiaohongshu | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| Weibo | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| Any Webpage | other `http(s)://` URLs | markitdown |\n\nLocal file support: PDF, Word, PPT, Excel, images, audio, CSV/JSON/XML, etc.\n\n### Three Destinations\n\n| Destination | Environment Variable | Description |\n|-------------|---------------------|-------------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | Local Markdown + frontmatter + tags |\n| Feishu Cloud Docs | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | Cloud team collaboration |\n| Tencent IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI-native knowledge base (FIM) |\n\n## Quick Start\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"Custom Title\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## Environment Variables\n\n```bash\n# Obsidian Vault path (optional, has default)\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n\n# Feishu credentials\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\nexport IMA_OPENAPI_CLIENTID=\"your_client_id\"\nexport IMA_OPENAPI_APIKEY=\"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\nexport IMA_KB_NAME=\"FIM知识库\"\n```\n\n> Credentials must be configured via environment variables, never hardcoded. Legacy variable names `IMA_CLIENT_ID` / `IMA_API_KEY` are still supported as fallback.\n\n## Usage Examples\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## Trigger Words\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\nTriggered when the user provides any URL or local file and requests conversion to a document.\n\n## Verify Connections\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA Smart Routing (v3.0)\n\n| source_url Type | IMA Storage Method | Reason |\n|----------------|-------------------|--------|\n| WeChat / General webpage | `import_urls` (server-side fetch) | Preserve images and layout |\n| X/Twitter | Plain text note (verbatim transcript) | Skill rule requires verbatim |\n| Feishu wiki | Plain text note (verbatim transcript) | Requires login, IMA cannot fetch |\n\n## Version History\n\n- **v3.1.0**: Batch mode checkpoint recovery; Obsidian frontmatter auto tags; generalized tweet structured conversion; subprocess 120s timeout; improved WeChat content extraction\n- **v3.0.0**: IMA switched to knowledge base two-step flow; WeChat/webpage with images (import_urls); added Feishu wiki source; WeChat anti-scraping fallback\n- **v2.x**: Basic three-destination storage; X/Twitter verbatim transcript; Feishu Cloud Docs integration\n\nSee [CHANGELOG.md](./CHANGELOG.md) for details.\n\n## License\n\nMIT-0 (c) 2026 EdwardWason\n\nFile v3.2.0:skill-card.md\n\n## Description: <br>\nConverts user-provided web links or local files into structured Markdown and can store the result in an Obsidian vault, Feishu Cloud Docs, and a Tencent IMA knowledge base. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[edwardwason](https://clawhub.ai/user/edwardwason) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers, knowledge workers, and agent operators use this skill to capture URLs or local files as reusable Markdown notes and route them into personal or team knowledge systems. It is suited for document ingestion and archival workflows, not for authoring new document content or editing existing Feishu documents. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: User-provided URLs or local files may be stored persistently in Obsidian, Feishu, and Tencent IMA. <br>\nMitigation: Use --dry-run or disable cloud destinations with --no-feishu and --no-ima when content should remain local or should not be retained. <br>\nRisk: Sensitive or regulated content may be uploaded to third-party cloud services when Feishu or IMA credentials are configured. <br>\nMitigation: Use only approved destinations for the data type being processed and avoid sensitive inputs unless those cloud services are authorized. <br>\nRisk: Runtime dependencies and external fetchers affect conversion behavior and security posture. <br>\nMitigation: Pin and audit dependencies before production use. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/edwardwason/skills/web-to-fim) <br>\n- [Feishu setup](references/feishu-setup.md) <br>\n- [Tencent IMA setup](references/ima-setup.md) <br>\n- [Feishu block mapping](references/feishu-blocks.md) <br>\n- [Feishu Open Platform](https://open.feishu.cn/) <br>\n- [Tencent IMA OpenAPI](https://ima.qq.com/agent-interface) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Markdown, Files, Shell commands, Configuration, Guidance] <br>\n**Output Format:** [Markdown files with YAML frontmatter, cloud document records, command output, and setup guidance] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Can write to a configured Obsidian vault and can call Feishu and Tencent IMA APIs when credentials are configured; dry-run and cloud-disable flags support local-only handling.] <br>\n\n## Skill Version(s): <br>\n3.2.0 (source: frontmatter, changelog, server release metadata) <br>\n\n## Ethical Considerations: <br>\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. <br>\n\nFile v3.2.0:requirements.txt\n\nrequests\npython-dotenv\n\nArchive v3.1.0: 15 files, 37354 bytes\n\nFiles: _meta.json (129b), CHANGELOG.md (3223b), README.en.md (4142b), README.md (3967b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/tweet_to_md.py (7319b), scripts/web_to_all.py (13605b), scripts/web_to_md.py (8091b), skill-card.md (2486b), SKILL.md (11620b)\n\nFile v3.1.0:SKILL.md\n\n---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.1.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云文档、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（WebFetch 全文转录）；(4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云文档（团队协作）+ IMA 知识库（FIM知识库，AI 原生）。\n  IMA 智能路由：公众号/网页 → import_urls 保留图片；X/Twitter/飞书 → 纯文本笔记逐字转录。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📚 **飞书云文档** - 云端团队协作\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | WebFetch 全文转录 |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地保存到指定目录，带 frontmatter（默认：`E:\\Obsidian\\md\\inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端服务，参考 `references/feishu-setup.md` |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | **云端 API v1.1.7**，两步流程存入知识库，参考 `references/ima-setup.md` |\n\n### Obsidian Vault 路径配置\n跨平台支持，通过环境变量 `OBSIDIAN_VAULT_PATH` 配置：\n\n```bash\n# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian\\Vault\\inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian\\Vault\\inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian/Vault/inbox\n```\n\n如果未设置，默认使用：\n- Windows: `E:\\Obsidian\\md\\inbox`\n- macOS/Linux: `~/Obsidian/inbox`\n\n## 一键保存到所有目的地\n\n使用 `web_to_all.py` 一键转换并保存到 Obsidian/飞书/IMA：\n\n```bash\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian\n```\n\n## 安全配置\n\n⚠️ **凭证必须通过环境变量配置**，禁止硬编码：\n\n### 飞书配置\n\n```bash\n# 设置环境变量\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n```\n\n参考 [references/feishu-setup.md](references/feishu-setup.md) 获取凭证。\n\n### ima 配置\n\n```bash\n# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_N\n\nArchive v3.0.2: 12 files, 28732 bytes\n\nFiles: _meta.json (129b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/tweet_to_md.py (6120b), scripts/web_to_all.py (9920b), scripts/web_to_md.py (6613b), skill-card.md (2793b), SKILL.md (10880b)\n\nArchive v3.0.1: 12 files, 28557 bytes\n\nFiles: _meta.json (129b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/tweet_to_md.py (6120b), scripts/web_to_all.py (9920b), scripts/web_to_md.py (6613b), skill-card.md (2763b), SKILL.md (10354b)\n\nArchive v3.0.0: 12 files, 28335 bytes\n\nFiles: _meta.json (129b), references/feishu-blocks.md (3972b), references/feishu-setup.md (1840b), references/ima-setup.md (6751b), requirements.txt (23b), scripts/feishu_client.py (8793b), scripts/ima_client.py (13813b), scripts/tweet_to_md.py (6120b), scripts/web_to_all.py (9920b), scripts/web_to_md.py (6613b), skill-card.md (2846b), SKILL.md (9588b)\n\nArchive v2.2.0: 11 files, 18878 bytes\n\nFiles: _meta.json (129b), references/feishu-setup.md (1840b), references/ima-setup.md (2357b), requirements.txt (23b), scripts/feishu_client.py (9040b), scripts/ima_client.py (6619b), scripts/tweet_to_md.py (6120b), scripts/web_to_all.py (4690b), scripts/web_to_md.py (4969b), skill-card.md (2572b), SKILL.md (7017b)\n\nArchive v2.1.0: 10 files, 16513 bytes\n\nFiles: _meta.json (129b), references/feishu-setup.md (1840b), references/ima-setup.md (2357b), requirements.txt (23b), scripts/feishu_client.py (9040b), scripts/ima_client.py (6619b), scripts/tweet_to_md.py (6120b), scripts/web_to_all.py (4094b), scripts/web_to_md.py (4969b), SKILL.md (5269b)","readmeExcerpt":"Skill: Web To Fim Owner: edwardwason Summary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。 支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）； (3) 飞书... Tags: ai-information-management:3.7.0, latest:3.7.0, productivity:3.7.0 Version history: v3.7.0 | 2026-07-18T15:05:55.458Z | user v3.7.0: Feishu wiki fetch via lark-cli docs +fetch (WebFetch truncation fix). Breaki","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# 1. 安装 lark-cli（一次性）\nnpm i -g @larksuiteoapi/lark-cli\n\n# 2. 用户身份登录（一次性，浏览器授权）\nlark-cli auth login\n\n# 3. 验证身份\nlark-cli whoami\n# 应显示：identity: user, tokenStatus: ready"},{"language":"bash","snippet":"# Windows (PowerShell)\n$env:OBSIDIAN_VAULT_PATH = \"C:\\Users\\YourName\\Obsidian-Vault\\00-Inbox\"\n\n# Windows (CMD)\nset OBSIDIAN_VAULT_PATH=C:\\Users\\YourName\\Obsidian-Vault\\00-Inbox\n\n# macOS/Linux\nexport OBSIDIAN_VAULT_PATH=~/Obsidian-Vault/00-Inbox"},{"language":"bash","snippet":"python3 scripts/web_to_all.py --url \"<url_or_path>\"\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima  # 仅保存 Obsidian"},{"language":"bash","snippet":"# 设置环境变量（v3.0 — IMA OpenAPI v1.1.7）\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# 可选：指定知识库名称（默认 \"FIM知识库\"）\n$env:IMA_KB_NAME = \"FIM知识库\""},{"language":"bash","snippet":"python3 scripts/web_to_md.py --url \"<url_or_path>\" --output <output.md>"},{"language":"python","snippet":"from scripts.web_to_all import save_to_obsidian\nfilepath = save_to_obsidian(markdown_content, title, url, keywords=\"数字人、口播、heygen\")  # v3.5.0 keywords"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: web-to-FIM\nlabel: 网页内容转 Markdown/飞书/IMA\nslug: web-to-fim\ndisplayName: web-to-FIM\nversion: 3.7.0\nsummary: 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian、飞书云盘、腾讯 IMA 知识库。\nlicense: MIT-0\ndescription: >\n  将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。\n  支持的信源：(1) X/Twitter 推文、长文 Article、Thread 线程（逐字转录）；(2) 微信公众号文章（带图片，IMA 服务端抓取保留排版）；\n  (3) 飞书 wiki 文档（v3.7.0 改用 lark-cli docs +fetch 抓取完整内容，WebFetch 截断严重已弃用）；\n  (4) 小红书笔记；(5) 微博；(6) YouTube 视频；\n  (7) 任意 HTML 网页（带图片，IMA 服务端抓取）；(8) 本地文件：PDF、Word、PPT、Excel、图片、音频等。\n  三处存放：Obsidian（本地 Markdown+frontmatter+tags）+ 飞书云盘（.md 原文件，用户身份上传立即可见）+ IMA 知识库（FIM知识库，AI 原生）。\n  v3.7.0 飞书 wiki 抓取改造：从 WebFetch（截断严重，200-1000 字符）改为 lark-cli docs +fetch（完整内容，3K-25K 字符），实测 33 篇文章中 19 篇被 WebFetch 截断。\n  v3.6.0 飞书存储改造：从应用身份创建在线 docx 改为 lark-cli drive +upload 上传 .md 原文件到用户云盘，用户在飞书\"我的空间 > 云盘\"立即可见。\n  IMA 智能路由：公众号/普通网页 → import_urls 保留图片；X/Twitter/飞书/GitHub → 纯文本笔记逐字转录。\n  飞书 wiki 原文链接优先转录：检查文章头部\"原文链接\"，有则优先抓取原文内容作为最终产物存三处，IMA 只存原文链接地址自动识别。\n  X 链接转录流程：飞书 wiki 中发现 X 原文链接时，用 x-tweet-fetcher 抓取完整长文（10K-15K 字符），失败时降级到飞书 wiki 内容。\n  批量模式支持断点恢复，Obsidian 写入失败自动 fallback。\n  工作流：自动识别 URL/文件类型 → 路由到最佳抓取工具 → 结构化 Markdown → 三处存放。\n  触发词：抓网页存飞书、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n  当用户明确要求将 URL 或本地文件转存为文档并存储到 Obsidian/飞书/IMA 时触发。\n  Do NOT use for 创建文档内容、编辑飞书文档正文、代码开发、非文档转存任务、普通文档格式转换（非三处存放意图）。\n---\n\n# Web-to-FIM | 网页内容转 Markdown/飞书/IMA\n\n## 🤖 AI 时代必备的信息库基础技能\n\n在 AI 时代，无论是使用 **OpenClaw**、**Hermes Agent**，还是实践 **Obsidian + LLM** 的信息管理方法论，**一键入库、人机共用**的 AI 信息库搭建都是必备的基础设施。\n\n**Web-to-FIM** 就是这样一个基础技能：它将任意网络内容一键转换为结构化 Markdown，并同步到：\n- 📝 **Obsidian Vault** - 本地个人知识库，带 frontmatter\n- 📁 **飞书云盘** - .md 原文件，用户身份上传立即可见（v3.6.0）\n- 🧠 **腾讯 IMA 知识库** - AI 原生知识库（FIM知识库）\n\n将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云盘、腾讯 IMA 知识库。\n\n## 支持的信源\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | **lark-cli docs +fetch**（v3.7.0 改造，完整内容） |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n> ⚠️ **v3.7.0 飞书 wiki 抓取方式变更**：\n> - **旧版本（v3.6.0 及更早）**：用 WebFetch 抓取飞书 wiki 内容，但实测会严重截断（200-1000 字符，完整文章应有 3K-25K 字符）。第十批 33 篇飞书 wiki 文章转录时，19 篇被 WebFetch 截断，导致飞书云盘上保存的内容大量丢失。\n> - **新版本（v3.7.0）**：改用 `lark-cli docs +fetch --doc <url> --doc-format markdown --scope full` 抓取完整内容。lark-cli 通过用户身份认证，可读取全文，实测 33 篇全部完整获取（800-24000 字符）。\n> - WebFetch 对飞书 wiki 的截断问题源于飞书 wiki 页面需 JS 渲染 + 登录认证，WebFetch 无法处理。lark-cli 通过官方 OpenAPI 直接获取结构化内容，无此问题。\n\n### 本地文件支持\n\n| 类型 | 扩展名 |\n|------|--------|\n| PDF | `.pdf` |\n| Word | `.docx` / `.doc` |\n| PowerPoint | `.pptx` / `.ppt` |\n| Excel | `.xlsx` / `.xls` |\n| 图片 | `.png` `.jpg` `.jpeg` `.gif` `.webp` |\n| 音频 | `.mp3` `.wav` `.m4a` `.flac` |\n| 数据 | `.csv` `.json` `.xml` |\n\n## 输出目的地\n\n| 目的地 | 依赖 | 说明 |\n|--------|------|"},{"path":"README.md","content":"[English](./README.en.md) | 中文\n\n# web-to-FIM\n\n> 将任意网页链接或本地文件一键转为结构化 Markdown，并三处存放到 Obsidian Vault、飞书云文档、腾讯 IMA 知识库。\n\n## 核心功能\n\n### 支持的信源（7 类 URL + 本地文件）\n\n| 信源 | URL 特征 | 抓取方式 |\n|------|---------|---------|\n| X/Twitter | `x.com` / `twitter.com` | x-tweet-fetcher（逐字转录） |\n| 微信公众号 | `mp.weixin.qq.com` | markitdown + 移动端 UA fallback |\n| 飞书 wiki | `*.feishu.cn/wiki/` | **lark-cli docs +fetch**（v3.7.0，完整内容） |\n| 小红书 | `xiaohongshu.com` / `xhslink.com` | markitdown |\n| 微博 | `weibo.com` | markitdown |\n| YouTube | `youtube.com` / `youtu.be` | markitdown |\n| 任意网页 | 其他 `http(s)://` 链接 | markitdown |\n\n本地文件支持：PDF、Word、PPT、Excel、图片、音频、CSV/JSON/XML 等。\n\n### 三处存放\n\n| 目的地 | 环境变量 | 说明 |\n|--------|---------|------|\n| Obsidian Vault | `OBSIDIAN_VAULT_PATH` | 本地 Markdown + frontmatter + tags（默认 `E:\\Obsidian-Vault\\00-Inbox`） |\n| 飞书云文档 | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | 云端团队协作 |\n| 腾讯 IMA | `IMA_OPENAPI_CLIENTID` + `IMA_OPENAPI_APIKEY` | AI 原生知识库（FIM知识库） |\n\n## 快速开始\n\n```bash\n# Install dependencies\npip install markitdown requests python-dotenv\n\n# Convert and save to all three destinations\npython3 scripts/web_to_all.py --url \"<url_or_path>\"\n\n# Convert with custom title\npython3 scripts/web_to_all.py --url \"<url>\" --title \"自定义标题\"\n\n# Save to Obsidian only\npython3 scripts/web_to_all.py --url \"<url>\" --no-feishu --no-ima\n```\n\n## 环境变量配置\n\n```bash\n# Obsidian Vault path (optional, has default)\n$env:OBSIDIAN_VAULT_PATH = \"E:\\Obsidian-Vault\\00-Inbox\"\n\n# Feishu credentials\n$env:FEISHU_APP_ID = \"your_app_id\"\n$env:FEISHU_APP_SECRET = \"your_app_secret\"\n\n# IMA credentials (v3.0 - OpenAPI v1.1.7)\n$env:IMA_OPENAPI_CLIENTID = \"your_client_id\"\n$env:IMA_OPENAPI_APIKEY = \"your_api_key\"\n\n# Optional: IMA knowledge base name (default: FIM知识库)\n$env:IMA_KB_NAME = \"FIM知识库\"\n```\n\n> 凭证必须通过环境变量配置，禁止硬编码。旧变量名 `IMA_CLIENT_ID` / `IMA_API_KEY` 仍兼容回退。\n\n## 使用示例\n\n```bash\n# X/Twitter tweet\npython3 scripts/web_to_all.py --url \"https://x.com/user/status/123\"\n\n# WeChat article\npython3 scripts/web_to_all.py --url \"https://mp.weixin.qq.com/s/xxxxx\"\n\n# Feishu wiki\npython3 scripts/web_to_all.py --url \"https://xxx.feishu.cn/wiki/xxxxx\"\n\n# Local PDF file\npython3 scripts/web_to_all.py --url \"C:\\docs\\report.pdf\"\n\n# Only convert to Markdown, no storage\npython3 scripts/web_to_md.py --url \"<url>\" --output output.md\n```\n\n## 触发词\n\n转文档、抓网页存飞书、网页转文档、web to feishu、url转文档、文件转飞书、存到ima、存到obsidian、web to fim、三处存放。\n\n当用户提供任意 URL 或本地文件并要求转存为文档时触发。\n\n## 验证连接\n\n```bash\n# Verify Feishu connection\npython scripts/feishu_client.py --action test\n\n# Verify IMA connection\npython scripts/ima_client.py --action test\n```\n\n## IMA 智能路由（v3.0）\n\n| source_url 类型 | IMA 存放方式 | 原因 |\n|----------------|------------|------|\n| 公众号 / 普通网页 | `import_urls`（服务端抓取） | 保留图片和排版 |\n| X/Twitter | 纯文本笔记（逐字转录） | 技能规则要求逐字转录 |\n| 飞书 wiki | 纯文本笔记（逐字转录） | 需登录认证，IMA 无法抓取 |\n\n## 版本历史\n\n- **v3.7.0**：飞书 wiki 抓取改造——从 WebFetch（截断严重，200-1000 字符）改为 `lark-cli docs +fetch`（完整内容，3K-25K 字符）；实测 33 篇文章全部完整获取\n- **v3.6.0**：飞书存储改造——从应用身份创建在线 docx 改为 `lark-cli drive +upload` 上传 .md 原文件到用户云盘，立即可见\n- **"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"web-to-fim\",\n  \"version\": \"3.7.0\",\n  \"publishedAt\": 1784387155458\n}"},{"path":"references/feishu-blocks.md","content":"# 飞书云文档 Block 类型映射表\n\n> 飞书 Docx API 的 block_type 枚举值。创建文档 blocks 时必须使用正确的 block_type，否则返回 400 Bad Request。\n\n## block_type 完整映射\n\n| block_type | 名称 | Markdown 对应 | block 字段名 |\n|-----------|------|-------------|------------|\n| 1 | Page（页面根块） | — | `page` |\n| 2 | Text（文本） | 普通段落 | `text` |\n| 3 | Heading1（一级标题） | `# ` | `heading1` |\n| 4 | Heading2（二级标题） | `## ` | `heading2` |\n| 5 | Heading3（三级标题） | `### ` | `heading3` |\n| 6 | Heading4（四级标题） | `#### ` | `heading4` |\n| 7 | Heading5（五级标题） | `##### ` | `heading5` |\n| 8 | Heading6（六级标题） | `###### ` | `heading6` |\n| 9 | Heading7（七级标题） | — | `heading7` |\n| 10 | Heading8（八级标题） | — | `heading8` |\n| 11 | Heading9（九级标题） | — | `heading9` |\n| 12 | Bullet（无序列表） | `- ` 或 `* ` | `bullet` |\n| 13 | Ordered（有序列表） | `1. ` | `ordered` |\n| 14 | Code（代码块） | ` ``` ` | `code` |\n| 15 | Quote（引用） | `> ` | `quote` |\n\n## 常见错误\n\n| 错误 | 正确值 | 说明 |\n|------|-------|------|\n| Code 用 block_type=2 | **block_type=14** | 2 是 Text，不是 Code |\n| Quote 用 block_type=11 | **block_type=15** | 11 是 Heading9，不是 Quote |\n\n## Block 结构示例\n\n### Text（block_type=2）\n\n```json\n{\n    \"block_type\": 2,\n    \"text\": {\n        \"elements\": [{\"text_run\": {\"content\": \"文本内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Heading1（block_type=3）\n\n```json\n{\n    \"block_type\": 3,\n    \"heading1\": {\n        \"elements\": [{\"text_run\": {\"content\": \"标题内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Bullet（block_type=12）\n\n```json\n{\n    \"block_type\": 12,\n    \"bullet\": {\n        \"elements\": [{\"text_run\": {\"content\": \"列表项\"}}],\n        \"style\": {}\n    }\n}\n```\n\n### Code（block_type=14）\n\n```json\n{\n    \"block_type\": 14,\n    \"code\": {\n        \"elements\": [{\"text_run\": {\"content\": \"code content\"}}],\n        \"style\": {\"language\": 1}\n    }\n}\n```\n\n### Quote（block_type=15）\n\n```json\n{\n    \"block_type\": 15,\n    \"quote\": {\n        \"elements\": [{\"text_run\": {\"content\": \"引用内容\"}}],\n        \"style\": {}\n    }\n}\n```\n\n## 关键约束\n\n### 1. elements 中不要加多余字段\n\n```json\n// ❌ 错误 — 多了 \"type\" 字段\n{\"text_run\": {\"type\": \"text_run\", \"content\": \"文本\"}}\n\n// ✅ 正确\n{\"text_run\": {\"content\": \"文本\"}}\n```\n\n### 2. 空行不要创建空文本块\n\n```python\n# ❌ 错误 — 空行创建空块会导致 400\nif not stripped:\n    blocks.append({\"block_type\": 2, \"text\": {\"elements\": [{\"text_run\": {\"content\": \"\"}}]}})\n\n# ✅ 正确 — 空行直接跳过\nif not stripped:\n    continue\n```\n\n### 3. 图片块需要预上传 token\n\n图片不能直接用 URL，必须先通过飞书上传 API 获取 `file_token`，再创建图片块。当前实现暂时跳过图片。\n\n### 4. 单次请求最多 50 个 blocks\n\n```\nPOST /docx/v1/documents/{document_id}/blocks/{document_id}/children\n```\n\n**payload 中 `children` 数组最多 50 个 block**。长文章必须分批插入：\n\n```python\nfor i in range(0, len(blocks), 50):\n    batch = blocks[i:i+50]\n    requests.post(url, headers=headers, json={\"children\": batch})\n```\n\n### 5. payload 中不要传 index\n\n```json\n// ❌ 错误 — index=-1 可能导致问题\n{\"children\": blocks, \"index\": -1}\n\n// ✅ 正确 — 不传 index，默认追加到末尾\n{\"children\": blocks}\n```\n\n## API 端点\n\n| 操作 | 方法 | URL |\n|------|------|-----|\n| 创建文档 | POST | `/docx/v1/documents` |\n| 插入 blocks | POST | `/docx/v1/documents/{document_id}/blocks/{document_id}/children` |\n| 获取文档信息 | GET | `/docx/v1/d"},{"path":"references/feishu-setup.md","content":"# 飞书云文档 API 配置指南\n\n## 获取凭证\n\n### 步骤 1: 创建飞书应用\n\n1. 访问 [飞书开放平台](https://open.feishu.cn/)\n2. 登录后进入「开发者后台」\n3. 点击「创建应用」，填写应用名称和描述\n4. 获取 **App ID** 和 **App Secret**\n\n### 步骤 2: 配置权限\n\n在应用后台开启以下权限：\n\n| 权限名称 | 权限说明 | 必要性 |\n|---------|---------|--------|\n| `docx.document:readonly` | 读取云文档 | 可选 |\n| `docx.document:write` | 创建/编辑云文档 | 必须 |\n| `drive:drive:folder` | 云文档文件夹操作 | 必须 |\n| `sheets:Spreadsheet:readonly` | 读取表格 | 可选 |\n\n### 步骤 3: 发布应用\n\n1. 在「版本管理与发布」中创建版本\n2. 选择「发布」并等待审核（或自建企业直接通过）\n\n## 本地配置\n\n### 设置环境变量\n\n```bash\n# Windows PowerShell\n$env:FEISHU_APP_ID=\"your_app_id\"\n$env:FEISHU_APP_SECRET=\"your_app_secret\"\n\n# Linux/macOS\nexport FEISHU_APP_ID=\"your_app_id\"\nexport FEISHU_APP_SECRET=\"your_app_secret\"\n```\n\n### 验证配置\n\n```python\nfrom feishu_client import FeishuClient\n\nclient = FeishuClient()\nif client.test_connection():\n    print(\"✅ 飞书连接成功\")\nelse:\n    print(\"❌ 飞书连接失败，请检查凭证\")\n```\n\n## 安全注意事项\n\n⚠️ **重要提示**：\n- **永远不要**将 `.env` 文件或包含真实凭证的文件提交到 Git\n- 已在 `.gitignore` 中添加 `.env` 规则\n- 生产环境建议使用密钥管理服务（如 AWS Secrets Manager）\n\n## 故障排查\n\n| 问题 | 解决方案 |\n|------|---------|\n| `invalid_app_id` | 检查 App ID 是否正确 |\n| `app_secret` 错误 | 在飞书开放平台重置 App Secret |\n| 权限不足 | 在应用后台添加所需权限并重新发布 |\n| 签名校验失败 | 确保使用 HTTPS，检查时间戳是否正确 |"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1311,"uniquenessScore":41,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T20:54:54.953Z","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-09T20:54:54.953Z","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-10T06:02:27.998Z","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"}]}}}