wechat-bridge-opencode 0.1.2
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/.opencode/tools/send-wechat.ts +88 -0
- package/LICENSE +21 -0
- package/README.md +244 -0
- package/dist/bin/wechat-acp.d.ts +14 -0
- package/dist/bin/wechat-acp.d.ts.map +1 -0
- package/dist/bin/wechat-acp.js +284 -0
- package/dist/bin/wechat-acp.js.map +1 -0
- package/dist/bin/wechat-opencode.d.ts +14 -0
- package/dist/bin/wechat-opencode.d.ts.map +1 -0
- package/dist/bin/wechat-opencode.js +284 -0
- package/dist/bin/wechat-opencode.js.map +1 -0
- package/dist/package.json +60 -0
- package/dist/src/acp/agent-manager.d.ts +23 -0
- package/dist/src/acp/agent-manager.d.ts.map +1 -0
- package/dist/src/acp/agent-manager.js +134 -0
- package/dist/src/acp/agent-manager.js.map +1 -0
- package/dist/src/acp/client.d.ts +49 -0
- package/dist/src/acp/client.d.ts.map +1 -0
- package/dist/src/acp/client.js +219 -0
- package/dist/src/acp/client.js.map +1 -0
- package/dist/src/acp/opencode-sessions.d.ts +17 -0
- package/dist/src/acp/opencode-sessions.d.ts.map +1 -0
- package/dist/src/acp/opencode-sessions.js +59 -0
- package/dist/src/acp/opencode-sessions.js.map +1 -0
- package/dist/src/acp/session.d.ts +75 -0
- package/dist/src/acp/session.d.ts.map +1 -0
- package/dist/src/acp/session.js +273 -0
- package/dist/src/acp/session.js.map +1 -0
- package/dist/src/acp/workspace-manager.d.ts +48 -0
- package/dist/src/acp/workspace-manager.d.ts.map +1 -0
- package/dist/src/acp/workspace-manager.js +141 -0
- package/dist/src/acp/workspace-manager.js.map +1 -0
- package/dist/src/adapter/inbound.d.ts +10 -0
- package/dist/src/adapter/inbound.d.ts.map +1 -0
- package/dist/src/adapter/inbound.js +149 -0
- package/dist/src/adapter/inbound.js.map +1 -0
- package/dist/src/adapter/outbound.d.ts +9 -0
- package/dist/src/adapter/outbound.d.ts.map +1 -0
- package/dist/src/adapter/outbound.js +25 -0
- package/dist/src/adapter/outbound.js.map +1 -0
- package/dist/src/adapter/workspace-cmd.d.ts +53 -0
- package/dist/src/adapter/workspace-cmd.d.ts.map +1 -0
- package/dist/src/adapter/workspace-cmd.js +172 -0
- package/dist/src/adapter/workspace-cmd.js.map +1 -0
- package/dist/src/bridge.d.ts +42 -0
- package/dist/src/bridge.d.ts.map +1 -0
- package/dist/src/bridge.js +557 -0
- package/dist/src/bridge.js.map +1 -0
- package/dist/src/config.d.ts +63 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +88 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/weixin/api.d.ts +50 -0
- package/dist/src/weixin/api.d.ts.map +1 -0
- package/dist/src/weixin/api.js +87 -0
- package/dist/src/weixin/api.js.map +1 -0
- package/dist/src/weixin/auth.d.ts +20 -0
- package/dist/src/weixin/auth.d.ts.map +1 -0
- package/dist/src/weixin/auth.js +88 -0
- package/dist/src/weixin/auth.js.map +1 -0
- package/dist/src/weixin/media.d.ts +24 -0
- package/dist/src/weixin/media.d.ts.map +1 -0
- package/dist/src/weixin/media.js +91 -0
- package/dist/src/weixin/media.js.map +1 -0
- package/dist/src/weixin/monitor.d.ts +16 -0
- package/dist/src/weixin/monitor.d.ts.map +1 -0
- package/dist/src/weixin/monitor.js +111 -0
- package/dist/src/weixin/monitor.js.map +1 -0
- package/dist/src/weixin/send.d.ts +32 -0
- package/dist/src/weixin/send.d.ts.map +1 -0
- package/dist/src/weixin/send.js +193 -0
- package/dist/src/weixin/send.js.map +1 -0
- package/dist/src/weixin/types.d.ts +150 -0
- package/dist/src/weixin/types.d.ts.map +1 -0
- package/dist/src/weixin/types.js +33 -0
- package/dist/src/weixin/types.js.map +1 -0
- package/package.json +60 -0
- package/scripts/install-tool.mjs +14 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode custom tool: send files to WeChat.
|
|
3
|
+
*
|
|
4
|
+
* Place this file at:
|
|
5
|
+
* - Global: ~/.config/opencode/tools/send-wechat.ts
|
|
6
|
+
* - Project: .opencode/tools/send-wechat.ts
|
|
7
|
+
*
|
|
8
|
+
* Tool name: send-wechat
|
|
9
|
+
* Reads userId/sessionId from .wechat-bridge-state.json automatically.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { tool } from "@opencode-ai/plugin"
|
|
13
|
+
import path from "node:path"
|
|
14
|
+
import os from "node:os"
|
|
15
|
+
import fs from "node:fs"
|
|
16
|
+
|
|
17
|
+
const API_URL = "http://127.0.0.1:18792/send-wechat"
|
|
18
|
+
|
|
19
|
+
/** Load state from ~/.wechat-opencode/.wechat-bridge-state.json */
|
|
20
|
+
function loadState(): { lastUserId?: string; lastSessionId?: string } {
|
|
21
|
+
try {
|
|
22
|
+
const stateFile = path.join(os.homedir(), ".wechat-opencode", ".wechat-bridge-state.json")
|
|
23
|
+
if (fs.existsSync(stateFile)) {
|
|
24
|
+
return JSON.parse(fs.readFileSync(stateFile, "utf-8"))
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
// ignore
|
|
28
|
+
}
|
|
29
|
+
return {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default tool({
|
|
33
|
+
description: "Send a file to the last active WeChat user through the wechat-opencode bridge. Use this to share files, images, PDFs, etc. with the WeChat contact.",
|
|
34
|
+
args: {
|
|
35
|
+
filePath: tool.schema.string().describe("Absolute path to the file to send (e.g., F:\\report.pdf)"),
|
|
36
|
+
},
|
|
37
|
+
async execute(args) {
|
|
38
|
+
const absolutePath = path.resolve(args.filePath)
|
|
39
|
+
|
|
40
|
+
// Validate file exists
|
|
41
|
+
try {
|
|
42
|
+
if (!fs.existsSync(absolutePath)) {
|
|
43
|
+
return `Error: File not found: ${absolutePath}`
|
|
44
|
+
}
|
|
45
|
+
const stat = fs.statSync(absolutePath)
|
|
46
|
+
if (!stat.isFile()) {
|
|
47
|
+
return `Error: Not a file: ${absolutePath}`
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
return `Error accessing file: ${err instanceof Error ? err.message : String(err)}`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Load userId/sessionId from state file
|
|
54
|
+
const state = loadState()
|
|
55
|
+
if (!state.lastUserId && !state.lastSessionId) {
|
|
56
|
+
return "Error: No active WeChat session found. Has anyone messaged you recently? The bridge must be running and have received at least one message."
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const fileName = path.basename(absolutePath)
|
|
60
|
+
|
|
61
|
+
// Call the bridge API
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(API_URL, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
filePath: absolutePath,
|
|
68
|
+
userId: state.lastUserId,
|
|
69
|
+
sessionId: state.lastSessionId,
|
|
70
|
+
}),
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const result = await response.json()
|
|
74
|
+
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
return `Error: ${result.error || `HTTP ${response.status}`}`
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `Successfully sent "${result.fileName || fileName}" to WeChat user ${state.lastUserId}!`
|
|
80
|
+
} catch (err) {
|
|
81
|
+
const msg = err instanceof Error ? err.message : String(err)
|
|
82
|
+
if (msg.includes("ECONNREFUSED")) {
|
|
83
|
+
return `Error: Cannot connect to wechat-opencode bridge at 127.0.0.1:18792. Is the bridge running?`
|
|
84
|
+
}
|
|
85
|
+
return `Error: ${msg}`
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
})
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jun Han
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# WeChat OpenCode
|
|
2
|
+
|
|
3
|
+
Bridge WeChat direct messages to opencode.
|
|
4
|
+
|
|
5
|
+
`wechat-bridge-opencode` (aka `wbo`) logs in with the WeChat iLink bot API, polls incoming 1:1 messages, forwards them to opencode over stdio, and sends the agent reply back to WeChat.
|
|
6
|
+
|
|
7
|
+
<img src="./resources/screenshot.jpg" alt="wbo screenshot" width="400" />
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- WeChat QR login with terminal QR rendering
|
|
12
|
+
- One ACP agent session per WeChat user
|
|
13
|
+
- Built-in ACP agent presets for common CLIs
|
|
14
|
+
- Custom raw agent command support
|
|
15
|
+
- Auto-allow permission requests from the agent
|
|
16
|
+
- Direct message only; group chats are ignored
|
|
17
|
+
- Background daemon mode
|
|
18
|
+
- File sending: agent can send files/images back to WeChat via the `send-wechat` tool
|
|
19
|
+
- Automatic model config forwarding for opencode agents
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Node.js 20+
|
|
24
|
+
- A WeChat environment that can use the iLink bot API
|
|
25
|
+
- [OpenCode](https://github.com/anomalyco/opencode) installed locally or via `npx`
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx wbo --agent opencode
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That's it — `wbo` will be available globally after first run, and the `send-wechat` tool is automatically installed to `~/.config/opencode/tools/send-wechat.ts`.
|
|
34
|
+
|
|
35
|
+
To install globally:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g wechat-bridge-opencode
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
> **Important**: Run the bridge from your **working directory** (e.g. your project folder), **not** from an arbitrary install directory. Running from the install directory may cause conflicts.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd /path/to/your/workdir
|
|
47
|
+
wbo --agent opencode
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or with a custom agent command:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
wbo --agent "npx my-agent --acp"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
On first run, the bridge will:
|
|
57
|
+
|
|
58
|
+
1. Start WeChat QR login
|
|
59
|
+
2. Render a QR code in the terminal
|
|
60
|
+
3. Save the login token under `~/.wechat-bridge-opencode`
|
|
61
|
+
4. Begin polling direct messages
|
|
62
|
+
|
|
63
|
+
## Built-in Agent Presets
|
|
64
|
+
|
|
65
|
+
List the bundled presets:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
wbo agents
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Current presets:
|
|
72
|
+
|
|
73
|
+
- `opencode`
|
|
74
|
+
|
|
75
|
+
These presets resolve to concrete `command + args` pairs internally, so users do not need to type long `npx ...` commands.
|
|
76
|
+
|
|
77
|
+
## CLI Usage
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
wbo --agent <preset|command> [options]
|
|
81
|
+
wbo agents
|
|
82
|
+
wbo stop
|
|
83
|
+
wbo status
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Options:
|
|
87
|
+
|
|
88
|
+
- `--agent <value>`: built-in preset name or raw agent command
|
|
89
|
+
- `--cwd <dir>`: working directory for the agent process
|
|
90
|
+
- `--login`: force QR re-login and replace the saved token
|
|
91
|
+
- `--daemon`: run in background after startup
|
|
92
|
+
- `--config <file>`: load JSON config file
|
|
93
|
+
- `--idle-timeout <minutes>`: session idle timeout, default `1440` (use `0` for unlimited)
|
|
94
|
+
- `--max-sessions <count>`: maximum concurrent user sessions, default `10`
|
|
95
|
+
- `--show-thoughts`: forward agent thinking to WeChat (default: off)
|
|
96
|
+
- `-h, --help`: show help
|
|
97
|
+
|
|
98
|
+
Examples:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
cd /path/to/your/workdir
|
|
102
|
+
wbo --agent opencode
|
|
103
|
+
wbo --agent opencode --cwd D:\code\project
|
|
104
|
+
wbo --agent "npx opencode-ai acp"
|
|
105
|
+
wbo --agent opencode --daemon
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Configuration File
|
|
109
|
+
|
|
110
|
+
You can provide a JSON config file with `--config`.
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"agent": {
|
|
117
|
+
"preset": "opencode",
|
|
118
|
+
"cwd": "D:/code/project"
|
|
119
|
+
},
|
|
120
|
+
"session": {
|
|
121
|
+
"idleTimeoutMs": 86400000,
|
|
122
|
+
"maxConcurrentUsers": 10
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
You can also override or add agent presets:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"agent": {
|
|
132
|
+
"preset": "my-agent"
|
|
133
|
+
},
|
|
134
|
+
"agents": {
|
|
135
|
+
"my-agent": {
|
|
136
|
+
"label": "My Agent",
|
|
137
|
+
"description": "Internal team agent",
|
|
138
|
+
"command": "npx",
|
|
139
|
+
"args": ["my-agent-cli", "--acp"]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Runtime Behavior
|
|
146
|
+
|
|
147
|
+
- Each WeChat user gets a dedicated ACP session and subprocess.
|
|
148
|
+
- Messages are processed serially per user.
|
|
149
|
+
- Replies are formatted for WeChat before sending.
|
|
150
|
+
- Typing indicators are sent when supported by the WeChat API.
|
|
151
|
+
- Sessions are cleaned up after inactivity (set `idleTimeoutMs` to `0` to disable idle cleanup).
|
|
152
|
+
- Switching workspace or session kills the old agent and spawns a new one immediately.
|
|
153
|
+
- OpenCode session history is resumed via `unstable_resumeSession()` when switching to an existing session.
|
|
154
|
+
|
|
155
|
+
## WeChat Commands
|
|
156
|
+
|
|
157
|
+
Users can manage workspaces and sessions directly from WeChat:
|
|
158
|
+
|
|
159
|
+
### Workspace (`/workspace` or `/ws`)
|
|
160
|
+
|
|
161
|
+
| Command | Description |
|
|
162
|
+
|---------|-------------|
|
|
163
|
+
| `/workspace list` | List all directories from OpenCode sessions |
|
|
164
|
+
| `/workspace switch <n\|path>` | Switch to directory by index or path |
|
|
165
|
+
| `/workspace add /path` | Add directory (creates if not exists) |
|
|
166
|
+
| `/workspace status` | Show current directory |
|
|
167
|
+
|
|
168
|
+
### Session (`/session` or `/s`)
|
|
169
|
+
|
|
170
|
+
| Command | Description |
|
|
171
|
+
|---------|-------------|
|
|
172
|
+
| `/session list` | List recent 10 sessions with directory |
|
|
173
|
+
| `/session switch <n\|slug>` | Switch to session by index or slug |
|
|
174
|
+
| `/session new` | Restart session (clear context) |
|
|
175
|
+
| `/session status` | Show current session info |
|
|
176
|
+
|
|
177
|
+
### Help
|
|
178
|
+
|
|
179
|
+
| Command | Description |
|
|
180
|
+
|---------|-------------|
|
|
181
|
+
| `/help` | Show all available commands |
|
|
182
|
+
|
|
183
|
+
## Storage
|
|
184
|
+
|
|
185
|
+
By default, runtime files are stored under:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
~/.wechat-bridge-opencode
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This directory is used for:
|
|
192
|
+
|
|
193
|
+
- saved login token
|
|
194
|
+
- auth tokens
|
|
195
|
+
- tempfile (downloaded media)
|
|
196
|
+
- daemon pid file
|
|
197
|
+
- daemon log file
|
|
198
|
+
- sync state
|
|
199
|
+
- bridge state (`.wechat-bridge-state.json` — tracks last active user/session for the `send-wechat` tool)
|
|
200
|
+
|
|
201
|
+
## Custom Tool: send-wechat
|
|
202
|
+
|
|
203
|
+
The `send-wechat` tool is automatically installed to `~/.config/opencode/tools/send-wechat.ts`.
|
|
204
|
+
|
|
205
|
+
This tool is available to opencode agents and lets them send files back to WeChat:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
send-wechat(filePath: string)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The tool reads `~/.wechat-bridge-opencode/.wechat-bridge-state.json` to automatically determine the target user and session. The agent only needs to provide the file path.
|
|
212
|
+
|
|
213
|
+
## Current Limitations
|
|
214
|
+
|
|
215
|
+
- Direct messages only; group chats are ignored
|
|
216
|
+
- Permission requests are auto-approved
|
|
217
|
+
- Some preset agents may require separate authentication before they can respond successfully
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
Clone and build locally:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
git clone https://github.com/pan17/wechat-bridge-opencode.git
|
|
225
|
+
cd wechat-bridge-opencode
|
|
226
|
+
npm install
|
|
227
|
+
npm run build
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Run the CLI locally:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
node dist/bin/wechat-opencode.js --help # or simply: wbo --help
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Watch mode:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npm run dev
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wechat-acp CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* wechat-acp --agent "claude code"
|
|
7
|
+
* wechat-acp --agent "gemini" --cwd /path/to/project
|
|
8
|
+
* wechat-acp --agent "npx tsx ./agent.ts" --login
|
|
9
|
+
* wechat-acp --agent "claude code" --daemon
|
|
10
|
+
* wechat-acp stop
|
|
11
|
+
* wechat-acp status
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=wechat-acp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-acp.d.ts","sourceRoot":"","sources":["../../bin/wechat-acp.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wechat-acp CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* wechat-acp --agent "claude code"
|
|
7
|
+
* wechat-acp --agent "gemini" --cwd /path/to/project
|
|
8
|
+
* wechat-acp --agent "npx tsx ./agent.ts" --login
|
|
9
|
+
* wechat-acp --agent "claude code" --daemon
|
|
10
|
+
* wechat-acp stop
|
|
11
|
+
* wechat-acp status
|
|
12
|
+
*/
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { spawn } from "node:child_process";
|
|
16
|
+
import qrcodeTerminal from "qrcode-terminal";
|
|
17
|
+
import { WeChatAcpBridge } from "../src/bridge.js";
|
|
18
|
+
import { defaultConfig, listBuiltInAgents, resolveAgentSelection, } from "../src/config.js";
|
|
19
|
+
function usage() {
|
|
20
|
+
const presets = listBuiltInAgents()
|
|
21
|
+
.map(({ id }) => id)
|
|
22
|
+
.join(", ");
|
|
23
|
+
console.log(`
|
|
24
|
+
wechat-acp — Bridge WeChat to any ACP-compatible AI agent
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
wechat-acp --agent <preset|command> [options]
|
|
28
|
+
wechat-acp agents List built-in agent presets
|
|
29
|
+
wechat-acp stop Stop a running daemon
|
|
30
|
+
wechat-acp status Check daemon status
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
--agent <value> Built-in preset name or raw agent command
|
|
34
|
+
Presets: ${presets}
|
|
35
|
+
Examples: "copilot", "claude", "npx tsx ./agent.ts"
|
|
36
|
+
--cwd <dir> Working directory for agent (default: current dir)
|
|
37
|
+
--login Force re-login (new QR code)
|
|
38
|
+
--daemon Run in background after login
|
|
39
|
+
--config <file> Config file path (JSON)
|
|
40
|
+
--idle-timeout <m> Session idle timeout in minutes (default: 1440)
|
|
41
|
+
Use 0 to disable idle cleanup
|
|
42
|
+
--max-sessions <n> Max concurrent user sessions (default: 10)
|
|
43
|
+
--show-thoughts Forward agent thinking to WeChat (default: off)
|
|
44
|
+
-v, --verbose Verbose logging
|
|
45
|
+
-h, --help Show this help
|
|
46
|
+
`);
|
|
47
|
+
}
|
|
48
|
+
function parseArgs(argv) {
|
|
49
|
+
const result = {
|
|
50
|
+
forceLogin: false,
|
|
51
|
+
daemon: false,
|
|
52
|
+
showThoughts: false,
|
|
53
|
+
verbose: false,
|
|
54
|
+
help: false,
|
|
55
|
+
};
|
|
56
|
+
const args = argv.slice(2);
|
|
57
|
+
let i = 0;
|
|
58
|
+
// Check for subcommand
|
|
59
|
+
if (args[0] && !args[0].startsWith("-")) {
|
|
60
|
+
result.command = args[0];
|
|
61
|
+
i = 1;
|
|
62
|
+
}
|
|
63
|
+
while (i < args.length) {
|
|
64
|
+
const arg = args[i];
|
|
65
|
+
switch (arg) {
|
|
66
|
+
case "--agent":
|
|
67
|
+
result.agent = args[++i];
|
|
68
|
+
break;
|
|
69
|
+
case "--cwd":
|
|
70
|
+
result.cwd = args[++i];
|
|
71
|
+
break;
|
|
72
|
+
case "--login":
|
|
73
|
+
result.forceLogin = true;
|
|
74
|
+
break;
|
|
75
|
+
case "--daemon":
|
|
76
|
+
result.daemon = true;
|
|
77
|
+
break;
|
|
78
|
+
case "--config":
|
|
79
|
+
result.configFile = args[++i];
|
|
80
|
+
break;
|
|
81
|
+
case "--idle-timeout":
|
|
82
|
+
result.idleTimeout = parseInt(args[++i], 10);
|
|
83
|
+
break;
|
|
84
|
+
case "--max-sessions":
|
|
85
|
+
result.maxSessions = parseInt(args[++i], 10);
|
|
86
|
+
break;
|
|
87
|
+
case "--show-thoughts":
|
|
88
|
+
result.showThoughts = true;
|
|
89
|
+
break;
|
|
90
|
+
case "-v":
|
|
91
|
+
case "--verbose":
|
|
92
|
+
result.verbose = true;
|
|
93
|
+
break;
|
|
94
|
+
case "-h":
|
|
95
|
+
case "--help":
|
|
96
|
+
result.help = true;
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
if (arg?.startsWith("-")) {
|
|
100
|
+
console.error(`Unknown option: ${arg}`);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
i++;
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
function loadConfigFile(filePath) {
|
|
109
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
110
|
+
return JSON.parse(content);
|
|
111
|
+
}
|
|
112
|
+
function handleAgents(config) {
|
|
113
|
+
console.log("Built-in ACP agent presets:\n");
|
|
114
|
+
for (const { id, preset } of listBuiltInAgents(config.agents)) {
|
|
115
|
+
const commandLine = [preset.command, ...preset.args].join(" ");
|
|
116
|
+
console.log(`${id.padEnd(10)} ${commandLine}`);
|
|
117
|
+
if (preset.description) {
|
|
118
|
+
console.log(` ${preset.description}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function handleStop(config) {
|
|
123
|
+
const pidFile = config.daemon.pidFile;
|
|
124
|
+
if (!fs.existsSync(pidFile)) {
|
|
125
|
+
console.log("No daemon running (no PID file found)");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
129
|
+
try {
|
|
130
|
+
process.kill(pid, "SIGTERM");
|
|
131
|
+
fs.unlinkSync(pidFile);
|
|
132
|
+
console.log(`Stopped daemon (PID ${pid})`);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err.code === "ESRCH") {
|
|
136
|
+
fs.unlinkSync(pidFile);
|
|
137
|
+
console.log(`Daemon not running (stale PID ${pid}), cleaned up`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
console.error(`Failed to stop daemon: ${String(err)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function handleStatus(config) {
|
|
145
|
+
const pidFile = config.daemon.pidFile;
|
|
146
|
+
if (!fs.existsSync(pidFile)) {
|
|
147
|
+
console.log("Not running");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
151
|
+
try {
|
|
152
|
+
process.kill(pid, 0); // test if process exists
|
|
153
|
+
console.log(`Running (PID ${pid})`);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
console.log(`Not running (stale PID ${pid})`);
|
|
157
|
+
fs.unlinkSync(pidFile);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function daemonize(config) {
|
|
161
|
+
const logFile = config.daemon.logFile;
|
|
162
|
+
const pidFile = config.daemon.pidFile;
|
|
163
|
+
fs.mkdirSync(path.dirname(logFile), { recursive: true });
|
|
164
|
+
fs.mkdirSync(path.dirname(pidFile), { recursive: true });
|
|
165
|
+
const out = fs.openSync(logFile, "a");
|
|
166
|
+
const err = fs.openSync(logFile, "a");
|
|
167
|
+
// Re-run ourselves with --no-daemon (internal flag) as a detached process
|
|
168
|
+
const args = process.argv.slice(1).filter((a) => a !== "--daemon");
|
|
169
|
+
const child = spawn(process.execPath, args, {
|
|
170
|
+
detached: true,
|
|
171
|
+
stdio: ["ignore", out, err],
|
|
172
|
+
env: { ...process.env, WECHAT_ACP_DAEMON: "1" },
|
|
173
|
+
});
|
|
174
|
+
child.unref();
|
|
175
|
+
fs.writeFileSync(pidFile, String(child.pid), "utf-8");
|
|
176
|
+
console.log(`Daemon started (PID ${child.pid})`);
|
|
177
|
+
console.log(`Logs: ${logFile}`);
|
|
178
|
+
console.log(`PID file: ${pidFile}`);
|
|
179
|
+
process.exit(0);
|
|
180
|
+
}
|
|
181
|
+
function renderQrInTerminal(url) {
|
|
182
|
+
qrcodeTerminal.generate(url, { small: true }, (qr) => {
|
|
183
|
+
console.log(qr);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
async function main() {
|
|
187
|
+
const args = parseArgs(process.argv);
|
|
188
|
+
if (args.help) {
|
|
189
|
+
usage();
|
|
190
|
+
process.exit(0);
|
|
191
|
+
}
|
|
192
|
+
const config = defaultConfig();
|
|
193
|
+
// Load config file if specified
|
|
194
|
+
if (args.configFile) {
|
|
195
|
+
const fileConfig = loadConfigFile(args.configFile);
|
|
196
|
+
Object.assign(config.wechat, fileConfig.wechat ?? {});
|
|
197
|
+
Object.assign(config.agent, fileConfig.agent ?? {});
|
|
198
|
+
Object.assign(config.agents, fileConfig.agents ?? {});
|
|
199
|
+
Object.assign(config.session, fileConfig.session ?? {});
|
|
200
|
+
Object.assign(config.daemon, fileConfig.daemon ?? {});
|
|
201
|
+
Object.assign(config.storage, fileConfig.storage ?? {});
|
|
202
|
+
}
|
|
203
|
+
// Handle subcommands
|
|
204
|
+
if (args.command === "agents") {
|
|
205
|
+
handleAgents(config);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (args.command === "stop") {
|
|
209
|
+
handleStop(config);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (args.command === "status") {
|
|
213
|
+
handleStatus(config);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const agentSelection = args.agent ?? config.agent.preset;
|
|
217
|
+
// Require preset or raw command
|
|
218
|
+
if (!agentSelection && !config.agent.command) {
|
|
219
|
+
console.error("Error: --agent is required\n");
|
|
220
|
+
usage();
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
if (agentSelection) {
|
|
224
|
+
const resolvedAgent = resolveAgentSelection(agentSelection, config.agents);
|
|
225
|
+
config.agent.preset = resolvedAgent.id;
|
|
226
|
+
config.agent.command = resolvedAgent.command;
|
|
227
|
+
config.agent.args = resolvedAgent.args;
|
|
228
|
+
if (resolvedAgent.env) {
|
|
229
|
+
config.agent.env = { ...(config.agent.env ?? {}), ...resolvedAgent.env };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (args.cwd)
|
|
233
|
+
config.agent.cwd = path.resolve(args.cwd);
|
|
234
|
+
if (args.idleTimeout !== undefined) {
|
|
235
|
+
if (!Number.isFinite(args.idleTimeout) || args.idleTimeout < 0) {
|
|
236
|
+
console.error("Error: invalid --idle-timeout value");
|
|
237
|
+
console.error('Use a non-negative integer minute value, where "0" means unlimited.');
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
config.session.idleTimeoutMs = args.idleTimeout * 60_000;
|
|
241
|
+
}
|
|
242
|
+
if (args.maxSessions)
|
|
243
|
+
config.session.maxConcurrentUsers = args.maxSessions;
|
|
244
|
+
if (args.showThoughts)
|
|
245
|
+
config.agent.showThoughts = true;
|
|
246
|
+
config.daemon.enabled = args.daemon;
|
|
247
|
+
// Handle daemon mode
|
|
248
|
+
if (args.daemon && !process.env.WECHAT_ACP_DAEMON) {
|
|
249
|
+
daemonize(config);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Create and start bridge
|
|
253
|
+
const bridge = new WeChatAcpBridge(config, (msg) => {
|
|
254
|
+
const ts = new Date().toISOString().substring(11, 19);
|
|
255
|
+
console.log(`[${ts}] ${msg}`);
|
|
256
|
+
});
|
|
257
|
+
// Handle graceful shutdown
|
|
258
|
+
const shutdown = async () => {
|
|
259
|
+
await bridge.stop();
|
|
260
|
+
process.exit(0);
|
|
261
|
+
};
|
|
262
|
+
process.on("SIGINT", () => void shutdown());
|
|
263
|
+
process.on("SIGTERM", () => void shutdown());
|
|
264
|
+
try {
|
|
265
|
+
await bridge.start({
|
|
266
|
+
forceLogin: args.forceLogin,
|
|
267
|
+
renderQrUrl: renderQrInTerminal,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
if (err.message === "aborted") {
|
|
272
|
+
// Normal shutdown
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
console.error(`Fatal: ${String(err)}`);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
main().catch((err) => {
|
|
281
|
+
console.error(`Fatal: ${String(err)}`);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
});
|
|
284
|
+
//# sourceMappingURL=wechat-acp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-acp.js","sourceRoot":"","sources":["../../bin/wechat-acp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wechat-opencode CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* wechat-opencode --agent "claude code"
|
|
7
|
+
* wechat-opencode --agent "gemini" --cwd /path/to/project
|
|
8
|
+
* wechat-opencode --agent "npx tsx ./agent.ts" --login
|
|
9
|
+
* wechat-opencode --agent "claude code" --daemon
|
|
10
|
+
* wechat-opencode stop
|
|
11
|
+
* wechat-opencode status
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=wechat-opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wechat-opencode.d.ts","sourceRoot":"","sources":["../../bin/wechat-opencode.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG"}
|