weiclawpy 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weiclawpy-0.1.0/LICENSE +21 -0
- weiclawpy-0.1.0/PKG-INFO +305 -0
- weiclawpy-0.1.0/README.md +276 -0
- weiclawpy-0.1.0/pyproject.toml +44 -0
- weiclawpy-0.1.0/setup.cfg +4 -0
- weiclawpy-0.1.0/weiclawpy/__init__.py +1 -0
- weiclawpy-0.1.0/weiclawpy/__main__.py +409 -0
- weiclawpy-0.1.0/weiclawpy/cdn.py +44 -0
- weiclawpy-0.1.0/weiclawpy/logger.py +169 -0
- weiclawpy-0.1.0/weiclawpy/opencode_api.py +281 -0
- weiclawpy-0.1.0/weiclawpy/opencode_cmd.py +201 -0
- weiclawpy-0.1.0/weiclawpy/opencode_serve.py +111 -0
- weiclawpy-0.1.0/weiclawpy/session_manager.py +102 -0
- weiclawpy-0.1.0/weiclawpy/weixin.py +423 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/PKG-INFO +305 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/SOURCES.txt +18 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/dependency_links.txt +1 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/entry_points.txt +2 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/requires.txt +3 -0
- weiclawpy-0.1.0/weiclawpy.egg-info/top_level.txt +1 -0
weiclawpy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 weiclawpy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
weiclawpy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: weiclawpy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 远程连接微信与 OpenCode | Connect WeChat to OpenCode
|
|
5
|
+
Author: Ming
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Ming0Liu/weiclawpy
|
|
8
|
+
Project-URL: Repository, https://github.com/Ming0Liu/weiclawpy
|
|
9
|
+
Project-URL: BugTracker, https://github.com/Ming0Liu/weiclawpy/issues
|
|
10
|
+
Keywords: wechat,opencode,ai,bridge,weixin
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Communications :: Chat
|
|
21
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: pycryptodome>=3.20.0
|
|
26
|
+
Requires-Dist: qrcode>=7.4.0
|
|
27
|
+
Requires-Dist: requests>=2.28.0
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# weiclawpy
|
|
31
|
+
|
|
32
|
+
<p>
|
|
33
|
+
<img src="https://img.shields.io/badge/python-3.9%2B-blue" alt="Python 3.9+">
|
|
34
|
+
<img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License">
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
远程连接微信与 OpenCode。
|
|
38
|
+
|
|
39
|
+
**weiclawpy** 是一个 Python CLI 桥接工具,连接微信(ilinkai 机器人 API)与 OpenCode AI(终端 AI 编码助手)。它让微信用户可以通过自然语言与 OpenCode 交互:发送文本、图片、语音消息和文件,并接收 AI 生成的回复。本质上,它将微信转变为 OpenCode 的对话前端。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 目录
|
|
44
|
+
|
|
45
|
+
- [快速开始](#快速开始)
|
|
46
|
+
- [CLI 用法](#cli-用法)
|
|
47
|
+
- [架构概览](#架构概览)
|
|
48
|
+
- [模块详解](#模块详解)
|
|
49
|
+
- [数据持久化](#数据持久化)
|
|
50
|
+
- [环境变量](#环境变量)
|
|
51
|
+
- [FAQ](#faq)
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 快速开始
|
|
56
|
+
|
|
57
|
+
### 前置条件
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Python >= 3.9
|
|
61
|
+
# 安装 OpenCode AI(npm 全局包)
|
|
62
|
+
npm install -g opencode-ai
|
|
63
|
+
|
|
64
|
+
# 安装 weiclawpy
|
|
65
|
+
pip install weiclawpy
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 启动桥接服务
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
weiclawpy run
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
首次运行会在终端打印微信二维码,扫码登录后即开始自动轮询消息。后续运行会自动复用凭证,无需重复扫码。**运行中若 token 过期,会自动弹出二维码重新登录,无需重启服务。**
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## CLI 用法
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
weiclawpy
|
|
82
|
+
├── weiclawpy run [选项] (默认命令) 启动长驻桥接服务
|
|
83
|
+
│ ├── --verbose, -v 打印详细 HTTP 调试日志
|
|
84
|
+
│ └── --relogin 强制重新扫码登录
|
|
85
|
+
│
|
|
86
|
+
└── weiclawpy send 一次性消息发送工具
|
|
87
|
+
├── --to <user_id> 接收者微信 user_id(必填)
|
|
88
|
+
├── --text <文本> 发送文本消息
|
|
89
|
+
├── --file <路径> 发送文件(支持 PDF 等)
|
|
90
|
+
├── --verbose, -v
|
|
91
|
+
└── --relogin
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### weiclawpy run — 主服务模式
|
|
95
|
+
|
|
96
|
+
启动后会依次执行:
|
|
97
|
+
|
|
98
|
+
1. 自动启动 `opencode serve` 子进程(监听 `127.0.0.1:4096`)
|
|
99
|
+
2. 加载微信凭证或弹出二维码登录
|
|
100
|
+
3. 进入无限消息轮询循环
|
|
101
|
+
|
|
102
|
+
主循环中,每小时会在终端打印一次心跳 `桥运行中...`。按 `Ctrl+C` 优雅停止。
|
|
103
|
+
|
|
104
|
+
### weiclawpy send — 一次性发送
|
|
105
|
+
|
|
106
|
+
用于从命令行主动向微信用户发送消息。需要接收者的 `user_id`(对方必须先通过微信向机器人发过消息,才能获取上下文令牌)。
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# 发送文本
|
|
110
|
+
weiclawpy send --to <user_id> --text "你好"
|
|
111
|
+
|
|
112
|
+
# 发送文件
|
|
113
|
+
weiclawpy send --to <user_id> --file report.pdf
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 架构概览
|
|
119
|
+
|
|
120
|
+
| 模块 | 职责 |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `__main__.py` | CLI 入口 + 主循环编排器 |
|
|
123
|
+
| `weixin.py` | 微信 ilinkai API 客户端 |
|
|
124
|
+
| `opencode_api.py` | OpenCode HTTP REST 客户端 |
|
|
125
|
+
| `opencode_cmd.py` | 微信斜杠命令路由器 |
|
|
126
|
+
| `opencode_serve.py` | OpenCode 子进程管理器 |
|
|
127
|
+
| `session_manager.py` | 微信用户 ↔ OpenCode 会话映射 |
|
|
128
|
+
| `cdn.py` | 微信 CDN AES-128-ECB 加解密 |
|
|
129
|
+
| `logger.py` | Markdown 对话日志 |
|
|
130
|
+
|
|
131
|
+
### 消息处理流程
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
微信用户发送消息
|
|
135
|
+
│
|
|
136
|
+
▼
|
|
137
|
+
__main__.py 轮询循环 (get_updates, 35s long-poll)
|
|
138
|
+
│
|
|
139
|
+
▼
|
|
140
|
+
_handle_msg() 按消息类型分发
|
|
141
|
+
│
|
|
142
|
+
├── 图片 ────────→ 下载解密 → 暂存 pending,等待关联文字
|
|
143
|
+
│
|
|
144
|
+
├── 语音 ────────→ 提取转文字 → 发给 OpenCode → 回复
|
|
145
|
+
│
|
|
146
|
+
├── 文件 ────────→ 下载解密 → 保存到 from_wechat/
|
|
147
|
+
│
|
|
148
|
+
└── 文字 ────────→ 以 / 开头 → opencode_cmd 命令路由
|
|
149
|
+
│
|
|
150
|
+
└── 普通文字 → _ask_opencode()
|
|
151
|
+
├── 获取/创建 OpenCode 会话
|
|
152
|
+
├── 读取用户的 model/agent 偏好
|
|
153
|
+
├── 发送"正在输入"状态到微信
|
|
154
|
+
├── opencode_api.send_message() → AI 回复
|
|
155
|
+
├── logger.log_response() 记录日志
|
|
156
|
+
└── 回复拆分为文本/图片,发回微信
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 模块详解
|
|
162
|
+
|
|
163
|
+
### `__main__.py` — 核心编排器
|
|
164
|
+
|
|
165
|
+
这是应用的**大脑**,负责编排所有其他模块。
|
|
166
|
+
|
|
167
|
+
**关键设计——图片缓冲机制:**
|
|
168
|
+
|
|
169
|
+
微信将图片和文字作为**两条独立消息**发送(图片先到,文字后到)。`pending` 字典(内存中,5 分钟 TTL)暂存图片 base64,等文字到来后组合为"图片+文字"一起发给 OpenCode。若 5 分钟内无文字到来,图片自动丢弃。
|
|
170
|
+
|
|
171
|
+
### `weixin.py` — 微信 API 客户端
|
|
172
|
+
|
|
173
|
+
对接微信 ilinkai 开放平台,基础地址 `https://ilinkai.weixin.qq.com`,机器人类型 `"3"`。
|
|
174
|
+
|
|
175
|
+
| 功能 | 说明 |
|
|
176
|
+
|---|---|
|
|
177
|
+
| 二维码登录 | 获取二维码 → 轮询扫描/确认/过期状态,得到 bot_token |
|
|
178
|
+
| 消息轮询 | 35 秒 long-poll,每次返回 get_updates_buf 做游标 |
|
|
179
|
+
| 发送消息 | 支持文本(type=1)、图片(type=2)、文件(type=4) |
|
|
180
|
+
| 文件上传 | 本地文件 AES-128-ECB 加密后上传微信 CDN,再发送媒体引用 |
|
|
181
|
+
| 输入状态 | send_typing(status=1 开始输入, status=2 停止输入) |
|
|
182
|
+
| 上下文令牌 | 多轮对话需要 context_token,自动保存到本地文件 |
|
|
183
|
+
|
|
184
|
+
### `opencode_api.py` — OpenCode HTTP 客户端
|
|
185
|
+
|
|
186
|
+
对 `opencode serve` 的 HTTP API(`http://127.0.0.1:4096`)的完整封装。
|
|
187
|
+
|
|
188
|
+
| 端点 | 用途 |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `GET /global/health` | 健康检查 |
|
|
191
|
+
| `POST /session` | 创建会话 |
|
|
192
|
+
| `POST /session/{id}/message` | 发送消息(超时 300 秒) |
|
|
193
|
+
| `POST /session/{id}/command` | 执行斜杠命令 |
|
|
194
|
+
| `GET /config/providers` | 获取可用模型列表 |
|
|
195
|
+
| `GET /agent` | 获取可用 Agent 列表 |
|
|
196
|
+
|
|
197
|
+
**模型解析:** 支持 `"provider/model"` 格式(如 `"anthropic/claude-sonnet-4-20250514"`),也支持纯 model ID 自动查找 provider。
|
|
198
|
+
|
|
199
|
+
### `opencode_cmd.py` — 命令路由器
|
|
200
|
+
|
|
201
|
+
在微信内通过斜杠命令控制 OpenCode 的行为。
|
|
202
|
+
|
|
203
|
+
| 命令 | 功能 |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `/help` | 显示帮助 + 当前模型/agent |
|
|
206
|
+
| `/new` | 开启新对话(创建新会话) |
|
|
207
|
+
| `/sessions` | 列出所有 OpenCode 会话 |
|
|
208
|
+
| `/models` | 列出所有可用模型 |
|
|
209
|
+
| `/model <名称>` | 切换模型(如 `anthropic/claude-sonnet-4-20250514`) |
|
|
210
|
+
| `/agents` | 列出所有可用 Agent |
|
|
211
|
+
| `/agent <名称>` | 切换当前 Agent |
|
|
212
|
+
| `/abort` | 中止当前 AI 生成 |
|
|
213
|
+
| `/config` | 查看 OpenCode 配置 |
|
|
214
|
+
| `/shell <命令>` | 在服务器上运行 Windows 命令(60 秒超时) |
|
|
215
|
+
| `/clear` | 清空对话(同 /new) |
|
|
216
|
+
|
|
217
|
+
### `opencode_serve.py` — 子进程管理
|
|
218
|
+
|
|
219
|
+
管理 `opencode serve` 进程的完整生命周期:
|
|
220
|
+
- 查找 `opencode` 可执行文件(PATH → npm 全局目录)
|
|
221
|
+
- 启动后轮询 `/global/health` 等待就绪
|
|
222
|
+
- 停止时先 SIGTERM,3 秒未响应则 SIGKILL
|
|
223
|
+
- 支持通过 `OPENCODE_SERVER_PASSWORD` 环境变量配置 Basic 认证
|
|
224
|
+
|
|
225
|
+
### `session_manager.py` — 用户会话管理
|
|
226
|
+
|
|
227
|
+
将微信用户 ID 映射到 OpenCode 会话 ID,持久化在 `~/.weiclawpy/user_sessions.json`。
|
|
228
|
+
- 线程安全读写(`threading.Lock` + 临时文件 + `os.replace()`)
|
|
229
|
+
- `ensure_session()`:检查会话存活,存活则复用,否则创建新会话
|
|
230
|
+
- 存储每个用户的模型偏好、agent 偏好
|
|
231
|
+
|
|
232
|
+
### `cdn.py` — CDN 加解密
|
|
233
|
+
|
|
234
|
+
微信多媒体文件的 AES-128-ECB 加解密处理。
|
|
235
|
+
|
|
236
|
+
### `logger.py` — 对话日志
|
|
237
|
+
|
|
238
|
+
将每次 AI 交互记录为 Markdown 文件,`~/.weiclawpy/logs/opencode-YYYY-MM-DD.md`,每日轮换。包含:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
思考过程(details 折叠)
|
|
242
|
+
工具调用(输入/输出/错误)
|
|
243
|
+
文件修改(修改的文件路径列表)
|
|
244
|
+
AI 回复(纯文本)
|
|
245
|
+
附件(图片/文件 URL)
|
|
246
|
+
统计(费用、tokens、缓存命中率)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 数据持久化
|
|
252
|
+
|
|
253
|
+
| 文件 | 用途 |
|
|
254
|
+
|---|---|
|
|
255
|
+
| `~/.weiclawpy/credentials.json` | 微信 API token、user_id、account_id |
|
|
256
|
+
| `~/.weiclawpy/context_tokens.json` | 每个用户的微信多轮对话上下文令牌 |
|
|
257
|
+
| `~/.weiclawpy/user_sessions.json` | 每个用户的 OpenCode 会话 ID、模型/agent 偏好 |
|
|
258
|
+
| `~/.weiclawpy/logs/opencode-YYYY-MM-DD.md` | 每日轮换的详细对话日志 |
|
|
259
|
+
| `./from_wechat/`(工作目录下) | 从微信下载的图片和文件 |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 环境变量
|
|
264
|
+
|
|
265
|
+
| 变量 | 说明 | 默认值 |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `WEICLAWPY_DIR` | 覆盖数据存储目录 | `~/.weiclawpy` |
|
|
268
|
+
| `OPENCODE_SERVER_PASSWORD` | OpenCode 服务 Basic 认证密码 | (无认证) |
|
|
269
|
+
| `OPENCODE_SERVER_USERNAME` | OpenCode 服务 Basic 认证用户名 | `opencode` |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## FAQ
|
|
274
|
+
|
|
275
|
+
### 支持的微信消息类型?
|
|
276
|
+
|
|
277
|
+
文本、图片、语音(自动转文字)、文件。
|
|
278
|
+
|
|
279
|
+
### 如何切换 AI 模型?
|
|
280
|
+
|
|
281
|
+
在微信中发送 `/models` 查看可用模型列表,然后发送 `/model provider/model_name` 切换。例如:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
/model anthropic/claude-sonnet-4-20250514
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 数据存储在哪里?
|
|
288
|
+
|
|
289
|
+
默认在 `~/.weiclawpy/`,可通过 `WEICLAWPY_DIR` 环境变量更改。
|
|
290
|
+
|
|
291
|
+
### 需要公网服务器吗?
|
|
292
|
+
|
|
293
|
+
不需要。weiclawpy 连接微信 ilinkai API(公网)和本地运行的 `opencode serve`,可在个人电脑上运行。
|
|
294
|
+
|
|
295
|
+
### 微信凭证过期怎么办?
|
|
296
|
+
|
|
297
|
+
**服务运行中过期:** weiclawpy 会自动检测 token 过期(HTTP 401/403),清除过期凭证并在终端重新展示二维码,扫码后自动恢复,无需手动干预。
|
|
298
|
+
|
|
299
|
+
**启动时强制重登:** 运行 `weiclawpy run --relogin` 可跳过已有凭证,强制重新扫码登录。
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## License
|
|
304
|
+
|
|
305
|
+
[MIT](LICENSE) © 2025 weiclawpy
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# weiclawpy
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<img src="https://img.shields.io/badge/python-3.9%2B-blue" alt="Python 3.9+">
|
|
5
|
+
<img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License">
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
远程连接微信与 OpenCode。
|
|
9
|
+
|
|
10
|
+
**weiclawpy** 是一个 Python CLI 桥接工具,连接微信(ilinkai 机器人 API)与 OpenCode AI(终端 AI 编码助手)。它让微信用户可以通过自然语言与 OpenCode 交互:发送文本、图片、语音消息和文件,并接收 AI 生成的回复。本质上,它将微信转变为 OpenCode 的对话前端。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [快速开始](#快速开始)
|
|
17
|
+
- [CLI 用法](#cli-用法)
|
|
18
|
+
- [架构概览](#架构概览)
|
|
19
|
+
- [模块详解](#模块详解)
|
|
20
|
+
- [数据持久化](#数据持久化)
|
|
21
|
+
- [环境变量](#环境变量)
|
|
22
|
+
- [FAQ](#faq)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 快速开始
|
|
27
|
+
|
|
28
|
+
### 前置条件
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Python >= 3.9
|
|
32
|
+
# 安装 OpenCode AI(npm 全局包)
|
|
33
|
+
npm install -g opencode-ai
|
|
34
|
+
|
|
35
|
+
# 安装 weiclawpy
|
|
36
|
+
pip install weiclawpy
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 启动桥接服务
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
weiclawpy run
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
首次运行会在终端打印微信二维码,扫码登录后即开始自动轮询消息。后续运行会自动复用凭证,无需重复扫码。**运行中若 token 过期,会自动弹出二维码重新登录,无需重启服务。**
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## CLI 用法
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
weiclawpy
|
|
53
|
+
├── weiclawpy run [选项] (默认命令) 启动长驻桥接服务
|
|
54
|
+
│ ├── --verbose, -v 打印详细 HTTP 调试日志
|
|
55
|
+
│ └── --relogin 强制重新扫码登录
|
|
56
|
+
│
|
|
57
|
+
└── weiclawpy send 一次性消息发送工具
|
|
58
|
+
├── --to <user_id> 接收者微信 user_id(必填)
|
|
59
|
+
├── --text <文本> 发送文本消息
|
|
60
|
+
├── --file <路径> 发送文件(支持 PDF 等)
|
|
61
|
+
├── --verbose, -v
|
|
62
|
+
└── --relogin
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### weiclawpy run — 主服务模式
|
|
66
|
+
|
|
67
|
+
启动后会依次执行:
|
|
68
|
+
|
|
69
|
+
1. 自动启动 `opencode serve` 子进程(监听 `127.0.0.1:4096`)
|
|
70
|
+
2. 加载微信凭证或弹出二维码登录
|
|
71
|
+
3. 进入无限消息轮询循环
|
|
72
|
+
|
|
73
|
+
主循环中,每小时会在终端打印一次心跳 `桥运行中...`。按 `Ctrl+C` 优雅停止。
|
|
74
|
+
|
|
75
|
+
### weiclawpy send — 一次性发送
|
|
76
|
+
|
|
77
|
+
用于从命令行主动向微信用户发送消息。需要接收者的 `user_id`(对方必须先通过微信向机器人发过消息,才能获取上下文令牌)。
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 发送文本
|
|
81
|
+
weiclawpy send --to <user_id> --text "你好"
|
|
82
|
+
|
|
83
|
+
# 发送文件
|
|
84
|
+
weiclawpy send --to <user_id> --file report.pdf
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 架构概览
|
|
90
|
+
|
|
91
|
+
| 模块 | 职责 |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `__main__.py` | CLI 入口 + 主循环编排器 |
|
|
94
|
+
| `weixin.py` | 微信 ilinkai API 客户端 |
|
|
95
|
+
| `opencode_api.py` | OpenCode HTTP REST 客户端 |
|
|
96
|
+
| `opencode_cmd.py` | 微信斜杠命令路由器 |
|
|
97
|
+
| `opencode_serve.py` | OpenCode 子进程管理器 |
|
|
98
|
+
| `session_manager.py` | 微信用户 ↔ OpenCode 会话映射 |
|
|
99
|
+
| `cdn.py` | 微信 CDN AES-128-ECB 加解密 |
|
|
100
|
+
| `logger.py` | Markdown 对话日志 |
|
|
101
|
+
|
|
102
|
+
### 消息处理流程
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
微信用户发送消息
|
|
106
|
+
│
|
|
107
|
+
▼
|
|
108
|
+
__main__.py 轮询循环 (get_updates, 35s long-poll)
|
|
109
|
+
│
|
|
110
|
+
▼
|
|
111
|
+
_handle_msg() 按消息类型分发
|
|
112
|
+
│
|
|
113
|
+
├── 图片 ────────→ 下载解密 → 暂存 pending,等待关联文字
|
|
114
|
+
│
|
|
115
|
+
├── 语音 ────────→ 提取转文字 → 发给 OpenCode → 回复
|
|
116
|
+
│
|
|
117
|
+
├── 文件 ────────→ 下载解密 → 保存到 from_wechat/
|
|
118
|
+
│
|
|
119
|
+
└── 文字 ────────→ 以 / 开头 → opencode_cmd 命令路由
|
|
120
|
+
│
|
|
121
|
+
└── 普通文字 → _ask_opencode()
|
|
122
|
+
├── 获取/创建 OpenCode 会话
|
|
123
|
+
├── 读取用户的 model/agent 偏好
|
|
124
|
+
├── 发送"正在输入"状态到微信
|
|
125
|
+
├── opencode_api.send_message() → AI 回复
|
|
126
|
+
├── logger.log_response() 记录日志
|
|
127
|
+
└── 回复拆分为文本/图片,发回微信
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 模块详解
|
|
133
|
+
|
|
134
|
+
### `__main__.py` — 核心编排器
|
|
135
|
+
|
|
136
|
+
这是应用的**大脑**,负责编排所有其他模块。
|
|
137
|
+
|
|
138
|
+
**关键设计——图片缓冲机制:**
|
|
139
|
+
|
|
140
|
+
微信将图片和文字作为**两条独立消息**发送(图片先到,文字后到)。`pending` 字典(内存中,5 分钟 TTL)暂存图片 base64,等文字到来后组合为"图片+文字"一起发给 OpenCode。若 5 分钟内无文字到来,图片自动丢弃。
|
|
141
|
+
|
|
142
|
+
### `weixin.py` — 微信 API 客户端
|
|
143
|
+
|
|
144
|
+
对接微信 ilinkai 开放平台,基础地址 `https://ilinkai.weixin.qq.com`,机器人类型 `"3"`。
|
|
145
|
+
|
|
146
|
+
| 功能 | 说明 |
|
|
147
|
+
|---|---|
|
|
148
|
+
| 二维码登录 | 获取二维码 → 轮询扫描/确认/过期状态,得到 bot_token |
|
|
149
|
+
| 消息轮询 | 35 秒 long-poll,每次返回 get_updates_buf 做游标 |
|
|
150
|
+
| 发送消息 | 支持文本(type=1)、图片(type=2)、文件(type=4) |
|
|
151
|
+
| 文件上传 | 本地文件 AES-128-ECB 加密后上传微信 CDN,再发送媒体引用 |
|
|
152
|
+
| 输入状态 | send_typing(status=1 开始输入, status=2 停止输入) |
|
|
153
|
+
| 上下文令牌 | 多轮对话需要 context_token,自动保存到本地文件 |
|
|
154
|
+
|
|
155
|
+
### `opencode_api.py` — OpenCode HTTP 客户端
|
|
156
|
+
|
|
157
|
+
对 `opencode serve` 的 HTTP API(`http://127.0.0.1:4096`)的完整封装。
|
|
158
|
+
|
|
159
|
+
| 端点 | 用途 |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `GET /global/health` | 健康检查 |
|
|
162
|
+
| `POST /session` | 创建会话 |
|
|
163
|
+
| `POST /session/{id}/message` | 发送消息(超时 300 秒) |
|
|
164
|
+
| `POST /session/{id}/command` | 执行斜杠命令 |
|
|
165
|
+
| `GET /config/providers` | 获取可用模型列表 |
|
|
166
|
+
| `GET /agent` | 获取可用 Agent 列表 |
|
|
167
|
+
|
|
168
|
+
**模型解析:** 支持 `"provider/model"` 格式(如 `"anthropic/claude-sonnet-4-20250514"`),也支持纯 model ID 自动查找 provider。
|
|
169
|
+
|
|
170
|
+
### `opencode_cmd.py` — 命令路由器
|
|
171
|
+
|
|
172
|
+
在微信内通过斜杠命令控制 OpenCode 的行为。
|
|
173
|
+
|
|
174
|
+
| 命令 | 功能 |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `/help` | 显示帮助 + 当前模型/agent |
|
|
177
|
+
| `/new` | 开启新对话(创建新会话) |
|
|
178
|
+
| `/sessions` | 列出所有 OpenCode 会话 |
|
|
179
|
+
| `/models` | 列出所有可用模型 |
|
|
180
|
+
| `/model <名称>` | 切换模型(如 `anthropic/claude-sonnet-4-20250514`) |
|
|
181
|
+
| `/agents` | 列出所有可用 Agent |
|
|
182
|
+
| `/agent <名称>` | 切换当前 Agent |
|
|
183
|
+
| `/abort` | 中止当前 AI 生成 |
|
|
184
|
+
| `/config` | 查看 OpenCode 配置 |
|
|
185
|
+
| `/shell <命令>` | 在服务器上运行 Windows 命令(60 秒超时) |
|
|
186
|
+
| `/clear` | 清空对话(同 /new) |
|
|
187
|
+
|
|
188
|
+
### `opencode_serve.py` — 子进程管理
|
|
189
|
+
|
|
190
|
+
管理 `opencode serve` 进程的完整生命周期:
|
|
191
|
+
- 查找 `opencode` 可执行文件(PATH → npm 全局目录)
|
|
192
|
+
- 启动后轮询 `/global/health` 等待就绪
|
|
193
|
+
- 停止时先 SIGTERM,3 秒未响应则 SIGKILL
|
|
194
|
+
- 支持通过 `OPENCODE_SERVER_PASSWORD` 环境变量配置 Basic 认证
|
|
195
|
+
|
|
196
|
+
### `session_manager.py` — 用户会话管理
|
|
197
|
+
|
|
198
|
+
将微信用户 ID 映射到 OpenCode 会话 ID,持久化在 `~/.weiclawpy/user_sessions.json`。
|
|
199
|
+
- 线程安全读写(`threading.Lock` + 临时文件 + `os.replace()`)
|
|
200
|
+
- `ensure_session()`:检查会话存活,存活则复用,否则创建新会话
|
|
201
|
+
- 存储每个用户的模型偏好、agent 偏好
|
|
202
|
+
|
|
203
|
+
### `cdn.py` — CDN 加解密
|
|
204
|
+
|
|
205
|
+
微信多媒体文件的 AES-128-ECB 加解密处理。
|
|
206
|
+
|
|
207
|
+
### `logger.py` — 对话日志
|
|
208
|
+
|
|
209
|
+
将每次 AI 交互记录为 Markdown 文件,`~/.weiclawpy/logs/opencode-YYYY-MM-DD.md`,每日轮换。包含:
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
思考过程(details 折叠)
|
|
213
|
+
工具调用(输入/输出/错误)
|
|
214
|
+
文件修改(修改的文件路径列表)
|
|
215
|
+
AI 回复(纯文本)
|
|
216
|
+
附件(图片/文件 URL)
|
|
217
|
+
统计(费用、tokens、缓存命中率)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 数据持久化
|
|
223
|
+
|
|
224
|
+
| 文件 | 用途 |
|
|
225
|
+
|---|---|
|
|
226
|
+
| `~/.weiclawpy/credentials.json` | 微信 API token、user_id、account_id |
|
|
227
|
+
| `~/.weiclawpy/context_tokens.json` | 每个用户的微信多轮对话上下文令牌 |
|
|
228
|
+
| `~/.weiclawpy/user_sessions.json` | 每个用户的 OpenCode 会话 ID、模型/agent 偏好 |
|
|
229
|
+
| `~/.weiclawpy/logs/opencode-YYYY-MM-DD.md` | 每日轮换的详细对话日志 |
|
|
230
|
+
| `./from_wechat/`(工作目录下) | 从微信下载的图片和文件 |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 环境变量
|
|
235
|
+
|
|
236
|
+
| 变量 | 说明 | 默认值 |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `WEICLAWPY_DIR` | 覆盖数据存储目录 | `~/.weiclawpy` |
|
|
239
|
+
| `OPENCODE_SERVER_PASSWORD` | OpenCode 服务 Basic 认证密码 | (无认证) |
|
|
240
|
+
| `OPENCODE_SERVER_USERNAME` | OpenCode 服务 Basic 认证用户名 | `opencode` |
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## FAQ
|
|
245
|
+
|
|
246
|
+
### 支持的微信消息类型?
|
|
247
|
+
|
|
248
|
+
文本、图片、语音(自动转文字)、文件。
|
|
249
|
+
|
|
250
|
+
### 如何切换 AI 模型?
|
|
251
|
+
|
|
252
|
+
在微信中发送 `/models` 查看可用模型列表,然后发送 `/model provider/model_name` 切换。例如:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
/model anthropic/claude-sonnet-4-20250514
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 数据存储在哪里?
|
|
259
|
+
|
|
260
|
+
默认在 `~/.weiclawpy/`,可通过 `WEICLAWPY_DIR` 环境变量更改。
|
|
261
|
+
|
|
262
|
+
### 需要公网服务器吗?
|
|
263
|
+
|
|
264
|
+
不需要。weiclawpy 连接微信 ilinkai API(公网)和本地运行的 `opencode serve`,可在个人电脑上运行。
|
|
265
|
+
|
|
266
|
+
### 微信凭证过期怎么办?
|
|
267
|
+
|
|
268
|
+
**服务运行中过期:** weiclawpy 会自动检测 token 过期(HTTP 401/403),清除过期凭证并在终端重新展示二维码,扫码后自动恢复,无需手动干预。
|
|
269
|
+
|
|
270
|
+
**启动时强制重登:** 运行 `weiclawpy run --relogin` 可跳过已有凭证,强制重新扫码登录。
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## License
|
|
275
|
+
|
|
276
|
+
[MIT](LICENSE) © 2025 weiclawpy
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "weiclawpy"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "远程连接微信与 OpenCode | Connect WeChat to OpenCode"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Ming" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["wechat", "opencode", "ai", "bridge", "weixin"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Communications :: Chat",
|
|
27
|
+
"Topic :: Software Development :: Build Tools",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pycryptodome>=3.20.0",
|
|
31
|
+
"qrcode>=7.4.0",
|
|
32
|
+
"requests>=2.28.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/Ming0Liu/weiclawpy"
|
|
37
|
+
Repository = "https://github.com/Ming0Liu/weiclawpy"
|
|
38
|
+
BugTracker = "https://github.com/Ming0Liu/weiclawpy/issues"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
weiclawpy = "weiclawpy.__main__:main"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
include = ["weiclawpy*"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|