1 line
49 KiB
JSON
1 line
49 KiB
JSON
{"repo": "andreib180/wechat-skill-chat", "files": {"README.md": {"78f2eca85fba2469e081935592b7cf3b8cda0bb4": {"t": 1785746428.995866, "n": 6175, "h": "e1b5bc59e2aebed5", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/API-Anthropic_Compatible-orange\" alt=\"API\"> <img src=\"https://img.shields.io/badge/mode-Claude_Code-purple\" alt=\"CC\">\n</p>\n\n# WeChat Skill Chat\n\n**和你的 AI 人格在微信里聊天。**\n\n一个像素级复刻微信 PC 版界面的聊天应用。支持双模运行:API 直连 + Claude Code 管道。导入 skill persona,它就成了你的微信好友——像真人一样聊天、用黄脸表情、读文件、执行命令。\n\n---\n\n## 兼容性\n\n本项目使用 **Anthropic Messages API**(`/v1/messages`)。任何兼容该协议的 API 提供商均可使用,包括:\n\n| 提供商 | Base URL |\n|--------|----------|\n| **Anthropic** | 留空(SDK 自动使用 `https://api.anthropic.com`) |\n| **DeepSeek** | `https://api.deepseek.com/anthropic` |\n| 其他兼容网关 | 填入对应的 `/anthropic` 或 `/v1/messages` 端点 |\n\n只要你的 API 能响应 `POST /v1/messages` 并返回 Anthropic 格式的 `content` 数组,就能用。不兼容 OpenAI Chat Completions 格式(`/v1/chat/completions`)。\n\n---\n\n## 功能\n\n- **微信 PC 版 1:1 界面** — 55px 导航栏、250px 联系人列表、自适应聊天区,配色布局完全对齐\n- **Skill 即联系人** — 每个人格是独立的联系人,独立的头像、聊天记录、对话风格\n- **群聊** — 多 Skill 建群,路由 Agent 自动判断该谁回复,支持 @提及、SSE 流式响应\n- **导入即用** — 选择一个 skill 文件夹,自动验证、注册、生成头像、复制 persona\n- **文件附件** — 一次选多个文件发给 AI,支持 txt/docx/pdf,自动提取文本注入上下文\n- **聊天记录持久化** — 每个联系人 / 群聊一个 JSON,关掉浏览器再打开还在,按最新消息自动排序\n- **消息操作** — 右键菜单复制 / 删除消息,软删除标记持久化不丢数据\n- **多模型切换** — 设置里填 API Key + Base URL + Model,随时切 Anthropic ↔ DeepSeek\n- **头像拖拽上传** — 拖图片到设置或联系人编辑框的 URL 输入区,自动上传\n- **零硬编码** — 联系人是 `skills_config.json` 数据文件,群聊是 `groups_config.json`,增删改在 UI 完成,不动代码\n- **可移植** — `pip install flask anthropic && python3 server.py`,整个文件夹下载下来就能跑\n\n---\n\n## Skill 格式\n\n本项目导入的 skill 需要是一个**文件夹**,最低要求包含以下文件之一(优先级:`SKILL.md` > `persona.md`,两者同时存在时只读 `SKILL.md`):\n\n### 方式 A:单文件 `SKILL.md`(推荐)\n\n```\nmy-skill/\n├── SKILL.md # 完整的 persona + work 合并文件\n└── meta.json # 可选,提供 display_name、标签等元数据\n```\n\n这是 dot-skill 的标准输出格式。`SKILL.md` 即为完整的 system prompt,约 20-30KB,包含角色描述、说话风格、行为规则等。\n\n### 方式 B:分离文件 `persona.md` + `work.md`\n\n```\nmy-skill/\n├── persona.md # 人物性格(必选)\n├── work.md # 工作能力(可选)\n└── meta.json # 可选\n```\n\n导入时自动合并 `persona.md` 和 `work.md`。\n\n### meta.json(可选)\n\n```json\n{\n \"display_name\": \"肖易恒\",\n \"name\": \"colleague-xiaoyiheng\",\n \"tags\": [\"NPD\", \"自恋型人格障碍\", \"北京林业大学\"]\n}\n```\n\n- `display_name` → 联系人列表显示的名字(优先于文件夹名)\n- `name` → 内部 skill 名\n- 没有 `meta.json` 时使用文件夹名\n\n> **制作 skill**:用 `/dot-skill` 从聊天记录蒸馏高还原度人格,或用任何 LLM 写一段角色描述存为 `SKILL.md`。\n\n---\n\n## 快速开始\n\n### 1. 安装\n\n```bash\ngit clone https://github.com/AndreiB180/wechat-skill-chat.git\ncd wechat-skill-chat\npip install flask anthropic\n```\n\n### 2. 启动\n\n```bash\npython3 server.py\n```\n\n打开 `http://localhost:5888`。\n\n### 3. 配置 API\n\n左下角齿轮 → 设置:\n\n| 字段 | Anthropic | DeepSeek |\n|------|-----------|----------|\n| Base URL | 留空(SDK 默认) | `https://api.deepseek.com/anthropic` |\n| Model | `claude-sonnet-4-20250514` | `deepseek-v4-pro` |\n| API Key | `sk-ant-...` | `sk-...` |\n\nAPI Key 保存时自动 base64 混淆,不会明文泄露。\n\n### 4. 导入 Skill\n\n通讯录 → **+ 添加 Skill** → 输入文件夹路径 → 导入。新的联系人即刻出现在聊天列表。\n\n---\n\n## 架构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口,注册 5 个 Blueprint\n├── skills_config.json # 联系人注册表(JSON 数据,非代码)\n├── groups_config.json # 群聊配置(JSON 数据)\n├── settings.json # API 配置(gitignore)\n├── backend/\n│ ├── config.py # JSON 读写 + fcntl 文件锁\n│ ├── skills.py # Persona 三级查找加载\n│ ├── ai.py # Anthropic SDK 封装 + WeChat 格式注入\n│ ├── history.py # 聊天记录 CRUD(fcntl 锁,上限 300 条)\n│ └── routes/\n│ ├── chat_routes.py # /api/send, /api/history(单聊)\n│ ├── contacts_routes.py # /api/config, import/delete/update\n│ ├── group_routes.py # /api/groups, 群聊 SSE 发送, 路由 Agent\n│ ├── settings_routes.py # /api/settings\n│ └── static_routes.py # /avatars, /emoji, 头像上传\n├── templates/index.html # 微信 PC 版 1:1 结构\n├── static/\n│ ├── css/style.css # 完整样式\n│ ├── js/chat.js # 单聊前端(Emoji渲染/右键菜单/拖拽上传)\n│ ├── js/group-chat.js # 群聊前端(@提及/SSE流/群头像九宫格)\n│ ├── emoji/{face,gesture,...} # 109 个微信黄脸 PNG\n│ └── avatars/ # SVG / 上传头像\n├── skills/ # 用户导入的 skill 文件\n└── chat_history/ # 聊天记录 JSON(每联系人/群聊一个文件)\n```\n\n**数据流**:用户发消息 → Flask → 加载 SKILL.md → 拼入 system prompt(最高优先级格式指令)→ Anthropic Messages API → 按换行拆成多条 → 渲染聊天气泡。\n\n---\n\n## 细节\n\n### 消息发送\n\n用户消息先渲染绿气泡(乐观 UI),不等 API 返回。API 响应后追加白气泡。切换会话时 `chatId` 捕获机制保证消息不串到别人那里。中文输入法组合输入期间 Enter 不触发发送。\n\n### 并发安全\n\n`skills_config.json` 和 `chat_history/*.json` 使用 `fcntl.flock` 文件锁,多个请求同时操作不会损坏数据。每人的聊天记录上限 300 条(超出自动截断)。\n\n### 表情渲染\n\n109 个微信原生黄脸 PNG 按 `face/gesture/animal/blessing/other` 五类分目录。前端 `_emojiLookup` 映射中文名到目录,`[捂脸]` 在聊天气泡中渲染为 `<img src=\"/emoji/face/捂脸.png\">`。表情选择面板可直接点击插入。\n\n### 时间格式化\n\n| 距离 | 聊天气泡 | 联系人卡片 |\n|------|---------|-----------|\n| 今天 | `14:30` | `14:30` |\n| 昨天 | `昨天 14:30` | `昨天14:30` |\n| 2-6天前 | `星期三 14:30` | `星期三` |\n| 今年内 | `5/20 14:30` | `5/20` |\n| 更早 | `2025/12/3 14:30` | `2025/12/3` |\n\n### AI 格式约束\n\n每次 API 调用前,system prompt 最前面注入最高优先级格式指令,强制模型:\n- **禁止 Markdown 语法** — `# * ** ~~ \\` \\`\\`\\`` 等全部禁用,微信没人用这些\n- 禁止 `(顿了顿)` 等括号动作描写\n- 禁止旁白、叙述性文字、场景描述\n- 表情用 `[捂脸]` 格式\n- 消息简短、口语化、无剧本感\n\n### 消息操作\n\n右键聊天气泡弹出菜单,可复制消息文本(表情自动转为 `[捂脸]` 格式)或删除消息。删除采用软删除——聊天记录 JSON 中标记 `deleted: true`,渲染时过滤,服务器重启后依然有效。\n\n### 头像管理\n\n设置页和联系人编辑框中,将图片文件直接拖入 URL 输入框即可上传到 `static/avatars/`,自动生成 UUID 文件名。新导入的 Skill 自动生成首字母 SVG 头像,颜色从 8 种预设色中 hash 分配。\n\n### 输入框\n\n工具栏含表情/文件/语音通话/视频通话四个图标。语音/视频通话点击弹出 `\"你走火入魔了,还真想给 AI 打电话啊?\"`。输入框可拖拽顶部边框调整高度(52-120px)。有文字时发送按钮变微信绿。\n\n### 文件附件\n\n前端将文件转为 base64 传给后端。后端根据扩展名选择解析器:\n\n| 类型 | 支持 | 需要 |\n|------|------|------|\n| `.txt` `.md` `.py` 等 | ✓ 内置 | 无 |\n| `.docx` | ✓ | `pip install python-docx` |\n| `.pdf`(有文本层) | ✓ | `pip install PyPDF2` |\n\n提取文本截断到 100,000 字符注入 API 调用。聊天记录存 JSON 时再截断预览,避免历史文件过大。\n\n### 群聊\n\n联系人列表顶部 **+** 按钮可发起群聊,选多个 Skill 组成群。群聊通过 SSE(Server-Sent Events)实时流式返回消息。\n\n**路由 Agent**:系统先调用一个轻量 LLM 判断消息应该由哪个成员回复——如果消息中包含某成员的真名或显示名,该成员强制回复。接着最多进行 2-3 轮迭代,每轮选一个尚未发言的成员回复,有 90% 概率选还没说过话的人,避免同一人霸屏。\n\n**上下文隔离**:历史记录放进 system prompt 作为参考文本(而非 messages 数组),避免模型机械复制前人格式。每次调用前注入群成员名单 + 真名对应关系,强制模型用真名称呼他人。\n\n**@提及**:输入框打 `@` 自动弹出成员列表,支持 @所有人。检测到提及后强制对应成员回复。\n\n**群聊历史**存储在 `chat_history/grp_*.json`,支持右键删除消息(软删除,标记 `deleted: true`)。\n"}, "ff6841da8b260b86b074714a185b2b8c23ec54ee": {"t": 1785764106.1892605, "n": 6193, "h": "cf6f8030df532daf", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/API-Anthropic_Compatible-orange\" alt=\"API\">\n</p>\n# WeChat Skill Chat\n\n**和你的 AI 人格在微信里聊天。**\n\n一个像素级复刻微信 PC 版界面的聊天应用。导入一个 skill 文件夹,它就成了你的微信好友——像真人一样说话,用微信的黄脸表情,能读你发的文件。把任何 LLM persona 变成联系人。\n\n\n<p align=\"center\">\n <img src=\"screenshot.png\" width=\"720\" alt=\"WeChat Skill Chat screenshot\">\n</p>\n\n---\n\n## 兼容性\n\n本项目使用 **Anthropic Messages API**(`/v1/messages`)。任何兼容该协议的 API 提供商均可使用,包括:\n\n| 提供商 | Base URL |\n|--------|----------|\n| **Anthropic** | 留空(SDK 自动使用 `https://api.anthropic.com`) |\n| **DeepSeek** | `https://api.deepseek.com/anthropic` |\n| 其他兼容网关 | 填入对应的 `/anthropic` 或 `/v1/messages` 端点 |\n\n只要你的 API 能响应 `POST /v1/messages` 并返回 Anthropic 格式的 `content` 数组,就能用。不兼容 OpenAI Chat Completions 格式(`/v1/chat/completions`)。\n\n---\n\n## 功能\n\n- **微信 PC 版 1:1 界面** — 55px 导航栏、250px 联系人列表、自适应聊天区,配色布局完全对齐\n- **Skill 即联系人** — 每个人格是独立的联系人,独立的头像、聊天记录、对话风格\n- **群聊** — 多 Skill 建群,路由 Agent 自动判断该谁回复,支持 @提及、SSE 流式响应\n- **导入即用** — 选择一个 skill 文件夹,自动验证、注册、生成头像、复制 persona\n- **文件附件** — 一次选多个文件发给 AI,支持 txt/docx/pdf,自动提取文本注入上下文\n- **聊天记录持久化** — 每个联系人 / 群聊一个 JSON,关掉浏览器再打开还在,按最新消息自动排序\n- **消息操作** — 右键菜单复制 / 删除消息,软删除标记持久化不丢数据\n- **多模型切换** — 设置里填 API Key + Base URL + Model,随时切 Anthropic ↔ DeepSeek\n- **头像拖拽上传** — 拖图片到设置或联系人编辑框的 URL 输入区,自动上传\n- **零硬编码** — 联系人是 `skills_config.json` 数据文件,群聊是 `groups_config.json`,增删改在 UI 完成,不动代码\n- **可移植** — `pip install flask anthropic && python3 server.py`,整个文件夹下载下来就能跑\n\n---\n\n## Skill 格式\n\n本项目导入的 skill 需要是一个**文件夹**,最低要求包含以下文件之一(优先级:`SKILL.md` > `persona.md`,两者同时存在时只读 `SKILL.md`):\n\n### 方式 A:单文件 `SKILL.md`(推荐)\n\n```\nmy-skill/\n├── SKILL.md # 完整的 persona + work 合并文件\n└── meta.json # 可选,提供 display_name、标签等元数据\n```\n\n这是 dot-skill 的标准输出格式。`SKILL.md` 即为完整的 system prompt,约 20-30KB,包含角色描述、说话风格、行为规则等。\n\n### 方式 B:分离文件 `persona.md` + `work.md`\n\n```\nmy-skill/\n├── persona.md # 人物性格(必选)\n├── work.md # 工作能力(可选)\n└── meta.json # 可选\n```\n\n导入时自动合并 `persona.md` 和 `work.md`。\n\n### meta.json(可选)\n\n```json\n{\n \"display_name\": \"肖易恒\",\n \"name\": \"colleague-xiaoyiheng\",\n \"tags\": [\"NPD\", \"自恋型人格障碍\", \"北京林业大学\"]\n}\n```\n\n- `display_name` → 联系人列表显示的名字(优先于文件夹名)\n- `name` → 内部 skill 名\n- 没有 `meta.json` 时使用文件夹名\n\n> **制作 skill**:用 `/dot-skill` 从聊天记录蒸馏高还原度人格,或用任何 LLM 写一段角色描述存为 `SKILL.md`。\n\n---\n\n## 快速开始\n\n### 1. 安装\n\n```bash\ngit clone https://github.com/AndreiB180/wechat-skill-chat.git\ncd wechat-skill-chat\npip install flask anthropic\n```\n\n### 2. 启动\n\n```bash\npython3 server.py\n```\n\n打开 `http://localhost:5888`。\n\n### 3. 配置 API\n\n左下角齿轮 → 设置:\n\n| 字段 | Anthropic | DeepSeek |\n|------|-----------|----------|\n| Base URL | 留空(SDK 默认) | `https://api.deepseek.com/anthropic` |\n| Model | `claude-sonnet-4-20250514` | `deepseek-v4-pro` |\n| API Key | `sk-ant-...` | `sk-...` |\n\nAPI Key 保存时自动 base64 混淆,不会明文泄露。\n\n### 4. 导入 Skill\n\n通讯录 → **+ 添加 Skill** → 输入文件夹路径 → 导入。新的联系人即刻出现在聊天列表。\n\n---\n\n## 架构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口,注册 5 个 Blueprint\n├── skills_config.json # 联系人注册表(JSON 数据,非代码)\n├── groups_config.json # 群聊配置(JSON 数据)\n├── settings.json # API 配置(gitignore)\n├── backend/\n│ ├── config.py # JSON 读写 + fcntl 文件锁\n│ ├── skills.py # Persona 三级查找加载\n│ ├── ai.py # Anthropic SDK 封装 + WeChat 格式注入\n│ ├── history.py # 聊天记录 CRUD(fcntl 锁,上限 300 条)\n│ └── routes/\n│ ├── chat_routes.py # /api/send, /api/history(单聊)\n│ ├── contacts_routes.py # /api/config, import/delete/update\n│ ├── group_routes.py # /api/groups, 群聊 SSE 发送, 路由 Agent\n│ ├── settings_routes.py # /api/settings\n│ └── static_routes.py # /avatars, /emoji, 头像上传\n├── templates/index.html # 微信 PC 版 1:1 结构\n├── static/\n│ ├── css/style.css # 完整样式\n│ ├── js/chat.js # 单聊前端(Emoji渲染/右键菜单/拖拽上传)\n│ ├── js/group-chat.js # 群聊前端(@提及/SSE流/群头像九宫格)\n│ ├── emoji/{face,gesture,...} # 109 个微信黄脸 PNG\n│ └── avatars/ # SVG / 上传头像\n├── skills/ # 用户导入的 skill 文件\n└── chat_history/ # 聊天记录 JSON(每联系人/群聊一个文件)\n```\n\n**数据流**:用户发消息 → Flask → 加载 SKILL.md → 拼入 system prompt(最高优先级格式指令)→ Anthropic Messages API → 按换行拆成多条 → 渲染聊天气泡。\n\n---\n\n## 细节\n\n### 消息发送\n\n用户消息先渲染绿气泡(乐观 UI),不等 API 返回。API 响应后追加白气泡。切换会话时 `chatId` 捕获机制保证消息不串到别人那里。中文输入法组合输入期间 Enter 不触发发送。\n\n### 并发安全\n\n`skills_config.json` 和 `chat_history/*.json` 使用 `fcntl.flock` 文件锁,多个请求同时操作不会损坏数据。每人的聊天记录上限 300 条(超出自动截断)。\n\n### 表情渲染\n\n109 个微信原生黄脸 PNG 按 `face/gesture/animal/blessing/other` 五类分目录。前端 `_emojiLookup` 映射中文名到目录,`[捂脸]` 在聊天气泡中渲染为 `<img src=\"/emoji/face/捂脸.png\">`。表情选择面板可直接点击插入。\n\n### 时间格式化\n\n| 距离 | 聊天气泡 | 联系人卡片 |\n|------|---------|-----------|\n| 今天 | `14:30` | `14:30` |\n| 昨天 | `昨天 14:30` | `昨天14:30` |\n| 2-6天前 | `星期三 14:30` | `星期三` |\n| 今年内 | `5/20 14:30` | `5/20` |\n| 更早 | `2025/12/3 14:30` | `2025/12/3` |\n\n### AI 格式约束\n\n每次 API 调用前,system prompt 最前面注入最高优先级格式指令,强制模型:\n- **禁止 Markdown 语法** — `# * ** ~~ \\` \\`\\`\\`` 等全部禁用,微信没人用这些\n- 禁止 `(顿了顿)` 等括号动作描写\n- 禁止旁白、叙述性文字、场景描述\n- 表情用 `[捂脸]` 格式\n- 消息简短、口语化、无剧本感\n\n### 消息操作\n\n右键聊天气泡弹出菜单,可复制消息文本(表情自动转为 `[捂脸]` 格式)或删除消息。删除采用软删除——聊天记录 JSON 中标记 `deleted: true`,渲染时过滤,服务器重启后依然有效。\n\n### 头像管理\n\n设置页和联系人编辑框中,将图片文件直接拖入 URL 输入框即可上传到 `static/avatars/`,自动生成 UUID 文件名。新导入的 Skill 自动生成首字母 SVG 头像,颜色从 8 种预设色中 hash 分配。\n\n### 输入框\n\n工具栏含表情/文件/语音通话/视频通话四个图标。语音/视频通话点击弹出 `\"你走火入魔了,还真想给 AI 打电话啊?\"`。输入框可拖拽顶部边框调整高度(52-120px)。有文字时发送按钮变微信绿。\n\n### 文件附件\n\n前端将文件转为 base64 传给后端。后端根据扩展名选择解析器:\n\n| 类型 | 支持 | 需要 |\n|------|------|------|\n| `.txt` `.md` `.py` 等 | ✓ 内置 | 无 |\n| `.docx` | ✓ | `pip install python-docx` |\n| `.pdf`(有文本层) | ✓ | `pip install PyPDF2` |\n\n提取文本截断到 100,000 字符注入 API 调用。聊天记录存 JSON 时再截断预览,避免历史文件过大。\n\n### 群聊\n\n联系人列表顶部 **+** 按钮可发起群聊,选多个 Skill 组成群。群聊通过 SSE(Server-Sent Events)实时流式返回消息。\n\n**路由 Agent**:系统先调用一个轻量 LLM 判断消息应该由哪个成员回复——如果消息中包含某成员的真名或显示名,该成员强制回复。接着最多进行 2-3 轮迭代,每轮选一个尚未发言的成员回复,有 90% 概率选还没说过话的人,避免同一人霸屏。\n\n**上下文隔离**:历史记录放进 system prompt 作为参考文本(而非 messages 数组),避免模型机械复制前人格式。每次调用前注入群成员名单 + 真名对应关系,强制模型用真名称呼他人。\n\n**@提及**:输入框打 `@` 自动弹出成员列表,支持 @所有人。检测到提及后强制对应成员回复。\n\n**群聊历史**存储在 `chat_history/grp_*.json`,支持右键删除消息(软删除,标记 `deleted: true`)。\n"}, "7012cdc6ec354c0defe8b91212ee478f82c7a771": {"t": 1785764108.4703562, "n": 2928, "h": "9a0321b2dfcfa40d", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/mode-API_|_Claude_Code-orange\" alt=\"Dual Mode\">\n</p>\n\n# WeChat Skill Chat\n\n**像素级复刻微信 PC 版界面的 AI 聊天应用。支持双模运行:API 直连 + Claude Code 管道。**\n\n导入 skill persona,它就成了你的微信好友——像真人一样聊天、用黄脸表情、读文件、执行命令。私聊 + 群聊,所有对话持久化。\n\n---\n\n## 双模运行\n\n| | API 模式 | Claude Code 模式 |\n|---|---|---|\n| **原理** | 直接调用 Anthropic 兼容 API | 启动本地 `ccb` 子进程,stream-json 管道通信 |\n| **能力** | 纯文本对话 + 文件内容注入 | 完整 CC 能力:读写文件、执行命令、搜索等 |\n| **权限** | 无需 | auto / bypassPermissions,设置页动态切换 |\n| **启动** | 填 API Key 即可 | 需本地安装 `ccb`(或 `claude`) |\n| **适用** | 轻量聊天 | 需要 AI 帮你干活的场景 |\n\n- **CC 模式支持动态权限切换**:auto 和 bypassPermissions 之间随时切,不丢对话上下文\n- **原生文件选择器**:CC 模式下点 📄 按钮 → macOS 原生对话框 → 文件/文件夹绝对路径直接填入输入框\n- **400 自动恢复**:CC 内部工具拒绝产生的孤儿 tool_use 导致的 API 400 错误,后台自动重试,前端无感知\n- **媒体附件**(API 模式):多文件上传,自动提取 txt/docx/pdf 文本注入上下文\n\n---\n\n## 功能\n\n- **双模切换** — 设置页一键切换 API / CC 模式,CC 模式下检测 CLI 可用性\n- **动态权限** — auto(分类器自动决定)和 bypassPermissions(全部放行),设置页实时切换\n- **私聊 + 群聊** — 多人群聊,支持 @提及,路由 agent 决定谁回复\n- **微信界面** — 55px 导航栏、250px 联系人列表、聊天列表按最新消息排序\n- **Skill 即联系人** — 每个 persona 是独立联系人,独立头像、聊天记录\n- **对话持久化** — JSON 文件存储,关浏览器再开还在\n- **文件附件** — API 模式下读文件内容注入上下文;CC 模式下选绝对路径传给 CC\n- **右键菜单** — 复制消息、删除消息\n- **表情包** — 微信黄脸表情 PNG,支持 `[捂脸]` `[旺柴]` 等代码\n\n---\n\n## 快速开始\n\n```bash\npip install flask anthropic python-docx PyPDF2\npython3 server.py\n# 浏览器自动打开 http://localhost:5888\n```\n\n### API 模式\n1. 设置页填入 API Key、Base URL、Model\n2. 导入一个 Skill 文件夹(或直接在 `skills/` 下放 `.md` 文件,在 `skills_config.json` 注册)\n3. 开始聊天\n\n### Claude Code 模式\n1. 确保 `ccb`(或 `claude`)在 PATH 中\n2. 设置页切换到 Claude Code 模式,点「检测」确认可用\n3. 权限模式选 `auto`(推荐)或 `bypassPermissions`\n4. 开始聊天 — CC 能读文件、跑命令、写代码\n\n---\n\n## Skill 格式\n\n每个 skill 是一个 `.md` 文件放在 `skills/` 目录,内容为 system prompt(角色描述、说话风格、行为规则)。\n\n在 `skills_config.json` 中注册:\n\n```json\n{\n \"skills\": [\n {\n \"id\": \"my_bot\",\n \"name\": \"小明\",\n \"skill_name\": \"xiaoming\",\n \"avatar\": \"avatars/xiaoming.jpg\",\n \"real_name\": \"小明\"\n }\n ]\n}\n```\n\n`skill_name` 对应 `skills/` 下的文件名(不含 `.md`)。\n\n---\n\n## 项目结构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口\n├── settings.json # API Key、模式等配置\n├── skills_config.json # 联系人注册表\n├── groups_config.json # 群聊配置\n├── backend/\n│ ├── ai.py # API 模式调用逻辑\n│ ├── claude_cli.py # CC CLI 检测\n│ ├── claude_session.py # CC 持久化子进程管理(stream-json I/O)\n│ ├── config.py # 设置读写\n│ ├── history.py # 聊天记录持久化\n│ └── routes/ # Flask 路由\n├── skills/ # Skill persona 文件(.md)\n├── static/\n│ ├── css/style.css\n│ ├── js/chat.js # 私聊前端\n│ ├── js/group-chat.js # 群聊前端\n│ ├── avatars/ # 头像图片\n│ └── emoji/ # 微信表情 PNG\n└── templates/index.html\n```\n\n---\n\n## 兼容 API\n\n任何兼容 Anthropic Messages API(`/v1/messages`)的提供商均可使用:Anthropic、DeepSeek、及其他兼容网关。\n"}, "98dae3850412fbfec4101153202e98e03e9d5093": {"t": 1785764109.914901, "n": 5107, "h": "076ae03bb9892ba2", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/API-Anthropic_Compatible-orange\" alt=\"API\">\n</p>\n\n# WeChat Skill Chat\n\n**和你的 AI 人格在微信里聊天。**\n\n一个像素级复刻微信 PC 版界面的聊天应用。导入一个 skill 文件夹,它就成了你的微信好友——像真人一样说话,用微信的黄脸表情,能读你发的文件。把任何 LLM persona 变成联系人。\n\n\n<p align=\"center\">\n <img src=\"screenshot.png\" width=\"720\" alt=\"WeChat Skill Chat screenshot\">\n</p>\n\n---\n\n## 兼容性\n\n本项目使用 **Anthropic Messages API**(`/v1/messages`)。任何兼容该协议的 API 提供商均可使用,包括:\n\n| 提供商 | Base URL |\n|--------|----------|\n| **Anthropic** | 留空(SDK 自动使用 `https://api.anthropic.com`) |\n| **DeepSeek** | `https://api.deepseek.com/anthropic` |\n| 其他兼容网关 | 填入对应的 `/anthropic` 或 `/v1/messages` 端点 |\n\n只要你的 API 能响应 `POST /v1/messages` 并返回 Anthropic 格式的 `content` 数组,就能用。不兼容 OpenAI Chat Completions 格式(`/v1/chat/completions`)。\n\n---\n\n## 功能\n\n- **微信 PC 版 1:1 界面** — 55px 导航栏、250px 联系人列表、自适应聊天区,配色布局完全对齐\n- **Skill 即联系人** — 每个人格是独立的联系人,独立的头像、聊天记录、对话风格\n- **导入即用** — 选择一个 skill 文件夹,自动验证、注册、生成头像、复制 persona\n- **文件附件** — 一次选多个文件发给 AI,支持 txt/docx/pdf,自动提取文本注入上下文\n- **聊天记录持久化** — 每个联系人一个 JSON,关掉浏览器再打开还在,按最新消息自动排序\n- **多模型切换** — 设置里填 API Key + Base URL + Model,随时切 Anthropic ↔ DeepSeek\n- **零硬编码** — 联系人是 `skills_config.json` 数据文件,增删改在 UI 完成,不动代码\n- **可移植** — `pip install flask anthropic && python3 server.py`,整个文件夹下载下来就能跑\n\n---\n\n## Skill 格式\n\n本项目导入的 skill 需要是一个**文件夹**,最低要求包含以下文件之一(优先级:`SKILL.md` > `persona.md`,两者同时存在时只读 `SKILL.md`):\n\n### 方式 A:单文件 `SKILL.md`(推荐)\n\n```\nmy-skill/\n├── SKILL.md # 完整的 persona + work 合并文件\n└── meta.json # 可选,提供 display_name、标签等元数据\n```\n\n这是 dot-skill 的标准输出格式。`SKILL.md` 即为完整的 system prompt,约 20-30KB,包含角色描述、说话风格、行为规则等。\n\n### 方式 B:分离文件 `persona.md` + `work.md`\n\n```\nmy-skill/\n├── persona.md # 人物性格(必选)\n├── work.md # 工作能力(可选)\n└── meta.json # 可选\n```\n\n导入时自动合并 `persona.md` 和 `work.md`。\n\n### meta.json(可选)\n\n```json\n{\n \"display_name\": \"肖易恒\",\n \"name\": \"colleague-xiaoyiheng\",\n \"tags\": [\"NPD\", \"自恋型人格障碍\", \"北京林业大学\"]\n}\n```\n\n- `display_name` → 联系人列表显示的名字(优先于文件夹名)\n- `name` → 内部 skill 名\n- 没有 `meta.json` 时使用文件夹名\n\n> **制作 skill**:用 `/dot-skill` 从聊天记录蒸馏高还原度人格,或用任何 LLM 写一段角色描述存为 `SKILL.md`。\n\n---\n\n## 快速开始\n\n### 1. 安装\n\n```bash\ngit clone https://github.com/AndreiB180/wechat-skill-chat.git\ncd wechat-skill-chat\npip install flask anthropic\n```\n\n### 2. 启动\n\n```bash\npython3 server.py\n```\n\n打开 `http://localhost:5888`。\n\n### 3. 配置 API\n\n左下角齿轮 → 设置:\n\n| 字段 | Anthropic | DeepSeek |\n|------|-----------|----------|\n| Base URL | 留空(SDK 默认) | `https://api.deepseek.com/anthropic` |\n| Model | `claude-sonnet-4-20250514` | `deepseek-v4-pro` |\n| API Key | `sk-ant-...` | `sk-...` |\n\nAPI Key 保存时自动 base64 混淆,不会明文泄露。\n\n### 4. 导入 Skill\n\n通讯录 → **+ 添加 Skill** → 输入文件夹路径 → 导入。新的联系人即刻出现在聊天列表。\n\n---\n\n## 架构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口,注册 4 个 Blueprint\n├── skills_config.json # 联系人注册表(JSON 数据,非代码)\n├── settings.json # API 配置(gitignore)\n├── backend/\n│ ├── config.py # JSON 读写 + fcntl 文件锁\n│ ├── skills.py # Persona 三级查找加载\n│ ├── ai.py # Anthropic SDK 封装 + WeChat 格式注入\n│ ├── history.py # 聊天记录 CRUD(fcntl 锁,200 条/人上限)\n│ └── routes/\n│ ├── chat_routes.py # /api/send, /api/history\n│ ├── contacts_routes.py # /api/config, import/delete/update\n│ ├── settings_routes.py # /api/settings\n│ └── static_routes.py # /avatars, /emoji\n├── templates/index.html # 微信 PC 版 1:1 结构\n├── static/\n│ ├── css/style.css # 完整样式\n│ ├── js/chat.js # 前端逻辑(Session隔离/乐观UI/Emoji渲染)\n│ ├── emoji/{face,gesture,...} # 109 个微信黄脸 PNG\n│ └── avatars/ # SVG 头像\n└── skills/ # 用户导入的 skill 文件\n```\n\n**数据流**:用户发消息 → Flask → 加载 SKILL.md → 拼入 system prompt(最高优先级格式指令)→ Anthropic Messages API → 按换行拆成多条 → 渲染聊天气泡。\n\n---\n\n## 细节\n\n### 消息发送\n\n用户消息先渲染绿气泡(乐观 UI),不等 API 返回。API 响应后追加白气泡。切换会话时 `chatId` 捕获机制保证消息不串到别人那里。中文输入法组合输入期间 Enter 不触发发送。\n\n### 并发安全\n\n`skills_config.json` 和 `chat_history/*.json` 使用 `fcntl.flock` 文件锁,多个请求同时操作不会损坏数据。每人的聊天记录上限 200 条。\n\n### 表情渲染\n\n109 个微信原生黄脸 PNG 按 `face/gesture/animal/blessing/other` 五类分目录。前端 `_emojiLookup` 映射中文名到目录,`[捂脸]` 在聊天气泡中渲染为 `<img src=\"/emoji/face/捂脸.png\">`。表情选择面板可直接点击插入。\n\n### 时间格式化\n\n| 距离 | 聊天气泡 | 联系人卡片 |\n|------|---------|-----------|\n| 今天 | `14:30` | `14:30` |\n| 昨天 | `昨天 14:30` | `昨天14:30` |\n| 2-6天前 | `星期三 14:30` | `星期三` |\n| 今年内 | `5/20 14:30` | `5/20` |\n| 更早 | `2025/12/3 14:30` | `2025/12/3` |\n\n### AI 格式约束\n\n每次 API 调用前,system prompt 最前面注入最高优先级格式指令,强制模型:\n- **禁止 Markdown 语法** — `# * ** ~~ \\` \\`\\`\\`` 等全部禁用,微信没人用这些\n- 禁止 `(顿了顿)` 等括号动作描写\n- 禁止旁白、叙述性文字、场景描述\n- 表情用 `[捂脸]` 格式\n- 消息简短、口语化、无剧本感\n\n### 输入框\n\n工具栏含表情/文件/语音通话/视频通话四个图标。语音/视频通话点击弹出 `\"你走火入魔了,还真想给 AI 打电话啊?\"`。输入框可拖拽顶部边框调整高度(52-120px)。有文字时发送按钮变微信绿。\n\n### 文件附件\n\n前端将文件转为 base64 传给后端。后端根据扩展名选择解析器:\n\n| 类型 | 支持 | 需要 |\n|------|------|------|\n| `.txt` `.md` `.py` 等 | ✓ 内置 | 无 |\n| `.docx` | ✓ | `pip install python-docx` |\n| `.pdf`(有文本层) | ✓ | `pip install PyPDF2` |\n\n提取文本截断到 100,000 字符注入 API 调用。聊天记录存 JSON 时再截断预览,避免历史文件过大。\n"}, "5f0c4ef8a4ed7bee39d9f1f34e713f811680adf8": {"t": 1785764112.8950737, "n": 5106, "h": "86d1dd5e7608d197", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/API-Anthropic_Compatible-orange\" alt=\"API\">\n</p>\n# WeChat Skill Chat\n\n**和你的 AI 人格在微信里聊天。**\n\n一个像素级复刻微信 PC 版界面的聊天应用。导入一个 skill 文件夹,它就成了你的微信好友——像真人一样说话,用微信的黄脸表情,能读你发的文件。把任何 LLM persona 变成联系人。\n\n\n<p align=\"center\">\n <img src=\"screenshot.png\" width=\"720\" alt=\"WeChat Skill Chat screenshot\">\n</p>\n\n---\n\n## 兼容性\n\n本项目使用 **Anthropic Messages API**(`/v1/messages`)。任何兼容该协议的 API 提供商均可使用,包括:\n\n| 提供商 | Base URL |\n|--------|----------|\n| **Anthropic** | 留空(SDK 自动使用 `https://api.anthropic.com`) |\n| **DeepSeek** | `https://api.deepseek.com/anthropic` |\n| 其他兼容网关 | 填入对应的 `/anthropic` 或 `/v1/messages` 端点 |\n\n只要你的 API 能响应 `POST /v1/messages` 并返回 Anthropic 格式的 `content` 数组,就能用。不兼容 OpenAI Chat Completions 格式(`/v1/chat/completions`)。\n\n---\n\n## 功能\n\n- **微信 PC 版 1:1 界面** — 55px 导航栏、250px 联系人列表、自适应聊天区,配色布局完全对齐\n- **Skill 即联系人** — 每个人格是独立的联系人,独立的头像、聊天记录、对话风格\n- **导入即用** — 选择一个 skill 文件夹,自动验证、注册、生成头像、复制 persona\n- **文件附件** — 一次选多个文件发给 AI,支持 txt/docx/pdf,自动提取文本注入上下文\n- **聊天记录持久化** — 每个联系人一个 JSON,关掉浏览器再打开还在,按最新消息自动排序\n- **多模型切换** — 设置里填 API Key + Base URL + Model,随时切 Anthropic ↔ DeepSeek\n- **零硬编码** — 联系人是 `skills_config.json` 数据文件,增删改在 UI 完成,不动代码\n- **可移植** — `pip install flask anthropic && python3 server.py`,整个文件夹下载下来就能跑\n\n---\n\n## Skill 格式\n\n本项目导入的 skill 需要是一个**文件夹**,最低要求包含以下文件之一(优先级:`SKILL.md` > `persona.md`,两者同时存在时只读 `SKILL.md`):\n\n### 方式 A:单文件 `SKILL.md`(推荐)\n\n```\nmy-skill/\n├── SKILL.md # 完整的 persona + work 合并文件\n└── meta.json # 可选,提供 display_name、标签等元数据\n```\n\n这是 dot-skill 的标准输出格式。`SKILL.md` 即为完整的 system prompt,约 20-30KB,包含角色描述、说话风格、行为规则等。\n\n### 方式 B:分离文件 `persona.md` + `work.md`\n\n```\nmy-skill/\n├── persona.md # 人物性格(必选)\n├── work.md # 工作能力(可选)\n└── meta.json # 可选\n```\n\n导入时自动合并 `persona.md` 和 `work.md`。\n\n### meta.json(可选)\n\n```json\n{\n \"display_name\": \"肖易恒\",\n \"name\": \"colleague-xiaoyiheng\",\n \"tags\": [\"NPD\", \"自恋型人格障碍\", \"北京林业大学\"]\n}\n```\n\n- `display_name` → 联系人列表显示的名字(优先于文件夹名)\n- `name` → 内部 skill 名\n- 没有 `meta.json` 时使用文件夹名\n\n> **制作 skill**:用 `/dot-skill` 从聊天记录蒸馏高还原度人格,或用任何 LLM 写一段角色描述存为 `SKILL.md`。\n\n---\n\n## 快速开始\n\n### 1. 安装\n\n```bash\ngit clone https://github.com/AndreiB180/wechat-skill-chat.git\ncd wechat-skill-chat\npip install flask anthropic\n```\n\n### 2. 启动\n\n```bash\npython3 server.py\n```\n\n打开 `http://localhost:5888`。\n\n### 3. 配置 API\n\n左下角齿轮 → 设置:\n\n| 字段 | Anthropic | DeepSeek |\n|------|-----------|----------|\n| Base URL | 留空(SDK 默认) | `https://api.deepseek.com/anthropic` |\n| Model | `claude-sonnet-4-20250514` | `deepseek-v4-pro` |\n| API Key | `sk-ant-...` | `sk-...` |\n\nAPI Key 保存时自动 base64 混淆,不会明文泄露。\n\n### 4. 导入 Skill\n\n通讯录 → **+ 添加 Skill** → 输入文件夹路径 → 导入。新的联系人即刻出现在聊天列表。\n\n---\n\n## 架构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口,注册 4 个 Blueprint\n├── skills_config.json # 联系人注册表(JSON 数据,非代码)\n├── settings.json # API 配置(gitignore)\n├── backend/\n│ ├── config.py # JSON 读写 + fcntl 文件锁\n│ ├── skills.py # Persona 三级查找加载\n│ ├── ai.py # Anthropic SDK 封装 + WeChat 格式注入\n│ ├── history.py # 聊天记录 CRUD(fcntl 锁,200 条/人上限)\n│ └── routes/\n│ ├── chat_routes.py # /api/send, /api/history\n│ ├── contacts_routes.py # /api/config, import/delete/update\n│ ├── settings_routes.py # /api/settings\n│ └── static_routes.py # /avatars, /emoji\n├── templates/index.html # 微信 PC 版 1:1 结构\n├── static/\n│ ├── css/style.css # 完整样式\n│ ├── js/chat.js # 前端逻辑(Session隔离/乐观UI/Emoji渲染)\n│ ├── emoji/{face,gesture,...} # 109 个微信黄脸 PNG\n│ └── avatars/ # SVG 头像\n└── skills/ # 用户导入的 skill 文件\n```\n\n**数据流**:用户发消息 → Flask → 加载 SKILL.md → 拼入 system prompt(最高优先级格式指令)→ Anthropic Messages API → 按换行拆成多条 → 渲染聊天气泡。\n\n---\n\n## 细节\n\n### 消息发送\n\n用户消息先渲染绿气泡(乐观 UI),不等 API 返回。API 响应后追加白气泡。切换会话时 `chatId` 捕获机制保证消息不串到别人那里。中文输入法组合输入期间 Enter 不触发发送。\n\n### 并发安全\n\n`skills_config.json` 和 `chat_history/*.json` 使用 `fcntl.flock` 文件锁,多个请求同时操作不会损坏数据。每人的聊天记录上限 200 条。\n\n### 表情渲染\n\n109 个微信原生黄脸 PNG 按 `face/gesture/animal/blessing/other` 五类分目录。前端 `_emojiLookup` 映射中文名到目录,`[捂脸]` 在聊天气泡中渲染为 `<img src=\"/emoji/face/捂脸.png\">`。表情选择面板可直接点击插入。\n\n### 时间格式化\n\n| 距离 | 聊天气泡 | 联系人卡片 |\n|------|---------|-----------|\n| 今天 | `14:30` | `14:30` |\n| 昨天 | `昨天 14:30` | `昨天14:30` |\n| 2-6天前 | `星期三 14:30` | `星期三` |\n| 今年内 | `5/20 14:30` | `5/20` |\n| 更早 | `2025/12/3 14:30` | `2025/12/3` |\n\n### AI 格式约束\n\n每次 API 调用前,system prompt 最前面注入最高优先级格式指令,强制模型:\n- **禁止 Markdown 语法** — `# * ** ~~ \\` \\`\\`\\`` 等全部禁用,微信没人用这些\n- 禁止 `(顿了顿)` 等括号动作描写\n- 禁止旁白、叙述性文字、场景描述\n- 表情用 `[捂脸]` 格式\n- 消息简短、口语化、无剧本感\n\n### 输入框\n\n工具栏含表情/文件/语音通话/视频通话四个图标。语音/视频通话点击弹出 `\"你走火入魔了,还真想给 AI 打电话啊?\"`。输入框可拖拽顶部边框调整高度(52-120px)。有文字时发送按钮变微信绿。\n\n### 文件附件\n\n前端将文件转为 base64 传给后端。后端根据扩展名选择解析器:\n\n| 类型 | 支持 | 需要 |\n|------|------|------|\n| `.txt` `.md` `.py` 等 | ✓ 内置 | 无 |\n| `.docx` | ✓ | `pip install python-docx` |\n| `.pdf`(有文本层) | ✓ | `pip install PyPDF2` |\n\n提取文本截断到 100,000 字符注入 API 调用。聊天记录存 JSON 时再截断预览,避免历史文件过大。\n"}, "ab57fbff6f0456b8ef1123982f9c56aee5bef803": {"t": 1785764114.0754783, "n": 5107, "h": "bb8461f14aedbb90", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/python-3.10+-blue\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\">\n <img src=\"https://img.shields.io/badge/API-Anthropic_Compatible-orange\" alt=\"API\">\n</p>\n# WeChat Skill Chat\n\n**和你的 AI 人格在微信里聊天。**\n\n一个像素级复刻微信 PC 版界面的聊天应用。导入一个 skill 文件夹,它就成了你的微信好友——像真人一样说话,用微信的黄脸表情,能读你发的文件。把任何 LLM persona 变成联系人。\n\n\n<p align=\"center\">\n <img src=\"screenshot.png\" width=\"720\" alt=\"WeChat Skill Chat screenshot\">\n</p>\n---\n\n## 兼容性\n\n本项目使用 **Anthropic Messages API**(`/v1/messages`)。任何兼容该协议的 API 提供商均可使用,包括:\n\n| 提供商 | Base URL |\n|--------|----------|\n| **Anthropic** | 留空(SDK 自动使用 `https://api.anthropic.com`) |\n| **DeepSeek** | `https://api.deepseek.com/anthropic` |\n| 其他兼容网关 | 填入对应的 `/anthropic` 或 `/v1/messages` 端点 |\n\n只要你的 API 能响应 `POST /v1/messages` 并返回 Anthropic 格式的 `content` 数组,就能用。不兼容 OpenAI Chat Completions 格式(`/v1/chat/completions`)。\n\n---\n\n## 功能\n\n- **微信 PC 版 1:1 界面** — 55px 导航栏、250px 联系人列表、自适应聊天区,配色布局完全对齐\n- **Skill 即联系人** — 每个人格是独立的联系人,独立的头像、聊天记录、对话风格\n- **导入即用** — 选择一个 skill 文件夹,自动验证、注册、生成头像、复制 persona\n- **文件附件** — 一次选多个文件发给 AI,支持 txt/docx/pdf,自动提取文本注入上下文\n- **聊天记录持久化** — 每个联系人一个 JSON,关掉浏览器再打开还在,按最新消息自动排序\n- **多模型切换** — 设置里填 API Key + Base URL + Model,随时切 Anthropic ↔ DeepSeek\n- **零硬编码** — 联系人是 `skills_config.json` 数据文件,增删改在 UI 完成,不动代码\n- **可移植** — `pip install flask anthropic && python3 server.py`,整个文件夹下载下来就能跑\n\n---\n\n## Skill 格式\n\n本项目导入的 skill 需要是一个**文件夹**,最低要求包含以下文件之一(优先级:`SKILL.md` > `persona.md`,两者同时存在时只读 `SKILL.md`):\n\n### 方式 A:单文件 `SKILL.md`(推荐)\n\n```\nmy-skill/\n├── SKILL.md # 完整的 persona + work 合并文件\n└── meta.json # 可选,提供 display_name、标签等元数据\n```\n\n这是 dot-skill 的标准输出格式。`SKILL.md` 即为完整的 system prompt,约 20-30KB,包含角色描述、说话风格、行为规则等。\n\n### 方式 B:分离文件 `persona.md` + `work.md`\n\n```\nmy-skill/\n├── persona.md # 人物性格(必选)\n├── work.md # 工作能力(可选)\n└── meta.json # 可选\n```\n\n导入时自动合并 `persona.md` 和 `work.md`。\n\n### meta.json(可选)\n\n```json\n{\n \"display_name\": \"肖易恒\",\n \"name\": \"colleague-xiaoyiheng\",\n \"tags\": [\"NPD\", \"自恋型人格障碍\", \"北京林业大学\"]\n}\n```\n\n- `display_name` → 联系人列表显示的名字(优先于文件夹名)\n- `name` → 内部 skill 名\n- 没有 `meta.json` 时使用文件夹名\n\n> **制作 skill**:用 `/dot-skill` 从聊天记录蒸馏高还原度人格,或用任何 LLM 写一段角色描述存为 `SKILL.md`。\n\n---\n\n## 快速开始\n\n### 1. 安装\n\n```bash\ngit clone https://github.com/yourusername/wechat-skill-chat.git\ncd wechat-skill-chat\npip install flask anthropic\n```\n\n### 2. 启动\n\n```bash\npython3 server.py\n```\n\n打开 `http://localhost:5888`。\n\n### 3. 配置 API\n\n左下角齿轮 → 设置:\n\n| 字段 | Anthropic | DeepSeek |\n|------|-----------|----------|\n| Base URL | 留空(SDK 默认) | `https://api.deepseek.com/anthropic` |\n| Model | `claude-sonnet-4-20250514` | `deepseek-v4-pro` |\n| API Key | `sk-ant-...` | `sk-...` |\n\nAPI Key 保存时自动 base64 混淆,不会明文泄露。\n\n### 4. 导入 Skill\n\n通讯录 → **+ 添加 Skill** → 输入文件夹路径 → 导入。新的联系人即刻出现在聊天列表。\n\n---\n\n## 架构\n\n```\nwechat-skill-chat/\n├── server.py # Flask 入口,注册 4 个 Blueprint\n├── skills_config.json # 联系人注册表(JSON 数据,非代码)\n├── settings.json # API 配置(gitignore)\n├── backend/\n│ ├── config.py # JSON 读写 + fcntl 文件锁\n│ ├── skills.py # Persona 三级查找加载\n│ ├── ai.py # Anthropic SDK 封装 + WeChat 格式注入\n│ ├── history.py # 聊天记录 CRUD(fcntl 锁,200 条/人上限)\n│ └── routes/\n│ ├── chat_routes.py # /api/send, /api/history\n│ ├── contacts_routes.py # /api/config, import/delete/update\n│ ├── settings_routes.py # /api/settings\n│ └── static_routes.py # /avatars, /emoji\n├── templates/index.html # 微信 PC 版 1:1 结构\n├── static/\n│ ├── css/style.css # 完整样式\n│ ├── js/chat.js # 前端逻辑(Session隔离/乐观UI/Emoji渲染)\n│ ├── emoji/{face,gesture,...} # 109 个微信黄脸 PNG\n│ └── avatars/ # SVG 头像\n└── skills/ # 用户导入的 skill 文件\n```\n\n**数据流**:用户发消息 → Flask → 加载 SKILL.md → 拼入 system prompt(最高优先级格式指令)→ Anthropic Messages API → 按换行拆成多条 → 渲染聊天气泡。\n\n---\n\n## 细节\n\n### 消息发送\n\n用户消息先渲染绿气泡(乐观 UI),不等 API 返回。API 响应后追加白气泡。切换会话时 `chatId` 捕获机制保证消息不串到别人那里。中文输入法组合输入期间 Enter 不触发发送。\n\n### 并发安全\n\n`skills_config.json` 和 `chat_history/*.json` 使用 `fcntl.flock` 文件锁,多个请求同时操作不会损坏数据。每人的聊天记录上限 200 条。\n\n### 表情渲染\n\n109 个微信原生黄脸 PNG 按 `face/gesture/animal/blessing/other` 五类分目录。前端 `_emojiLookup` 映射中文名到目录,`[捂脸]` 在聊天气泡中渲染为 `<img src=\"/emoji/face/捂脸.png\">`。表情选择面板可直接点击插入。\n\n### 时间格式化\n\n| 距离 | 聊天气泡 | 联系人卡片 |\n|------|---------|-----------|\n| 今天 | `14:30` | `14:30` |\n| 昨天 | `昨天 14:30` | `昨天14:30` |\n| 2-6天前 | `星期三 14:30` | `星期三` |\n| 今年内 | `5/20 14:30` | `5/20` |\n| 更早 | `2025/12/3 14:30` | `2025/12/3` |\n\n### AI 格式约束\n\n每次 API 调用前,system prompt 最前面注入最高优先级格式指令,强制模型:\n- **禁止 Markdown 语法** — `# * ** ~~ \\` \\`\\`\\`` 等全部禁用,微信没人用这些\n- 禁止 `(顿了顿)` 等括号动作描写\n- 禁止旁白、叙述性文字、场景描述\n- 表情用 `[捂脸]` 格式\n- 消息简短、口语化、无剧本感\n\n### 输入框\n\n工具栏含表情/文件/语音通话/视频通话四个图标。语音/视频通话点击弹出 `\"你走火入魔了,还真想给 AI 打电话啊?\"`。输入框可拖拽顶部边框调整高度(52-120px)。有文字时发送按钮变微信绿。\n\n### 文件附件\n\n前端将文件转为 base64 传给后端。后端根据扩展名选择解析器:\n\n| 类型 | 支持 | 需要 |\n|------|------|------|\n| `.txt` `.md` `.py` 等 | ✓ 内置 | 无 |\n| `.docx` | ✓ | `pip install python-docx` |\n| `.pdf`(有文本层) | ✓ | `pip install PyPDF2` |\n\n提取文本截断到 100,000 字符注入 API 调用。聊天记录存 JSON 时再截断预览,避免历史文件过大。\n"}}}} |