weacpx 0.4.4 → 0.4.6
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.md +42 -16
- package/dist/bridge/bridge-main.js +17 -27
- package/dist/cli.js +999 -551
- package/dist/orchestration/orchestration-types.d.ts +12 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## 这是什么
|
|
13
13
|
|
|
14
|
-
`weacpx` 是一个可以通过微信、飞书或元宝直接控制 Codex / Claude Code / Gemini / OpenCode 的工具。它把聊天消息通过 `acpx` 连接到 Agent CLI 会话上,让你直接在手机里:
|
|
14
|
+
`weacpx` 是一个可以通过微信、飞书或元宝直接控制 Codex / Claude Code / Gemini / OpenCode 等 ACP Agent 的工具。它把聊天消息通过 `acpx` 连接到 Agent CLI 会话上,让你直接在手机里:
|
|
15
15
|
|
|
16
16
|
- 新建和切换会话
|
|
17
17
|
- 让 Agent 继续在指定项目目录里工作
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
开始前,你至少需要:
|
|
35
35
|
|
|
36
36
|
- Node.js 22+ 或 Bun
|
|
37
|
-
- 已可用的 Codex / Claude Code / Gemini / OpenCode
|
|
37
|
+
- 已可用的 Codex / Claude Code / Gemini / OpenCode 等你要使用的 Agent CLI
|
|
38
38
|
- 一台装了微信、飞书或元宝的手机
|
|
39
39
|
|
|
40
40
|
> 微信频道基于 `weixin-agent-sdk` 工作,飞书频道使用飞书自建应用凭据,元宝频道使用 `appKey` / `appSecret`;底层 Agent 会话由 `acpx` 驱动。正常情况下,你不需要额外全局安装 `acpx`。
|
|
@@ -169,13 +169,16 @@ weacpx restart
|
|
|
169
169
|
| `weacpx status` | 查看后台状态、PID、配置路径、日志路径 |
|
|
170
170
|
| `weacpx stop` | 停止后台实例 |
|
|
171
171
|
| `weacpx restart` | 重启后台实例,让频道配置变更生效 |
|
|
172
|
-
| `weacpx update [--all
|
|
172
|
+
| `weacpx update [--all\|<name>]` | 检查并更新 weacpx 与已安装插件;安装了插件时会交互式选择更新项 |
|
|
173
173
|
| `weacpx channel list` | 查看已配置的消息频道 |
|
|
174
174
|
| `weacpx plugin known` | 查看官方插件清单(飞书/元宝包名) |
|
|
175
175
|
| `weacpx plugin add @ganglion/weacpx-channel-feishu && weacpx channel add feishu` | 安装并添加飞书频道,会提示输入飞书应用凭据 |
|
|
176
176
|
| `weacpx plugin add @ganglion/weacpx-channel-yuanbao && weacpx channel add yuanbao` | 安装并添加元宝频道,会提示输入元宝 appKey/appSecret |
|
|
177
177
|
| `weacpx doctor` | 运行环境诊断 |
|
|
178
178
|
| `weacpx version` | 查看当前版本 |
|
|
179
|
+
| `weacpx agent list` | 查看本机已注册的 agent |
|
|
180
|
+
| `weacpx agent add <name>` | 从内置模板添加 agent;已存在且配置不同的同名 agent 不会被覆盖 |
|
|
181
|
+
| `weacpx agent rm <name>` | 删除 agent |
|
|
179
182
|
| `weacpx workspace list` | 查看本机已注册的 workspace |
|
|
180
183
|
| `weacpx workspace add [name]` | 把当前目录注册成 workspace;不传 `name` 时使用当前目录名 |
|
|
181
184
|
| `weacpx workspace rm <name>` | 删除 workspace |
|
|
@@ -223,6 +226,26 @@ weacpx ws rm frontend
|
|
|
223
226
|
|
|
224
227
|
注意:`workspace add` 总是注册**当前终端所在目录**;如果不传名称,会用当前目录名作为 workspace 名称。
|
|
225
228
|
|
|
229
|
+
### `agent` CLI 怎么用
|
|
230
|
+
|
|
231
|
+
`weacpx agent` 用来在电脑本机维护 `~/.weacpx/config.json` 里的 `agents` 配置;`agents` 是同等别名。
|
|
232
|
+
|
|
233
|
+
| 命令 | 说明 |
|
|
234
|
+
|------|------|
|
|
235
|
+
| `weacpx agent list` | 列出已注册的 agent |
|
|
236
|
+
| `weacpx agent templates` | 列出可添加的内置模板 |
|
|
237
|
+
| `weacpx agent add <name>` | 从内置模板添加 agent,例如 `kimi`、`opencode` |
|
|
238
|
+
| `weacpx agent rm <name>` | 删除指定 agent |
|
|
239
|
+
|
|
240
|
+
常见用法:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
weacpx agent templates
|
|
244
|
+
weacpx agent add kimi
|
|
245
|
+
weacpx agents list
|
|
246
|
+
weacpx agent rm kimi
|
|
247
|
+
```
|
|
248
|
+
|
|
226
249
|
### `doctor` 怎么用
|
|
227
250
|
|
|
228
251
|
```bash
|
|
@@ -245,9 +268,7 @@ weacpx doctor --smoke --agent codex --workspace backend
|
|
|
245
268
|
|
|
246
269
|
### Agent 管理
|
|
247
270
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
可以使用 `/agent add opencode` 添加你所需要的 agents。
|
|
271
|
+
默认配置通常已包含 `codex` 与 `claude`。如果你要使用其它 acpx 支持的 agent,可以先用 `/agent add <name>` 从内置模板添加。
|
|
251
272
|
|
|
252
273
|
| 命令 | 说明 |
|
|
253
274
|
|------|------|
|
|
@@ -256,6 +277,16 @@ weacpx doctor --smoke --agent codex --workspace backend
|
|
|
256
277
|
| `/agent add opencode` | 添加 `OpenCode` Agent |
|
|
257
278
|
| `/agent rm <name>` | 删除 agent |
|
|
258
279
|
|
|
280
|
+
当前内置模板与 acpx 的 built-in agents 对齐:
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
codex, claude, pi, openclaw, gemini, cursor, copilot, droid,
|
|
284
|
+
factory-droid, factorydroid, iflow, kilocode, kimi, kiro,
|
|
285
|
+
opencode, qoder, qwen, trae
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
这些模板只写入 `driver`,实际启动命令交给 acpx 解析;例如 `/agent add kimi` 会保存 `{ "driver": "kimi" }`。完整命令说明见 [docs/commands.md](./docs/commands.md),配置字段见 [docs/config-reference.md](./docs/config-reference.md)。
|
|
289
|
+
|
|
259
290
|
### Workspace 管理
|
|
260
291
|
|
|
261
292
|
| 命令 | 说明 |
|
|
@@ -320,22 +351,15 @@ README 里只保留用户视角的最常用命令。
|
|
|
320
351
|
| 命令 | 说明 |
|
|
321
352
|
|------|------|
|
|
322
353
|
| `/dg <agent> <task>` | 快速委派一个子任务 |
|
|
323
|
-
| `/group new <title>` | 创建任务组 |
|
|
324
|
-
| `/group add <groupId> <agent> <task>` | 往任务组里加子任务 |
|
|
325
|
-
| `/groups` | 查看任务组列表 |
|
|
326
|
-
| `/group <id>` | 查看单个任务组 |
|
|
327
|
-
| `/group cancel <groupId>` | 取消组内未结束任务 |
|
|
328
354
|
| `/tasks` | 查看当前主线下的任务 |
|
|
329
355
|
| `/task <id>` | 查看单个任务详情 |
|
|
330
356
|
| `/task approve <id>` | 批准 `needs_confirmation` 任务 |
|
|
331
|
-
| `/task cancel <id>` |
|
|
357
|
+
| `/task cancel <id>` | 取消任务;取消一个尚未批准的任务等同于拒绝 |
|
|
332
358
|
|
|
333
359
|
最常见例子:
|
|
334
360
|
|
|
335
361
|
```text
|
|
336
362
|
/dg claude 审查当前方案的 3 个高风险点
|
|
337
|
-
/group new review
|
|
338
|
-
/group add review claude 审查接口设计
|
|
339
363
|
/tasks
|
|
340
364
|
/task approve task_123
|
|
341
365
|
```
|
|
@@ -345,9 +369,9 @@ README 里只保留用户视角的最常用命令。
|
|
|
345
369
|
- 当前会话就是主控会话
|
|
346
370
|
- 被委派出去的是独立子任务会话
|
|
347
371
|
- agent 发起的委派请求默认需要人工确认
|
|
348
|
-
-
|
|
372
|
+
- 如果你在用外部 MCP host(Codex / Claude Code),用 `delegate_batch` 一次派发多个并行子任务:传一个 `tasks` 数组,底层自动建组,全部结果一次性回注,无需手动维护 groupId
|
|
349
373
|
|
|
350
|
-
如果你想先理解什么时候该用 delegate
|
|
374
|
+
如果你想先理解什么时候该用 delegate、什么时候应该并行派出多个子任务,请看:
|
|
351
375
|
|
|
352
376
|
- [docs/weacpx-group-usage-guide.md](./docs/weacpx-group-usage-guide.md)
|
|
353
377
|
|
|
@@ -356,6 +380,8 @@ README 里只保留用户视角的最常用命令。
|
|
|
356
380
|
|
|
357
381
|
如果你想让 Codex、Claude Code 等外部 MCP host 直接使用 weacpx 的多 Agent 编排能力,可以把 `weacpx mcp-stdio` 配成一个 stdio MCP server。
|
|
358
382
|
|
|
383
|
+
`delegate_request` 支持 MCP Tasks:支持该能力的 host 可以让委派请求立即返回原生 task handle,之后通过 `tasks/get` / `tasks/result` / `tasks/cancel` 获取状态、结果或取消任务;worker 输出的 `[PROGRESS] ...` 会显示在 `tasks/get` / `tasks/list` 的 `statusMessage` 里;`input_required` 状态下的 `tasks/result` 会返回下一步操作提示并结束本次 result stream,而不是长时间阻塞;client 按提示调用 `task_get` / `task_approve` / `coordinator_answer_question` 等工具后,再继续 `tasks/get` / `tasks/result` 轮询。不支持 MCP Tasks 的 host 仍可使用兼容工具 `task_get` / `task_list` / `task_watch` / `task_cancel`。
|
|
384
|
+
|
|
359
385
|
先启动 daemon:
|
|
360
386
|
|
|
361
387
|
```bash
|
|
@@ -111,38 +111,24 @@ function extractPromptFailureMessage(result) {
|
|
|
111
111
|
function extractPromptOutput(output) {
|
|
112
112
|
const lines = output.split(`
|
|
113
113
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
114
|
-
|
|
115
|
-
let currentSegment = "";
|
|
114
|
+
let text = "";
|
|
116
115
|
let hasAgentMessage = false;
|
|
117
116
|
for (const line of lines) {
|
|
117
|
+
let event;
|
|
118
118
|
try {
|
|
119
|
-
|
|
120
|
-
const isMessageChunk = event.method === "session/update" && event.params?.update?.sessionUpdate === "agent_message_chunk" && event.params.update.content?.type === "text" && typeof event.params.update.content.text === "string";
|
|
121
|
-
if (isMessageChunk) {
|
|
122
|
-
hasAgentMessage = true;
|
|
123
|
-
const chunk = event.params.update.content.text ?? "";
|
|
124
|
-
if (chunk.length > 0) {
|
|
125
|
-
currentSegment += chunk;
|
|
126
|
-
}
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (currentSegment.trim().length > 0) {
|
|
130
|
-
messageSegments.push(currentSegment.trim());
|
|
131
|
-
}
|
|
132
|
-
currentSegment = "";
|
|
119
|
+
event = JSON.parse(line);
|
|
133
120
|
} catch {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const isMessageChunk = event.method === "session/update" && event.params?.update?.sessionUpdate === "agent_message_chunk" && event.params.update.content?.type === "text" && typeof event.params.update.content.text === "string";
|
|
124
|
+
if (isMessageChunk) {
|
|
125
|
+
hasAgentMessage = true;
|
|
126
|
+
text += event.params.update.content.text ?? "";
|
|
138
127
|
}
|
|
139
128
|
}
|
|
140
|
-
if (
|
|
141
|
-
messageSegments.push(currentSegment.trim());
|
|
142
|
-
}
|
|
143
|
-
if (messageSegments.length > 0) {
|
|
129
|
+
if (hasAgentMessage && text.trim().length > 0) {
|
|
144
130
|
return {
|
|
145
|
-
text:
|
|
131
|
+
text: text.trim(),
|
|
146
132
|
hasAgentMessage
|
|
147
133
|
};
|
|
148
134
|
}
|
|
@@ -176,8 +162,12 @@ function extractJsonRpcErrorMessages(output) {
|
|
|
176
162
|
`).map((line) => line.trim()).filter((line) => line.length > 0).flatMap((line) => {
|
|
177
163
|
try {
|
|
178
164
|
const payload = JSON.parse(line);
|
|
179
|
-
|
|
180
|
-
|
|
165
|
+
const err = payload.error;
|
|
166
|
+
const dataMsg = typeof err?.data?.message === "string" && err.data.message.length > 0 ? err.data.message : undefined;
|
|
167
|
+
const baseMsg = typeof err?.message === "string" && err.message.length > 0 ? err.message : undefined;
|
|
168
|
+
const chosen = dataMsg && dataMsg !== baseMsg ? dataMsg : baseMsg;
|
|
169
|
+
if (chosen) {
|
|
170
|
+
return [chosen];
|
|
181
171
|
}
|
|
182
172
|
} catch {
|
|
183
173
|
return [];
|