Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,45 @@ npm install -g @zed-industries/codex-acp
npx weixin-acp start -- codex-acp
```

### 在同一个微信会话里切换 Claude / Codex

如果你希望在手机上直接切换后端,而不是为每个后端单独启动一个 bot,可以使用 `router config` 模式:

```bash
# 安装两个 ACP agent
npm install -g @zed-industries/claude-agent-acp @zed-industries/codex-acp

# 使用多后端路由启动
npx weixin-acp start --router-config ./packages/agent-acp/router.example.json
```
Comment on lines +51 to +57
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example uses ./packages/agent-acp/router.example.json, which only exists when running from this monorepo checkout. For users following the README via npx weixin-acp ..., that path won’t exist. Consider adjusting the docs to instruct users to create their own router.json (and optionally reference the example file on GitHub) rather than pointing to a workspace-relative path.

Copilot uses AI. Check for mistakes.

示例配置文件:

```json
{
"defaultBackend": "claude",
"backends": {
"claude": {
"command": "claude-agent-acp"
},
"codex": {
"command": "codex-acp"
}
}
}
```

启动后,可以在微信里直接发送:

- `/claude`:切换当前会话默认后端到 Claude
- `/codex`:切换当前会话默认后端到 Codex
- `/claude 解释这个错误`:本条消息直接走 Claude,并切换默认后端
- `/codex 帮我改这段代码`:本条消息直接走 Codex,并切换默认后端
- `/mode`:查看当前默认后端和可用后端
- `/mode claude` / `/mode codex`:只切换默认后端,不发送问题

这个默认后端会按微信会话持久化保存,重启桥接进程后仍然生效。

### kimi-cli

```bash
Expand Down
53 changes: 53 additions & 0 deletions packages/agent-acp/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#!/usr/bin/env node

import fs from "node:fs";
import path from "node:path";

/**
* WeChat + ACP (Agent Client Protocol) adapter.
*
* Usage:
* npx weixin-acp login # QR-code login
* npx weixin-acp start --router-config file.json # Start bot with multi-backend router
* npx weixin-acp start -- <command> [args...] # Start bot
*
* Examples:
Expand All @@ -15,9 +19,27 @@
import { login, start } from "weixin-agent-sdk";

import { AcpAgent } from "./src/acp-agent.js";
import type { AcpRouterConfig } from "./src/types.js";

const command = process.argv[2];

function resolveRouterConfigPath(input: string): string {
return path.isAbsolute(input) ? input : path.resolve(process.cwd(), input);
}

function loadRouterConfig(configPath: string): AcpRouterConfig {
const resolvedPath = resolveRouterConfigPath(configPath);
const raw = fs.readFileSync(resolvedPath, "utf8");
const parsed = JSON.parse(raw) as AcpRouterConfig;
if (!parsed.defaultBackend?.trim()) {
throw new Error("router config 缺少 defaultBackend");
}
if (!parsed.backends || Object.keys(parsed.backends).length === 0) {
throw new Error("router config 缺少 backends");
}
return parsed;
}

async function main() {
switch (command) {
case "login": {
Expand All @@ -26,10 +48,39 @@ async function main() {
}

case "start": {
const routerArgIndex = process.argv.indexOf("--router-config");
if (routerArgIndex !== -1) {
const configPath = process.argv[routerArgIndex + 1];
if (!configPath) {
console.error("错误: --router-config 后必须跟 JSON 文件路径");
process.exit(1);
}

const agent = new AcpAgent({
command: "",
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In router-config mode the CLI constructs new AcpAgent({ command: "", router: ... }). If the router config fails to load or router mode is later refactored, an empty command could lead to confusing spawn errors. This will also remain necessary as long as the type requires command even in router mode. Consider updating the options typing/API so router mode doesn’t need a placeholder command, and update this construction accordingly.

Suggested change
command: "",
// In router-config mode, no external command is spawned; this placeholder satisfies the type.
command: "__ROUTER_MODE_NO_COMMAND__",

Copilot uses AI. Check for mistakes.
router: loadRouterConfig(configPath),
});

const ac = new AbortController();
process.on("SIGINT", () => {
console.log("\n正在停止...");
agent.dispose();
ac.abort();
});
process.on("SIGTERM", () => {
agent.dispose();
ac.abort();
});

await start(agent, { abortSignal: ac.signal });
break;
}

const ddIndex = process.argv.indexOf("--");
if (ddIndex === -1 || ddIndex + 1 >= process.argv.length) {
console.error("错误: 请在 -- 后指定 ACP agent 启动命令");
console.error("示例: npx weixin-acp start -- codex-acp");
console.error("或: npx weixin-acp start --router-config ./router.json");
process.exit(1);
}

Expand Down Expand Up @@ -61,9 +112,11 @@ async function main() {

用法:
npx weixin-acp login 扫码登录微信
npx weixin-acp start --router-config file.json 启动多后端路由
npx weixin-acp start -- <command> [args...] 启动 bot

示例:
npx weixin-acp start --router-config ./router.json
npx weixin-acp start -- codex-acp
npx weixin-acp start -- node ./my-agent.js`);
break;
Expand Down
11 changes: 11 additions & 0 deletions packages/agent-acp/router.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"defaultBackend": "claude",
"backends": {
"claude": {
"command": "claude-agent-acp"
},
"codex": {
"command": "codex-acp"
}
}
}
Loading
Loading