weacpx 0.4.6 → 0.4.9
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 +6 -5
- package/dist/bridge/bridge-main.js +78 -4
- package/dist/channels/types.d.ts +4 -0
- package/dist/cli.js +1775 -491
- package/dist/config/types.d.ts +2 -0
- package/dist/orchestration/orchestration-types.d.ts +7 -1
- package/dist/weixin/agent/interface.d.ts +2 -0
- package/dist/weixin/api/api.d.ts +28 -0
- package/dist/weixin/api/session-guard.d.ts +2 -0
- package/dist/weixin/api/types.d.ts +2 -0
- package/dist/weixin/auth/accounts.d.ts +8 -1
- package/dist/weixin/auth/login-qr.d.ts +6 -0
- package/dist/weixin/index.d.ts +1 -1
- package/dist/weixin/messaging/inbound.d.ts +18 -1
- package/dist/weixin/messaging/markdown-filter.d.ts +45 -0
- package/dist/weixin/messaging/send.d.ts +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -180,7 +180,7 @@ weacpx restart
|
|
|
180
180
|
| `weacpx agent add <name>` | 从内置模板添加 agent;已存在且配置不同的同名 agent 不会被覆盖 |
|
|
181
181
|
| `weacpx agent rm <name>` | 删除 agent |
|
|
182
182
|
| `weacpx workspace list` | 查看本机已注册的 workspace |
|
|
183
|
-
| `weacpx workspace add [name]` | 把当前目录注册成 workspace;不传 `name`
|
|
183
|
+
| `weacpx workspace add [name] [--raw]` | 把当前目录注册成 workspace;不传 `name` 时使用当前目录名,含特殊字符的名称会被自动规范化 |
|
|
184
184
|
| `weacpx workspace rm <name>` | 删除 workspace |
|
|
185
185
|
|
|
186
186
|
首次运行 `weacpx start` 或 `weacpx run` 时,如果没有会话、workspace 和插件,CLI 会询问是否把当前目录创建为 workspace,并选择一个内置 agent 模板;服务启动后会通过正常会话创建流程创建初始 acpx 会话。
|
|
@@ -200,8 +200,9 @@ weacpx ws rm backend
|
|
|
200
200
|
| 命令 | 说明 |
|
|
201
201
|
|------|------|
|
|
202
202
|
| `weacpx workspace list` | 列出已注册的 workspace 及其路径 |
|
|
203
|
-
| `weacpx workspace add` | 把当前目录注册为 workspace
|
|
204
|
-
| `weacpx workspace add <name>` |
|
|
203
|
+
| `weacpx workspace add` | 把当前目录注册为 workspace,名称默认取当前目录名(自动规范化) |
|
|
204
|
+
| `weacpx workspace add <name>` | 把当前目录注册为指定名称(含特殊字符时自动规范化) |
|
|
205
|
+
| `weacpx workspace add [name] --raw` | 保留原始名称(含空格等),后续命令需要用引号引用 |
|
|
205
206
|
| `weacpx workspace rm <name>` | 删除指定 workspace |
|
|
206
207
|
|
|
207
208
|
常见用法:
|
|
@@ -224,7 +225,7 @@ weacpx ws rm frontend
|
|
|
224
225
|
/ss new claude --ws frontend
|
|
225
226
|
```
|
|
226
227
|
|
|
227
|
-
注意:`workspace add`
|
|
228
|
+
注意:`workspace add` 总是注册**当前终端所在目录**。如果不传名称,会用当前目录名作为 workspace 名称。含空格、中文等字符的名称会被自动规范化为 `[a-zA-Z0-9._-]+`(例如目录 `My Project` 会保存为 `My-Project`),重名时追加 `-2`、`-3`。如需保留原始名称,加 `--raw`;之后 `weacpx workspace rm`、`/ws rm`、`--ws <name>` 都需要用引号引用,例如 `weacpx workspace rm "My Project"`。
|
|
228
229
|
|
|
229
230
|
### `agent` CLI 怎么用
|
|
230
231
|
|
|
@@ -292,7 +293,7 @@ opencode, qoder, qwen, trae
|
|
|
292
293
|
| 命令 | 说明 |
|
|
293
294
|
|------|------|
|
|
294
295
|
| `/workspaces` / `/workspace` / `/ws` | 查看 workspace 列表 |
|
|
295
|
-
| `/ws new <name> -d <path
|
|
296
|
+
| `/ws new <name> -d <path> [--raw]` | 添加 workspace,`path` 是电脑上的绝对路径,Windows 不用区分正反斜杠;含空格/中文等特殊字符的名称会被自动规范化,--raw 保留原名 |
|
|
296
297
|
| `/workspace rm <name>` | 删除 workspace |
|
|
297
298
|
|
|
298
299
|
### Session 会话
|
|
@@ -60,6 +60,10 @@ function encodeBridgePromptToolEvent(event) {
|
|
|
60
60
|
return `${JSON.stringify(event)}
|
|
61
61
|
`;
|
|
62
62
|
}
|
|
63
|
+
function encodeBridgePromptThoughtEvent(event) {
|
|
64
|
+
return `${JSON.stringify(event)}
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
63
67
|
function encodeBridgeSessionProgressEvent(event) {
|
|
64
68
|
return `${JSON.stringify(event)}
|
|
65
69
|
`;
|
|
@@ -366,6 +370,7 @@ var init_tool_kind_emoji = __esm(() => {
|
|
|
366
370
|
function createStreamingPromptState(formatToolCalls = false, options) {
|
|
367
371
|
let toolEventMode;
|
|
368
372
|
let onToolEvent;
|
|
373
|
+
let onThought;
|
|
369
374
|
if (options === undefined) {
|
|
370
375
|
toolEventMode = "text";
|
|
371
376
|
onToolEvent = undefined;
|
|
@@ -374,6 +379,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
374
379
|
toolEventMode = "structured";
|
|
375
380
|
} else {
|
|
376
381
|
onToolEvent = options.onToolEvent;
|
|
382
|
+
onThought = options.onThought;
|
|
377
383
|
toolEventMode = resolveToolEventMode({
|
|
378
384
|
toolEventMode: options.mode,
|
|
379
385
|
onToolEvent
|
|
@@ -388,6 +394,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
388
394
|
emittedToolCallIds: new Set,
|
|
389
395
|
toolEventMode,
|
|
390
396
|
onToolEvent,
|
|
397
|
+
onThought,
|
|
391
398
|
finalize() {
|
|
392
399
|
if (this.pendingLine.trim().length > 0) {
|
|
393
400
|
parseStreamingChunks(this, this.pendingLine);
|
|
@@ -446,6 +453,14 @@ function parseStreamingChunks(state, line) {
|
|
|
446
453
|
}
|
|
447
454
|
return;
|
|
448
455
|
}
|
|
456
|
+
const isThoughtChunk = update.sessionUpdate === "agent_thought_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
457
|
+
if (isThoughtChunk) {
|
|
458
|
+
const chunk2 = update.content.text;
|
|
459
|
+
if (chunk2.length > 0) {
|
|
460
|
+
state.onThought?.(chunk2);
|
|
461
|
+
}
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
449
464
|
const isMessageChunk = update.sessionUpdate === "agent_message_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
450
465
|
if (!isMessageChunk)
|
|
451
466
|
return;
|
|
@@ -473,7 +488,7 @@ function formatToolCallEvent(update, sessionUpdate) {
|
|
|
473
488
|
if (title.length === 0)
|
|
474
489
|
return null;
|
|
475
490
|
const emoji = TOOL_KIND_EMOJI[kind] ?? DEFAULT_TOOL_EMOJI;
|
|
476
|
-
const inputSummary = summarizeToolInput(update.rawInput, title);
|
|
491
|
+
const inputSummary = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
477
492
|
const status = readString(update, "status");
|
|
478
493
|
if (!inputSummary && status === "pending")
|
|
479
494
|
return null;
|
|
@@ -504,15 +519,23 @@ function buildToolUseEvent(update) {
|
|
|
504
519
|
})();
|
|
505
520
|
const title = (update.title ?? "").trim();
|
|
506
521
|
const toolName = title || "Tool";
|
|
507
|
-
const summaryRaw = summarizeToolInput(update.rawInput, title);
|
|
522
|
+
const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
508
523
|
const summary = summaryRaw && summaryRaw !== title ? summaryRaw : undefined;
|
|
509
524
|
const statusRaw = readString(update, "status");
|
|
510
525
|
const status = statusRaw === "completed" || statusRaw === "success" ? "success" : statusRaw === "failed" || statusRaw === "error" ? "error" : "running";
|
|
526
|
+
const rawInput = update.rawInput;
|
|
527
|
+
const content = update.content;
|
|
528
|
+
const rawOutput = update.rawOutput;
|
|
529
|
+
const locations = update.locations;
|
|
511
530
|
return {
|
|
512
531
|
toolCallId,
|
|
513
532
|
toolName,
|
|
514
533
|
kind,
|
|
515
534
|
...summary ? { summary } : {},
|
|
535
|
+
...rawInput !== undefined ? { rawInput } : {},
|
|
536
|
+
...content !== undefined ? { content } : {},
|
|
537
|
+
...rawOutput !== undefined ? { rawOutput } : {},
|
|
538
|
+
...locations !== undefined ? { locations } : {},
|
|
516
539
|
status
|
|
517
540
|
};
|
|
518
541
|
}
|
|
@@ -831,6 +854,8 @@ function buildQueueOwnerPayload(input) {
|
|
|
831
854
|
nonInteractivePermissions: input.nonInteractivePermissions,
|
|
832
855
|
ttlMs: input.ttlMs ?? 300000,
|
|
833
856
|
maxQueueDepth: input.maxQueueDepth ?? 16,
|
|
857
|
+
...Number.isFinite(input.promptRetries) ? { promptRetries: input.promptRetries } : {},
|
|
858
|
+
...input.sessionOptions ? { sessionOptions: input.sessionOptions } : {},
|
|
834
859
|
mcpServers: input.mcpServers
|
|
835
860
|
};
|
|
836
861
|
}
|
|
@@ -1113,6 +1138,7 @@ class BridgeRuntime {
|
|
|
1113
1138
|
async updatePermissionPolicy(policy) {
|
|
1114
1139
|
this.options.permissionMode = policy.permissionMode;
|
|
1115
1140
|
this.options.nonInteractivePermissions = policy.nonInteractivePermissions;
|
|
1141
|
+
this.options.permissionPolicy = policy.permissionPolicy;
|
|
1116
1142
|
return {};
|
|
1117
1143
|
}
|
|
1118
1144
|
async hasSession(input) {
|
|
@@ -1124,6 +1150,26 @@ class BridgeRuntime {
|
|
|
1124
1150
|
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
1125
1151
|
return { exists: result.code === 0 };
|
|
1126
1152
|
}
|
|
1153
|
+
async tailSessionHistory(input) {
|
|
1154
|
+
const candidates = [
|
|
1155
|
+
["sessions", "history", "quiet", "-s", input.name, String(input.lines)],
|
|
1156
|
+
["sessions", "history", "quiet", input.name, String(input.lines)],
|
|
1157
|
+
["sessions", "history", "-s", input.name, "--tail", String(input.lines)],
|
|
1158
|
+
["sessions", "history", input.name, "--tail", String(input.lines)],
|
|
1159
|
+
["sessions", "history", "--name", input.name, "--tail", String(input.lines)]
|
|
1160
|
+
];
|
|
1161
|
+
let lastResult;
|
|
1162
|
+
for (const tailArgs of candidates) {
|
|
1163
|
+
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, tailArgs));
|
|
1164
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
1165
|
+
if (result.code === 0) {
|
|
1166
|
+
return { text: result.stdout.trimEnd() };
|
|
1167
|
+
}
|
|
1168
|
+
lastResult = result;
|
|
1169
|
+
}
|
|
1170
|
+
const message = lastResult?.stderr || lastResult?.stdout || "sessions history failed";
|
|
1171
|
+
throw new Error(message);
|
|
1172
|
+
}
|
|
1127
1173
|
async ensureSession(input, onProgress) {
|
|
1128
1174
|
onProgress?.("spawn");
|
|
1129
1175
|
const onStderrLine = onProgress ? (line) => {
|
|
@@ -1346,7 +1392,11 @@ class BridgeRuntime {
|
|
|
1346
1392
|
const permissionMode = this.options.permissionMode ?? "approve-all";
|
|
1347
1393
|
const nonInteractivePermissions = this.options.nonInteractivePermissions ?? "deny";
|
|
1348
1394
|
const modeFlag = permissionModeToFlag(permissionMode);
|
|
1349
|
-
|
|
1395
|
+
const args = [modeFlag, "--non-interactive-permissions", nonInteractivePermissions];
|
|
1396
|
+
if (typeof this.options.permissionPolicy === "string" && this.options.permissionPolicy.trim().length > 0) {
|
|
1397
|
+
args.push("--permission-policy", this.options.permissionPolicy);
|
|
1398
|
+
}
|
|
1399
|
+
return args;
|
|
1350
1400
|
}
|
|
1351
1401
|
}
|
|
1352
1402
|
function spawnCapture(command, args, options) {
|
|
@@ -1398,7 +1448,8 @@ async function runStreamingPrompt(command, args, onEvent, options = {}) {
|
|
|
1398
1448
|
const toolEventMode = options.toolEventMode ?? "text";
|
|
1399
1449
|
const state = createStreamingPromptState(options.formatToolCalls ?? false, {
|
|
1400
1450
|
mode: toolEventMode,
|
|
1401
|
-
...onEvent && (toolEventMode === "structured" || toolEventMode === "both") ? { onToolEvent: (toolEvent) => onEvent({ type: "prompt.tool_event", event: toolEvent }) } : {}
|
|
1451
|
+
...onEvent && (toolEventMode === "structured" || toolEventMode === "both") ? { onToolEvent: (toolEvent) => onEvent({ type: "prompt.tool_event", event: toolEvent }) } : {},
|
|
1452
|
+
...onEvent ? { onThought: (chunk) => onEvent({ type: "prompt.thought", text: chunk }) } : {}
|
|
1402
1453
|
});
|
|
1403
1454
|
let lastReplyAt = now();
|
|
1404
1455
|
const flushBuffer = () => {
|
|
@@ -1514,6 +1565,7 @@ var BRIDGE_METHODS = new Set([
|
|
|
1514
1565
|
"updatePermissionPolicy",
|
|
1515
1566
|
"hasSession",
|
|
1516
1567
|
"ensureSession",
|
|
1568
|
+
"tailSessionHistory",
|
|
1517
1569
|
"prompt",
|
|
1518
1570
|
"setMode",
|
|
1519
1571
|
"cancel",
|
|
@@ -1522,6 +1574,7 @@ var BRIDGE_METHODS = new Set([
|
|
|
1522
1574
|
var SESSION_SCOPED_METHODS = new Set([
|
|
1523
1575
|
"hasSession",
|
|
1524
1576
|
"ensureSession",
|
|
1577
|
+
"tailSessionHistory",
|
|
1525
1578
|
"prompt",
|
|
1526
1579
|
"setMode",
|
|
1527
1580
|
"cancel",
|
|
@@ -1596,6 +1649,14 @@ class BridgeServer {
|
|
|
1596
1649
|
cwd: requireString(params, "cwd"),
|
|
1597
1650
|
name: requireString(params, "name")
|
|
1598
1651
|
});
|
|
1652
|
+
case "tailSessionHistory":
|
|
1653
|
+
return await this.runtime.tailSessionHistory({
|
|
1654
|
+
agent: requireString(params, "agent"),
|
|
1655
|
+
agentCommand: asOptionalString(params.agentCommand),
|
|
1656
|
+
cwd: requireString(params, "cwd"),
|
|
1657
|
+
name: requireString(params, "name"),
|
|
1658
|
+
lines: requirePositiveInt(params, "lines")
|
|
1659
|
+
});
|
|
1599
1660
|
case "ensureSession":
|
|
1600
1661
|
return await this.runtime.ensureSession({
|
|
1601
1662
|
agent: requireString(params, "agent"),
|
|
@@ -1647,6 +1708,12 @@ class BridgeServer {
|
|
|
1647
1708
|
event: "prompt.tool_event",
|
|
1648
1709
|
toolEvent: event.event
|
|
1649
1710
|
}));
|
|
1711
|
+
} else if (event.type === "prompt.thought") {
|
|
1712
|
+
writeLine?.(encodeBridgePromptThoughtEvent({
|
|
1713
|
+
id: requestId,
|
|
1714
|
+
event: "prompt.thought",
|
|
1715
|
+
text: event.text
|
|
1716
|
+
}));
|
|
1650
1717
|
}
|
|
1651
1718
|
});
|
|
1652
1719
|
case "setMode":
|
|
@@ -1745,6 +1812,13 @@ function requireString(params, key) {
|
|
|
1745
1812
|
}
|
|
1746
1813
|
return value;
|
|
1747
1814
|
}
|
|
1815
|
+
function requirePositiveInt(params, key) {
|
|
1816
|
+
const value = params[key];
|
|
1817
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
|
|
1818
|
+
throw new BridgeInvalidRequestError(`${key} must be a positive integer`);
|
|
1819
|
+
}
|
|
1820
|
+
return value;
|
|
1821
|
+
}
|
|
1748
1822
|
function requirePromptText(params, media) {
|
|
1749
1823
|
const value = params.text;
|
|
1750
1824
|
if (typeof value !== "string") {
|
package/dist/channels/types.d.ts
CHANGED
|
@@ -71,6 +71,10 @@ export interface ToolUseEvent {
|
|
|
71
71
|
kind: ToolUseKind;
|
|
72
72
|
/** Best-effort one-line summary derived from `rawInput`. */
|
|
73
73
|
summary?: string;
|
|
74
|
+
rawInput?: unknown;
|
|
75
|
+
content?: unknown;
|
|
76
|
+
rawOutput?: unknown;
|
|
77
|
+
locations?: unknown;
|
|
74
78
|
status: ToolUseStatus;
|
|
75
79
|
/** Set when status transitions out of "running". */
|
|
76
80
|
durationMs?: number;
|