wechat-to-anything 0.6.3 → 0.6.5
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.
- package/README.en.md +165 -0
- package/README.md +88 -89
- package/cli/agent-adapter.mjs +6 -6
- package/cli/bridge.mjs +1 -1
- package/cli/cdn.mjs +1 -0
- package/cli/weixin.mjs +6 -2
- package/docs/banner.png +0 -0
- package/docs/wechat-image-receive.png +0 -0
- package/docs/wechat-image-send.png +0 -0
- package/examples/file-test.mjs +39 -0
- package/package.json +1 -1
package/README.en.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.png" alt="wechat-to-anything" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">wechat-to-anything</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/wechat-to-anything"><img src="https://img.shields.io/npm/v/wechat-to-anything?style=flat-square&color=cb3837" alt="npm" /></a>
|
|
9
|
+
<a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/github/stars/kellyvv/wechat-to-anything?style=flat-square&color=yellow" alt="stars" /></a>
|
|
10
|
+
<a href="LICENSE"><img src="https://img.shields.io/github/license/kellyvv/wechat-to-anything?style=flat-square" alt="license" /></a>
|
|
11
|
+
<a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square" alt="node" /></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="#quick-start">Quick Start</a> · <a href="#full-multimodal-matrix">Multimodal</a> · <a href="#media-protocol">Media Protocol</a> · <a href="#multi-agent-mode">Multi-Agent</a> · <a href="#bring-your-own-agent">Custom Agent</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="README.md">中文</a> | English
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
> ⭐ If this project helps you, please give it a Star!
|
|
23
|
+
|
|
24
|
+
**The first open-source project** to support full multimodal bidirectional communication between WeChat and AI Agents — text, images, voice, video, and files, both sending and receiving.
|
|
25
|
+
|
|
26
|
+
<p align="center">
|
|
27
|
+
<img src="docs/wechat-image-send.png" width="250" alt="Agent sends files, images, voice" />
|
|
28
|
+
<img src="docs/wechat-image-receive.png" width="250" alt="Agent sends images, video, voice" />
|
|
29
|
+
<a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
|
|
30
|
+
<img src="docs/wechat-voice-demo.gif" width="250" alt="Voice demo (click for audio)" />
|
|
31
|
+
</a>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- 🔌 **Zero-config setup** — One `npx` command, no cloning, no configuration
|
|
37
|
+
- 🧠 **Agent-agnostic** — Works with any OpenAI-compatible API (Codex / Gemini / Claude / custom)
|
|
38
|
+
- 📡 **Full multimodal** — Text, images, voice, video, files — bidirectional
|
|
39
|
+
- 🤖 **Multi-Agent** — Connect multiple Agents simultaneously, route with `@` prefix
|
|
40
|
+
- ⌨️ **Typing indicator** — Shows "typing..." while Agent is thinking
|
|
41
|
+
|
|
42
|
+
### Full Multimodal Matrix
|
|
43
|
+
|
|
44
|
+
| Modality | WeChat → Agent | Agent → WeChat |
|
|
45
|
+
|------|:---:|:---:|
|
|
46
|
+
| 📝 Text | ✅ | ✅ |
|
|
47
|
+
| 📷 Image | ✅ Auto-detect | ✅ HD original |
|
|
48
|
+
| 🎤 Voice | ✅ Speech-to-text | ✅ Voice bubble |
|
|
49
|
+
| 🎬 Video | ✅ Auto-receive | ✅ With thumbnail |
|
|
50
|
+
| 📄 File | ✅ Content extraction | ✅ Downloadable |
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Pick your favorite Agent:
|
|
56
|
+
npx wechat-to-anything --codex # OpenAI Codex
|
|
57
|
+
npx wechat-to-anything --gemini # Google Gemini
|
|
58
|
+
npx wechat-to-anything --claude # Claude Code
|
|
59
|
+
npx wechat-to-anything --openclaw # OpenClaw
|
|
60
|
+
|
|
61
|
+
# Or pass a URL directly:
|
|
62
|
+
npx wechat-to-anything http://your-agent:8000/v1
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> First time: A QR code pops up in terminal → Scan with WeChat → Done. Login is cached automatically.
|
|
66
|
+
|
|
67
|
+
### Dependencies
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# 1. Node.js >= 22
|
|
71
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
72
|
+
nvm install 22
|
|
73
|
+
|
|
74
|
+
# 2. Python 3 + pip
|
|
75
|
+
brew install python3 # macOS
|
|
76
|
+
apt install python3 python3-pip # Linux
|
|
77
|
+
|
|
78
|
+
# 3. ffmpeg
|
|
79
|
+
brew install ffmpeg # macOS
|
|
80
|
+
apt install ffmpeg # Linux
|
|
81
|
+
|
|
82
|
+
# 4. pilk
|
|
83
|
+
pip install pilk
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## How It Works
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
WeChat User ←→ Tencent ilinkai API ←→ wechat-to-anything ←→ Your Agent (HTTP)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Directly calls Tencent's ilinkai API to send/receive WeChat messages. No middleware, no reverse engineering, no web client. Your Agent just needs an OpenAI-compatible HTTP endpoint.
|
|
93
|
+
|
|
94
|
+
## Bring Your Own Agent
|
|
95
|
+
|
|
96
|
+
Any language — just expose `POST /v1/chat/completions`:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
@app.post("/v1/chat/completions")
|
|
100
|
+
def chat(request):
|
|
101
|
+
message = request.json["messages"][-1]["content"]
|
|
102
|
+
reply = your_agent(message)
|
|
103
|
+
return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then: `npx wechat-to-anything http://your-agent:8000/v1`
|
|
107
|
+
|
|
108
|
+
## Media Protocol
|
|
109
|
+
|
|
110
|
+
Include specific formats in Agent responses to automatically send media:
|
|
111
|
+
|
|
112
|
+
| Type | Agent Response Format | Notes |
|
|
113
|
+
|------|----------------------|-------|
|
|
114
|
+
| Image | `` | URL, local path, or data URI |
|
|
115
|
+
| Voice | `[audio:path or URL]` | MP3/WAV/OGG, requires `ffmpeg` + `pilk` |
|
|
116
|
+
| Video | `[video:path or URL]` | Requires `ffmpeg` |
|
|
117
|
+
| File | `[file:path or URL]` | Any file type |
|
|
118
|
+
|
|
119
|
+
**Image receiving** (WeChat → Agent) follows the [OpenAI Vision API](https://platform.openai.com/docs/guides/vision):
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"messages": [{
|
|
124
|
+
"role": "user",
|
|
125
|
+
"content": [
|
|
126
|
+
{ "type": "text", "text": "What is this?" },
|
|
127
|
+
{ "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } }
|
|
128
|
+
]
|
|
129
|
+
}]
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
> Examples: [image-test.mjs](examples/image-test.mjs) · [voice-test.mjs](examples/voice-test.mjs) · [video-test-local.mjs](examples/video-test-local.mjs) · [file-test.mjs](examples/file-test.mjs)
|
|
134
|
+
|
|
135
|
+
## Multi-Agent Mode
|
|
136
|
+
|
|
137
|
+
Connect multiple Agents simultaneously, route with `@` prefix. Supports OpenAI format and [ACP](https://agentcommunicationprotocol.dev/):
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npx wechat-to-anything \
|
|
141
|
+
--agent codex=http://localhost:3001/v1 \
|
|
142
|
+
--agent gemini=http://localhost:3002/v1 \
|
|
143
|
+
--agent bee=acp://localhost:8000/chat \
|
|
144
|
+
--default codex
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
| WeChat Message | Effect |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `Hello` | Sent to default Agent |
|
|
150
|
+
| `@codex write a sort` | Routes to Codex |
|
|
151
|
+
| `@gemini review code` | Routes to Gemini |
|
|
152
|
+
| `@list` | List all Agents |
|
|
153
|
+
| `@switch gemini` | Switch default |
|
|
154
|
+
|
|
155
|
+
## Credentials
|
|
156
|
+
|
|
157
|
+
Login credentials are saved in `~/.wechat-to-anything/credentials.json`. Delete to re-login.
|
|
158
|
+
|
|
159
|
+
## Star History
|
|
160
|
+
|
|
161
|
+
If this project helped you, please give it a ⭐ Star — it's the best support!
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
[MIT](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,79 +1,99 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.png" alt="wechat-to-anything" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
5
|
-
> ⭐ 如果这个项目对你有帮助,请给个 Star!本项目仅用于技术学习和交流,开源不易。
|
|
5
|
+
<h1 align="center">wechat-to-anything</h1>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/wechat-to-anything"><img src="https://img.shields.io/npm/v/wechat-to-anything?style=flat-square&color=cb3837" alt="npm" /></a>
|
|
9
|
+
<a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/github/stars/kellyvv/wechat-to-anything?style=flat-square&color=yellow" alt="stars" /></a>
|
|
10
|
+
<a href="LICENSE"><img src="https://img.shields.io/github/license/kellyvv/wechat-to-anything?style=flat-square" alt="license" /></a>
|
|
11
|
+
<a href="https://github.com/kellyvv/wechat-to-anything"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square" alt="node" /></a>
|
|
12
|
+
</p>
|
|
8
13
|
|
|
9
14
|
<p align="center">
|
|
10
|
-
<
|
|
11
|
-
<img src="docs/wechat-image-receive.png" width="250" alt="Agent 发送图片到微信" />
|
|
12
|
-
<a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
|
|
13
|
-
<img src="docs/wechat-voice-demo.gif" width="250" alt="语音发送演示(点击播放有声版)" />
|
|
14
|
-
</a>
|
|
15
|
+
<a href="#快速开始">快速开始</a> · <a href="#全模态支持矩阵">全模态</a> · <a href="#多媒体协议">多媒体协议</a> · <a href="#多-agent-模式">多 Agent</a> · <a href="#接入自己的-agent">自定义 Agent</a>
|
|
15
16
|
</p>
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
<p align="center">
|
|
19
|
+
中文 | <a href="README.en.md">English</a>
|
|
20
|
+
</p>
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
> ⭐ 如果这个项目对你有帮助,请给个 Star!
|
|
23
|
+
|
|
24
|
+
**全网首个**支持微信与任何 AI Agent 全模态双向通信的开源项目 —— 文本、图片、语音、视频、文件,发送和接收全覆盖。
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
<p align="center">
|
|
27
|
+
<img src="docs/wechat-image-send.png" width="250" alt="Agent 发送文件、图片、语音" />
|
|
28
|
+
<img src="docs/wechat-image-receive.png" width="250" alt="Agent 发送图片、视频、语音" />
|
|
29
|
+
<a href="https://github.com/kellyvv/wechat-to-anything/raw/main/docs/wechat-voice-demo.mp4">
|
|
30
|
+
<img src="docs/wechat-voice-demo.gif" width="250" alt="语音演示(点击播放有声版)" />
|
|
31
|
+
</a>
|
|
32
|
+
</p>
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
## 特性
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
- 🔌 **零依赖接入** — `npx` 一条命令,无需 clone、无需配置
|
|
37
|
+
- 🧠 **Agent 无关** — 支持任何 OpenAI 兼容 API(Codex / Gemini / Claude / 自建)
|
|
38
|
+
- 📡 **全模态** — 文本、图片、语音、视频、文件,双向全覆盖
|
|
39
|
+
- 🤖 **多 Agent** — 同时接入多个 Agent,`@` 路由切换
|
|
40
|
+
- ⌨️ **打字指示器** — Agent 思考时显示"对方正在输入"
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
### 全模态支持矩阵
|
|
33
43
|
|
|
34
|
-
|
|
44
|
+
| 模态 | 微信 → Agent | Agent → 微信 |
|
|
45
|
+
|------|:---:|:---:|
|
|
46
|
+
| 📝 文本 | ✅ | ✅ |
|
|
47
|
+
| 📷 图片 | ✅ 自动识别 | ✅ HD 原图 |
|
|
48
|
+
| 🎤 语音 | ✅ 语音转文字 | ✅ 语音气泡 |
|
|
49
|
+
| 🎬 视频 | ✅ 自动接收 | ✅ 带缩略图 |
|
|
50
|
+
| 📄 文件 | ✅ 提取内容 | ✅ 可下载 |
|
|
35
51
|
|
|
36
52
|
## 快速开始
|
|
37
53
|
|
|
38
54
|
```bash
|
|
39
|
-
#
|
|
55
|
+
# 选你喜欢的 Agent:
|
|
40
56
|
npx wechat-to-anything --codex # OpenAI Codex
|
|
41
57
|
npx wechat-to-anything --gemini # Google Gemini
|
|
42
58
|
npx wechat-to-anything --claude # Claude Code
|
|
43
59
|
npx wechat-to-anything --openclaw # OpenClaw
|
|
44
60
|
|
|
45
|
-
#
|
|
46
|
-
npx wechat-to-anything
|
|
61
|
+
# 或直接传 URL:
|
|
62
|
+
npx wechat-to-anything http://your-agent:8000/v1
|
|
47
63
|
```
|
|
48
64
|
|
|
49
|
-
>
|
|
50
|
-
>
|
|
51
|
-
> 也支持直接传 URL:`npx wechat-to-anything http://your-agent:8000/v1`
|
|
65
|
+
> 首次使用:终端弹出二维码 → 微信扫码 → 完成。之后自动复用登录。
|
|
52
66
|
|
|
53
|
-
###
|
|
67
|
+
### 环境依赖
|
|
54
68
|
|
|
55
69
|
```bash
|
|
56
|
-
# 1.
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
# 1. Node.js >= 22
|
|
71
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
72
|
+
nvm install 22
|
|
73
|
+
|
|
74
|
+
# 2. Python 3 + pip
|
|
75
|
+
brew install python3 # macOS
|
|
76
|
+
apt install python3 python3-pip # Linux
|
|
59
77
|
|
|
60
|
-
#
|
|
61
|
-
|
|
78
|
+
# 3. ffmpeg
|
|
79
|
+
brew install ffmpeg # macOS
|
|
80
|
+
apt install ffmpeg # Linux
|
|
62
81
|
|
|
63
|
-
#
|
|
64
|
-
|
|
82
|
+
# 4. pilk
|
|
83
|
+
pip install pilk
|
|
65
84
|
```
|
|
66
85
|
|
|
67
|
-
|
|
68
|
-
> 如果 OpenClaw 已有 `openclaw-weixin` 插件,需先禁用以避免消息冲突。
|
|
86
|
+
## 原理
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
```
|
|
89
|
+
微信用户 ←→ 腾讯 ilinkai API ←→ wechat-to-anything ←→ 你的 Agent (HTTP)
|
|
90
|
+
```
|
|
71
91
|
|
|
72
|
-
|
|
92
|
+
直接调用腾讯 ilinkai 接口收发微信消息,无中间层、无逆向、无网页版。Agent 只需暴露一个 OpenAI 兼容的 HTTP 接口。
|
|
73
93
|
|
|
74
|
-
##
|
|
94
|
+
## 接入自己的 Agent
|
|
75
95
|
|
|
76
|
-
|
|
96
|
+
任何语言,暴露 `POST /v1/chat/completions` 即可:
|
|
77
97
|
|
|
78
98
|
```python
|
|
79
99
|
@app.post("/v1/chat/completions")
|
|
@@ -83,38 +103,20 @@ def chat(request):
|
|
|
83
103
|
return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
|
|
84
104
|
```
|
|
85
105
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## 多 Agent 模式
|
|
89
|
-
|
|
90
|
-
同时接入多个 Agent,通过 `@` 前缀路由消息。支持 OpenAI 兼容格式和 [ACP (Agent Communication Protocol)](https://agentcommunicationprotocol.dev/) 两种协议:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
npx wechat-to-anything \
|
|
94
|
-
--agent codex=http://localhost:3001/v1 \
|
|
95
|
-
--agent gemini=http://localhost:3002/v1 \
|
|
96
|
-
--agent bee=acp://localhost:8000/chat \
|
|
97
|
-
--default codex
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
> `http://` → OpenAI 格式,`acp://` → ACP 协议,自动识别。
|
|
106
|
+
然后:`npx wechat-to-anything http://your-agent:8000/v1`
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| 消息 | 效果 |
|
|
105
|
-
|---|---|
|
|
106
|
-
| `你好` | 发给默认 Agent |
|
|
107
|
-
| `@codex 写个排序` | 路由到 Codex |
|
|
108
|
-
| `@gemini 审查代码` | 路由到 Gemini |
|
|
109
|
-
| `@bee 分析数据` | 路由到 ACP Agent |
|
|
110
|
-
| `@list` | 查看已注册的 Agent |
|
|
111
|
-
| `@切换 gemini` | 切换默认 Agent |
|
|
108
|
+
## 多媒体协议
|
|
112
109
|
|
|
113
|
-
|
|
110
|
+
Agent 回复中包含特定格式即可自动发送多媒体:
|
|
114
111
|
|
|
115
|
-
|
|
112
|
+
| 类型 | Agent 回复格式 | 说明 |
|
|
113
|
+
|------|--------------|------|
|
|
114
|
+
| 图片 | `` | 支持 URL、本地路径、data URI |
|
|
115
|
+
| 语音 | `[audio:路径或URL]` | MP3/WAV/OGG,需 `ffmpeg` + `pilk` |
|
|
116
|
+
| 视频 | `[video:路径或URL]` | 需 `ffmpeg` |
|
|
117
|
+
| 文件 | `[file:路径或URL]` | 任意文件类型 |
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
**图片接收**(微信 → Agent)遵循 [OpenAI Vision API](https://platform.openai.com/docs/guides/vision):
|
|
118
120
|
|
|
119
121
|
```json
|
|
120
122
|
{
|
|
@@ -128,35 +130,32 @@ npx wechat-to-anything \
|
|
|
128
130
|
}
|
|
129
131
|
```
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
**语音(Agent → 微信)**:回复中包含 `[audio:path 或 URL]` 自动发语音气泡。支持 MP3、WAV、OGG 等。需要 `ffmpeg` 和 `pip install pilk`。
|
|
133
|
+
> 示例:[image-test.mjs](examples/image-test.mjs) · [voice-test.mjs](examples/voice-test.mjs) · [video-test-local.mjs](examples/video-test-local.mjs) · [file-test.mjs](examples/file-test.mjs)
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
@app.post("/v1/chat/completions")
|
|
137
|
-
def chat(request):
|
|
138
|
-
audio_path = your_tts(message) # → /tmp/reply.mp3
|
|
139
|
-
reply = f"[audio:{audio_path}]\n这是文字版内容"
|
|
140
|
-
return {"choices": [{"message": {"role": "assistant", "content": reply}}]}
|
|
141
|
-
```
|
|
135
|
+
## 多 Agent 模式
|
|
142
136
|
|
|
143
|
-
|
|
137
|
+
同时接入多个 Agent,`@` 前缀路由。支持 OpenAI 格式和 [ACP 协议](https://agentcommunicationprotocol.dev/):
|
|
144
138
|
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
139
|
+
```bash
|
|
140
|
+
npx wechat-to-anything \
|
|
141
|
+
--agent codex=http://localhost:3001/v1 \
|
|
142
|
+
--agent gemini=http://localhost:3002/v1 \
|
|
143
|
+
--agent bee=acp://localhost:8000/chat \
|
|
144
|
+
--default codex
|
|
150
145
|
```
|
|
151
146
|
|
|
152
|
-
|
|
147
|
+
| 微信消息 | 效果 |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `你好` | 发给默认 Agent |
|
|
150
|
+
| `@codex 写个排序` | 路由到 Codex |
|
|
151
|
+
| `@gemini 审查代码` | 路由到 Gemini |
|
|
152
|
+
| `@list` | 查看所有 Agent |
|
|
153
|
+
| `@切换 gemini` | 切换默认 |
|
|
153
154
|
|
|
154
155
|
## 凭证
|
|
155
156
|
|
|
156
157
|
登录凭证保存在 `~/.wechat-to-anything/credentials.json`,删除即可重新登录。
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
160
159
|
## Star History
|
|
161
160
|
|
|
162
161
|
如果这个项目帮到了你,请给个 ⭐ Star,这是对我们最大的支持!
|
package/cli/agent-adapter.mjs
CHANGED
|
@@ -17,10 +17,10 @@ import { randomBytes } from "node:crypto";
|
|
|
17
17
|
/**
|
|
18
18
|
* 统一调用接口 — 根据 URL 自动选择适配器
|
|
19
19
|
*/
|
|
20
|
-
export async function callAgentAuto(url, messages) {
|
|
21
|
-
if (url.startsWith("acp://")) return callACP(url, messages);
|
|
20
|
+
export async function callAgentAuto(url, messages, userId) {
|
|
21
|
+
if (url.startsWith("acp://")) return callACP(url, messages, userId);
|
|
22
22
|
if (url.startsWith("cli://")) return callCLI(url, messages);
|
|
23
|
-
return callOpenAI(url, messages);
|
|
23
|
+
return callOpenAI(url, messages, userId);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -50,11 +50,11 @@ export async function checkAgent(url) {
|
|
|
50
50
|
|
|
51
51
|
// ========== OpenAI 适配器 ==========
|
|
52
52
|
|
|
53
|
-
async function callOpenAI(agentUrl, messages) {
|
|
53
|
+
async function callOpenAI(agentUrl, messages, userId) {
|
|
54
54
|
const res = await fetch(`${agentUrl}/chat/completions`, {
|
|
55
55
|
method: "POST",
|
|
56
56
|
headers: { "Content-Type": "application/json" },
|
|
57
|
-
body: JSON.stringify({ messages }),
|
|
57
|
+
body: JSON.stringify({ messages, user: userId || undefined }),
|
|
58
58
|
signal: AbortSignal.timeout(300_000),
|
|
59
59
|
});
|
|
60
60
|
if (!res.ok) {
|
|
@@ -74,7 +74,7 @@ function parseACPUrl(acpUrl) {
|
|
|
74
74
|
return { httpUrl: `http://${withoutScheme.slice(0, slashIdx)}`, agentName: withoutScheme.slice(slashIdx + 1) };
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
async function callACP(acpUrl, messages) {
|
|
77
|
+
async function callACP(acpUrl, messages, userId) {
|
|
78
78
|
const { httpUrl, agentName } = parseACPUrl(acpUrl);
|
|
79
79
|
const input = messages.map((msg) => {
|
|
80
80
|
if (typeof msg.content === "string") {
|
package/cli/bridge.mjs
CHANGED
|
@@ -325,7 +325,7 @@ export async function start(agents, defaultAgent) {
|
|
|
325
325
|
// 调用 Agent
|
|
326
326
|
try {
|
|
327
327
|
if (typing) await typing.onReplyStart();
|
|
328
|
-
const reply = await callAgentAuto(agentUrl, agentMessages);
|
|
328
|
+
const reply = await callAgentAuto(agentUrl, agentMessages, from);
|
|
329
329
|
if (typing) typing.onIdle();
|
|
330
330
|
const agentTag = multiMode ? `[${targetAgent}] ` : "";
|
|
331
331
|
|
package/cli/cdn.mjs
CHANGED
package/cli/weixin.mjs
CHANGED
|
@@ -286,8 +286,11 @@ export async function sendVoiceMessage(token, to, contextToken, audioBase64, dur
|
|
|
286
286
|
|
|
287
287
|
/**
|
|
288
288
|
* 发送文件消息(通过 CDN 引用)
|
|
289
|
+
* 格式参考微信原始 file_item: 44-char aes_key, 无 encrypt_type, 有 md5
|
|
289
290
|
*/
|
|
290
291
|
export async function sendFileMessage(token, to, contextToken, uploaded, fileName) {
|
|
292
|
+
// aes_key: hex string → UTF-8 bytes → base64 = 44 chars(微信格式)
|
|
293
|
+
const aesKeyB64 = Buffer.from(uploaded.aeskey).toString("base64");
|
|
291
294
|
await apiPost(
|
|
292
295
|
"ilink/bot/sendmessage",
|
|
293
296
|
{
|
|
@@ -302,10 +305,10 @@ export async function sendFileMessage(token, to, contextToken, uploaded, fileNam
|
|
|
302
305
|
file_item: {
|
|
303
306
|
media: {
|
|
304
307
|
encrypt_query_param: uploaded.downloadParam,
|
|
305
|
-
aes_key:
|
|
306
|
-
encrypt_type: 1,
|
|
308
|
+
aes_key: aesKeyB64,
|
|
307
309
|
},
|
|
308
310
|
file_name: fileName,
|
|
311
|
+
md5: uploaded.rawMd5 || "",
|
|
309
312
|
len: String(uploaded.fileSize),
|
|
310
313
|
},
|
|
311
314
|
}],
|
|
@@ -459,6 +462,7 @@ export function extractMedia(msg) {
|
|
|
459
462
|
}
|
|
460
463
|
// 文件
|
|
461
464
|
if (item.type === 4 && item.file_item?.media?.encrypt_query_param) {
|
|
465
|
+
|
|
462
466
|
return {
|
|
463
467
|
type: "file",
|
|
464
468
|
encryptQueryParam: item.file_item.media.encrypt_query_param,
|
package/docs/banner.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文件发送测试脚本
|
|
3
|
+
*
|
|
4
|
+
* 用法: node examples/file-test.mjs [文件路径]
|
|
5
|
+
*
|
|
6
|
+
* 通过 CDN 上传文件,发送到自己的微信(用于测试)。
|
|
7
|
+
* 需要先扫码登录获取 credentials。
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync } from "fs";
|
|
10
|
+
import { homedir, tmpdir } from "os";
|
|
11
|
+
import { join, basename } from "path";
|
|
12
|
+
|
|
13
|
+
const creds = JSON.parse(readFileSync(homedir() + "/.wechat-to-anything/credentials.json", "utf-8"));
|
|
14
|
+
|
|
15
|
+
// 测试文件:命令行指定或自动生成
|
|
16
|
+
let filePath = process.argv[2];
|
|
17
|
+
let fileName;
|
|
18
|
+
if (filePath) {
|
|
19
|
+
fileName = basename(filePath);
|
|
20
|
+
} else {
|
|
21
|
+
const { writeFileSync } = await import("fs");
|
|
22
|
+
filePath = join(tmpdir(), "wxta-test-file.txt");
|
|
23
|
+
writeFileSync(filePath, `Hello from wechat-to-anything!\n测试文件 ${new Date().toISOString()}\n`);
|
|
24
|
+
fileName = "wxta-test-file.txt";
|
|
25
|
+
console.log("未指定文件,已生成测试文件:", filePath);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { uploadToCdn } = await import("../cli/cdn.mjs");
|
|
29
|
+
const { getUpdates, sendFileMessage } = await import("../cli/weixin.mjs");
|
|
30
|
+
|
|
31
|
+
const msgs = await getUpdates(creds.token);
|
|
32
|
+
const ct = msgs?.context_token || "";
|
|
33
|
+
|
|
34
|
+
console.log("上传文件:", fileName);
|
|
35
|
+
const uploaded = await uploadToCdn(filePath, creds.userId, creds.token, 3);
|
|
36
|
+
console.log("✅ CDN 上传完成 | 大小:", uploaded.fileSize, "bytes | md5:", uploaded.rawMd5);
|
|
37
|
+
|
|
38
|
+
await sendFileMessage(creds.token, creds.userId, ct, uploaded, fileName);
|
|
39
|
+
console.log("✅ 发送成功!请检查微信");
|