weacpx 0.4.6 → 0.4.8
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.
|
@@ -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;
|
package/dist/cli.js
CHANGED
|
@@ -2201,6 +2201,11 @@ function parseConfig(raw, options = {}) {
|
|
|
2201
2201
|
if ("nonInteractivePermissions" in transport && transport.nonInteractivePermissions !== "deny" && transport.nonInteractivePermissions !== "fail") {
|
|
2202
2202
|
throw new Error("transport.nonInteractivePermissions must be deny or fail");
|
|
2203
2203
|
}
|
|
2204
|
+
if ("permissionPolicy" in transport && transport.permissionPolicy !== undefined) {
|
|
2205
|
+
if (typeof transport.permissionPolicy !== "string" || transport.permissionPolicy.trim().length === 0) {
|
|
2206
|
+
throw new Error("transport.permissionPolicy must be a non-empty string");
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2204
2209
|
if (!isRecord(raw.agents)) {
|
|
2205
2210
|
throw new Error("agents must be an object");
|
|
2206
2211
|
}
|
|
@@ -2294,6 +2299,7 @@ function parseConfig(raw, options = {}) {
|
|
|
2294
2299
|
transport: {
|
|
2295
2300
|
...typeof transport.command === "string" ? { command: transport.command } : {},
|
|
2296
2301
|
...typeof transport.sessionInitTimeoutMs === "number" ? { sessionInitTimeoutMs: transport.sessionInitTimeoutMs } : {},
|
|
2302
|
+
...typeof transport.permissionPolicy === "string" ? { permissionPolicy: transport.permissionPolicy } : {},
|
|
2297
2303
|
type: transportType,
|
|
2298
2304
|
permissionMode,
|
|
2299
2305
|
nonInteractivePermissions
|
|
@@ -3096,7 +3102,7 @@ var init_orchestration_ipc = () => {};
|
|
|
3096
3102
|
// src/daemon/daemon-files.ts
|
|
3097
3103
|
import { dirname as dirname4, join as join2 } from "node:path";
|
|
3098
3104
|
function resolveDaemonPaths(options) {
|
|
3099
|
-
const runtimeDir = options.runtimeDir ?? join2(options.home, ".weacpx", "runtime");
|
|
3105
|
+
const runtimeDir = options.runtimeDir ?? (options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : join2(options.home, ".weacpx", "runtime"));
|
|
3100
3106
|
return {
|
|
3101
3107
|
runtimeDir,
|
|
3102
3108
|
pidFile: join2(runtimeDir, "daemon.pid"),
|
|
@@ -10044,6 +10050,31 @@ function resolveWeixinStateDir() {
|
|
|
10044
10050
|
function resolveAccountIndexPath() {
|
|
10045
10051
|
return path4.join(resolveWeixinStateDir(), "accounts.json");
|
|
10046
10052
|
}
|
|
10053
|
+
function listAccountFileIds() {
|
|
10054
|
+
const dir = resolveAccountsDir();
|
|
10055
|
+
try {
|
|
10056
|
+
if (!fs3.existsSync(dir))
|
|
10057
|
+
return [];
|
|
10058
|
+
return fs3.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => ({
|
|
10059
|
+
id: entry.name.slice(0, -5),
|
|
10060
|
+
data: readAccountFile(path4.join(dir, entry.name))
|
|
10061
|
+
})).filter((entry) => entry.id.trim() !== "" && Boolean(entry.data?.token?.trim())).map((entry) => entry.id).sort();
|
|
10062
|
+
} catch {
|
|
10063
|
+
return [];
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
10066
|
+
function uniqueAccountIds(ids) {
|
|
10067
|
+
const seen = new Set;
|
|
10068
|
+
const result = [];
|
|
10069
|
+
for (const raw of ids) {
|
|
10070
|
+
const id = raw.trim();
|
|
10071
|
+
if (!id || seen.has(id))
|
|
10072
|
+
continue;
|
|
10073
|
+
seen.add(id);
|
|
10074
|
+
result.push(id);
|
|
10075
|
+
}
|
|
10076
|
+
return result;
|
|
10077
|
+
}
|
|
10047
10078
|
function listIndexedWeixinAccountIds() {
|
|
10048
10079
|
const filePath = resolveAccountIndexPath();
|
|
10049
10080
|
try {
|
|
@@ -10053,7 +10084,7 @@ function listIndexedWeixinAccountIds() {
|
|
|
10053
10084
|
const parsed = JSON.parse(raw);
|
|
10054
10085
|
if (!Array.isArray(parsed))
|
|
10055
10086
|
return [];
|
|
10056
|
-
return parsed.filter((id) => typeof id === "string" && id.trim() !== "");
|
|
10087
|
+
return uniqueAccountIds(parsed.filter((id) => typeof id === "string" && id.trim() !== ""));
|
|
10057
10088
|
} catch {
|
|
10058
10089
|
return [];
|
|
10059
10090
|
}
|
|
@@ -10128,7 +10159,10 @@ function clearWeixinAccount(accountId) {
|
|
|
10128
10159
|
} catch {}
|
|
10129
10160
|
}
|
|
10130
10161
|
function clearAllWeixinAccounts() {
|
|
10131
|
-
const ids =
|
|
10162
|
+
const ids = uniqueAccountIds([
|
|
10163
|
+
...listIndexedWeixinAccountIds(),
|
|
10164
|
+
...listAccountFileIds()
|
|
10165
|
+
]);
|
|
10132
10166
|
for (const id of ids) {
|
|
10133
10167
|
clearWeixinAccount(id);
|
|
10134
10168
|
}
|
|
@@ -10169,7 +10203,10 @@ function loadConfigRouteTag(accountId) {
|
|
|
10169
10203
|
}
|
|
10170
10204
|
}
|
|
10171
10205
|
function listWeixinAccountIds() {
|
|
10172
|
-
|
|
10206
|
+
const indexed = listIndexedWeixinAccountIds();
|
|
10207
|
+
if (indexed.length > 0)
|
|
10208
|
+
return indexed;
|
|
10209
|
+
return listAccountFileIds();
|
|
10173
10210
|
}
|
|
10174
10211
|
function resolveWeixinAccount(accountId) {
|
|
10175
10212
|
const raw = accountId?.trim();
|
|
@@ -15672,6 +15709,18 @@ function parseCommand(input) {
|
|
|
15672
15709
|
return { kind: "workspaces" };
|
|
15673
15710
|
if (command === "/session" && parts[1] === "reset" && parts.length === 2)
|
|
15674
15711
|
return { kind: "session.reset" };
|
|
15712
|
+
if (command === "/session" && parts[1] === "tail") {
|
|
15713
|
+
if (parts.length === 2) {
|
|
15714
|
+
return { kind: "session.tail" };
|
|
15715
|
+
}
|
|
15716
|
+
if (parts.length === 3) {
|
|
15717
|
+
const lines = parsePositiveInt(parts[2]);
|
|
15718
|
+
if (lines !== null) {
|
|
15719
|
+
return { kind: "session.tail", lines };
|
|
15720
|
+
}
|
|
15721
|
+
}
|
|
15722
|
+
return { kind: "invalid", text: trimmed, recognizedCommand: "/session" };
|
|
15723
|
+
}
|
|
15675
15724
|
if (command === "/session" && parts[1] === "rm" && parts[2] && parts.length === 3) {
|
|
15676
15725
|
return { kind: "session.rm", alias: parts[2] };
|
|
15677
15726
|
}
|
|
@@ -15981,6 +16030,16 @@ function tokenizeCommand(input) {
|
|
|
15981
16030
|
}
|
|
15982
16031
|
return tokens;
|
|
15983
16032
|
}
|
|
16033
|
+
function parsePositiveInt(value) {
|
|
16034
|
+
if (!value)
|
|
16035
|
+
return null;
|
|
16036
|
+
if (!/^\d+$/.test(value))
|
|
16037
|
+
return null;
|
|
16038
|
+
const parsed = Number(value);
|
|
16039
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
16040
|
+
return null;
|
|
16041
|
+
return parsed;
|
|
16042
|
+
}
|
|
15984
16043
|
function parseListFilterFlags(parts, validStatuses) {
|
|
15985
16044
|
const filter = {};
|
|
15986
16045
|
let i = 1;
|
|
@@ -16104,6 +16163,7 @@ var init_command_policy = __esm(() => {
|
|
|
16104
16163
|
"agents",
|
|
16105
16164
|
"workspaces",
|
|
16106
16165
|
"sessions",
|
|
16166
|
+
"session.tail",
|
|
16107
16167
|
"status",
|
|
16108
16168
|
"mode.show",
|
|
16109
16169
|
"replymode.show",
|
|
@@ -16120,6 +16180,7 @@ var init_command_policy = __esm(() => {
|
|
|
16120
16180
|
COMMAND_KIND_TO_LABEL = {
|
|
16121
16181
|
"session.reset": "/clear",
|
|
16122
16182
|
"session.rm": "/session rm",
|
|
16183
|
+
"session.tail": "/session tail",
|
|
16123
16184
|
"replymode.set": "/replymode",
|
|
16124
16185
|
"replymode.reset": "/replymode reset",
|
|
16125
16186
|
"mode.set": "/mode",
|
|
@@ -16256,7 +16317,7 @@ async function handleConfigSet(context, path13, rawValue) {
|
|
|
16256
16317
|
return { text: result.error };
|
|
16257
16318
|
}
|
|
16258
16319
|
await context.configStore.save(updated);
|
|
16259
|
-
if (path13 === "transport.permissionMode" || path13 === "transport.nonInteractivePermissions") {
|
|
16320
|
+
if (path13 === "transport.permissionMode" || path13 === "transport.nonInteractivePermissions" || path13 === "transport.permissionPolicy") {
|
|
16260
16321
|
try {
|
|
16261
16322
|
await context.transport.updatePermissionPolicy?.(updated.transport);
|
|
16262
16323
|
} catch (error2) {
|
|
@@ -16303,6 +16364,11 @@ function applySupportedConfigUpdate(config2, path13, rawValue) {
|
|
|
16303
16364
|
config2.transport.nonInteractivePermissions = parsed;
|
|
16304
16365
|
return { renderedValue: parsed };
|
|
16305
16366
|
}
|
|
16367
|
+
case "transport.permissionPolicy":
|
|
16368
|
+
if (!rawValue.trim())
|
|
16369
|
+
return { error: "transport.permissionPolicy 不能为空。" };
|
|
16370
|
+
config2.transport.permissionPolicy = rawValue;
|
|
16371
|
+
return { renderedValue: rawValue };
|
|
16306
16372
|
case "logging.level": {
|
|
16307
16373
|
const parsed = parseEnum(rawValue, ["error", "info", "debug"]);
|
|
16308
16374
|
if (!parsed)
|
|
@@ -16412,6 +16478,7 @@ var init_config_handler = __esm(() => {
|
|
|
16412
16478
|
"transport.sessionInitTimeoutMs",
|
|
16413
16479
|
"transport.permissionMode",
|
|
16414
16480
|
"transport.nonInteractivePermissions",
|
|
16481
|
+
"transport.permissionPolicy",
|
|
16415
16482
|
"logging.level",
|
|
16416
16483
|
"logging.maxSizeBytes",
|
|
16417
16484
|
"logging.maxFiles",
|
|
@@ -16966,6 +17033,15 @@ async function handleCancel(context, chatKey) {
|
|
|
16966
17033
|
async function handleSessionReset(context, chatKey) {
|
|
16967
17034
|
return await context.lifecycle.resetCurrentSession(chatKey);
|
|
16968
17035
|
}
|
|
17036
|
+
async function handleSessionTail(context, chatKey, lines) {
|
|
17037
|
+
const session = await context.sessions.getCurrentSession(chatKey);
|
|
17038
|
+
if (!session) {
|
|
17039
|
+
return { text: NO_CURRENT_SESSION_TEXT };
|
|
17040
|
+
}
|
|
17041
|
+
const resolvedLines = Math.min(Math.max(lines ?? DEFAULT_SESSION_TAIL_LINES, 1), MAX_SESSION_TAIL_LINES);
|
|
17042
|
+
const result = await context.transport.tailSessionHistory(session, resolvedLines);
|
|
17043
|
+
return { text: result.text };
|
|
17044
|
+
}
|
|
16969
17045
|
async function handleSessionRemove(context, chatKey, alias) {
|
|
16970
17046
|
const internalAlias = await context.sessions.resolveAliasForChat(chatKey, alias);
|
|
16971
17047
|
const session = await context.sessions.getSession(internalAlias);
|
|
@@ -17036,7 +17112,7 @@ async function handleSessionRemove(context, chatKey, alias) {
|
|
|
17036
17112
|
return { text: lines.join(`
|
|
17037
17113
|
`) };
|
|
17038
17114
|
}
|
|
17039
|
-
async function promptWithSession(context, session, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, perfSpan) {
|
|
17115
|
+
async function promptWithSession(context, session, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan) {
|
|
17040
17116
|
const effectiveReplyMode = session.replyMode ?? context.config?.channel.replyMode ?? "verbose";
|
|
17041
17117
|
if (!session.replyMode)
|
|
17042
17118
|
session.replyMode = effectiveReplyMode;
|
|
@@ -17061,7 +17137,7 @@ async function promptWithSession(context, session, chatKey, text, reply, replyCo
|
|
|
17061
17137
|
const { promptText, taskIds, groupIds, claimHumanReply } = await preparePromptWithFallback(context, session, chatKey, text, replyContextToken, accountId);
|
|
17062
17138
|
try {
|
|
17063
17139
|
const replyContext = transportReply && context.quota && getChannelIdFromChatKey(chatKey) === "weixin" ? { chatKey, quota: context.quota } : undefined;
|
|
17064
|
-
const result = await context.interaction.promptTransportSession(session, promptText, transportReply, replyContext, media, abortSignal, onToolEvent, perfSpan);
|
|
17140
|
+
const result = await context.interaction.promptTransportSession(session, promptText, transportReply, replyContext, media, abortSignal, onToolEvent, onThought, perfSpan);
|
|
17065
17141
|
if (claimHumanReply) {
|
|
17066
17142
|
try {
|
|
17067
17143
|
await context.orchestration?.claimActiveHumanReply?.(claimHumanReply);
|
|
@@ -17081,17 +17157,17 @@ async function promptWithSession(context, session, chatKey, text, reply, replyCo
|
|
|
17081
17157
|
throw error2;
|
|
17082
17158
|
}
|
|
17083
17159
|
}
|
|
17084
|
-
async function handlePrompt(context, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, perfSpan) {
|
|
17160
|
+
async function handlePrompt(context, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan) {
|
|
17085
17161
|
const session = await context.sessions.getCurrentSession(chatKey);
|
|
17086
17162
|
if (!session) {
|
|
17087
17163
|
return { text: NO_CURRENT_SESSION_TEXT };
|
|
17088
17164
|
}
|
|
17089
17165
|
try {
|
|
17090
|
-
return await promptWithSession(context, session, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, perfSpan);
|
|
17166
|
+
return await promptWithSession(context, session, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan);
|
|
17091
17167
|
} catch (error2) {
|
|
17092
17168
|
const recovered = await context.recovery.tryRecoverMissingSession(session, error2);
|
|
17093
17169
|
if (recovered) {
|
|
17094
|
-
return await promptWithSession(context, recovered, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, perfSpan);
|
|
17170
|
+
return await promptWithSession(context, recovered, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan);
|
|
17095
17171
|
}
|
|
17096
17172
|
return context.recovery.renderTransportError(session, error2);
|
|
17097
17173
|
}
|
|
@@ -17158,7 +17234,7 @@ async function markCoordinatorResultsInjectionFailed(context, taskIds, groupIds,
|
|
|
17158
17234
|
});
|
|
17159
17235
|
}
|
|
17160
17236
|
}
|
|
17161
|
-
var NO_CURRENT_SESSION_TEXT = "当前还没有选中的会话。请先执行 /session new ... 或 /use <alias>。", sessionHelp, modeHelp, replyModeHelp, statusHelp, cancelHelp;
|
|
17237
|
+
var NO_CURRENT_SESSION_TEXT = "当前还没有选中的会话。请先执行 /session new ... 或 /use <alias>。", DEFAULT_SESSION_TAIL_LINES = 50, MAX_SESSION_TAIL_LINES = 500, sessionHelp, modeHelp, replyModeHelp, statusHelp, cancelHelp;
|
|
17162
17238
|
var init_session_handler = __esm(() => {
|
|
17163
17239
|
init_build_coordinator_prompt();
|
|
17164
17240
|
init_channel_scope();
|
|
@@ -17173,6 +17249,7 @@ var init_session_handler = __esm(() => {
|
|
|
17173
17249
|
{ usage: "/ss new <agent> (-d <path> | --ws <name>)", description: "强制新建会话" },
|
|
17174
17250
|
{ usage: "/ss new <alias> -a <name> --ws <name>", description: "按指定配置新建会话" },
|
|
17175
17251
|
{ usage: "/ss attach <alias> -a <name> --ws <name> --name <transport-session>", description: "绑定已有会话" },
|
|
17252
|
+
{ usage: "/session tail [N]", description: "补拉当前会话的历史输出(默认 50 行)" },
|
|
17176
17253
|
{ usage: "/session rm <alias>", description: "删除逻辑会话" },
|
|
17177
17254
|
{ usage: "/use <alias>", description: "切换当前会话" },
|
|
17178
17255
|
{ usage: "/session reset 或 /clear", description: "重置当前会话上下文" }
|
|
@@ -18595,7 +18672,7 @@ class CommandRouter {
|
|
|
18595
18672
|
this.quota = quota;
|
|
18596
18673
|
this.logger = logger2 ?? createNoopAppLogger();
|
|
18597
18674
|
}
|
|
18598
|
-
async handle(chatKey, input, reply, replyContextToken, accountId, media, metadata, abortSignal, onToolEvent, perfSpan) {
|
|
18675
|
+
async handle(chatKey, input, reply, replyContextToken, accountId, media, metadata, abortSignal, onToolEvent, onThought, perfSpan) {
|
|
18599
18676
|
const startedAt = Date.now();
|
|
18600
18677
|
const command = parseCommand(input);
|
|
18601
18678
|
await this.logger.debug("command.parsed", "parsed inbound command", {
|
|
@@ -18685,6 +18762,8 @@ class CommandRouter {
|
|
|
18685
18762
|
return await handleCancel(this.createSessionHandlerContext(undefined, perfSpan), chatKey);
|
|
18686
18763
|
case "session.reset":
|
|
18687
18764
|
return await handleSessionReset(this.createSessionHandlerContext(reply, perfSpan), chatKey);
|
|
18765
|
+
case "session.tail":
|
|
18766
|
+
return await handleSessionTail(this.createSessionHandlerContext(undefined, perfSpan), chatKey, command.lines);
|
|
18688
18767
|
case "session.rm":
|
|
18689
18768
|
return await handleSessionRemove(this.createSessionHandlerContext(undefined, perfSpan), chatKey, command.alias);
|
|
18690
18769
|
case "groups":
|
|
@@ -18712,7 +18791,7 @@ class CommandRouter {
|
|
|
18712
18791
|
case "task.cancel":
|
|
18713
18792
|
return await handleTaskCancel(this.createHandlerContext(), chatKey, command.taskId);
|
|
18714
18793
|
case "prompt":
|
|
18715
|
-
return await handlePrompt(this.createSessionHandlerContext(undefined, perfSpan), chatKey, command.text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, perfSpan);
|
|
18794
|
+
return await handlePrompt(this.createSessionHandlerContext(undefined, perfSpan), chatKey, command.text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan);
|
|
18716
18795
|
}
|
|
18717
18796
|
});
|
|
18718
18797
|
}
|
|
@@ -18765,7 +18844,7 @@ class CommandRouter {
|
|
|
18765
18844
|
return {
|
|
18766
18845
|
setModeTransportSession: (session, modeId) => this.setModeTransportSession(session, modeId),
|
|
18767
18846
|
cancelTransportSession: (session) => this.cancelTransportSession(session),
|
|
18768
|
-
promptTransportSession: (session, text, reply, replyContext, media, abortSignal, onToolEvent, perfSpanOverride) => this.promptTransportSession(session, text, reply, replyContext, media, abortSignal, onToolEvent, perfSpanOverride ?? perfSpan)
|
|
18847
|
+
promptTransportSession: (session, text, reply, replyContext, media, abortSignal, onToolEvent, onThought, perfSpanOverride) => this.promptTransportSession(session, text, reply, replyContext, media, abortSignal, onToolEvent, onThought, perfSpanOverride ?? perfSpan)
|
|
18769
18848
|
};
|
|
18770
18849
|
}
|
|
18771
18850
|
createSessionRenderRecoveryOps() {
|
|
@@ -18943,7 +19022,7 @@ class CommandRouter {
|
|
|
18943
19022
|
async checkTransportSession(session) {
|
|
18944
19023
|
return await this.measureTransportCall("has_session", session, () => this.transport.hasSession(session));
|
|
18945
19024
|
}
|
|
18946
|
-
async promptTransportSession(session, text, reply, replyContext, media, abortSignal, onToolEvent, perfSpan) {
|
|
19025
|
+
async promptTransportSession(session, text, reply, replyContext, media, abortSignal, onToolEvent, onThought, perfSpan) {
|
|
18947
19026
|
session.mcpCoordinatorSession ??= session.transportSession;
|
|
18948
19027
|
let done = false;
|
|
18949
19028
|
let abortRequested = false;
|
|
@@ -18999,7 +19078,8 @@ class CommandRouter {
|
|
|
18999
19078
|
return await this.measureTransportCall("prompt", session, () => this.transport.prompt(session, text, reply, replyContext, {
|
|
19000
19079
|
...media ? { media } : {},
|
|
19001
19080
|
...reply ? { onSegment } : {},
|
|
19002
|
-
...onToolEvent ? { onToolEvent } : {}
|
|
19081
|
+
...onToolEvent ? { onToolEvent } : {},
|
|
19082
|
+
...onThought ? { onThought } : {}
|
|
19003
19083
|
}));
|
|
19004
19084
|
} catch (error2) {
|
|
19005
19085
|
localOutcome = isAbortError2(error2) || abortRequested ? "aborted" : "error";
|
|
@@ -19165,7 +19245,7 @@ class ConsoleAgent {
|
|
|
19165
19245
|
...m.fileName ? { fileName: m.fileName } : {}
|
|
19166
19246
|
})) : undefined;
|
|
19167
19247
|
request.perfSpan?.mark("agent.dispatched");
|
|
19168
|
-
return await this.router.handle(request.conversationId, request.text, request.reply, request.replyContextToken, request.accountId, promptMedia, request.metadata, request.abortSignal, request.onToolEvent, request.perfSpan);
|
|
19248
|
+
return await this.router.handle(request.conversationId, request.text, request.reply, request.replyContextToken, request.accountId, promptMedia, request.metadata, request.abortSignal, request.onToolEvent, request.onThought, request.perfSpan);
|
|
19169
19249
|
}
|
|
19170
19250
|
isKnownCommand(text) {
|
|
19171
19251
|
return isKnownWeacpxCommandText(text);
|
|
@@ -23333,6 +23413,10 @@ function encodeBridgePromptToolEvent(event) {
|
|
|
23333
23413
|
return `${JSON.stringify(event)}
|
|
23334
23414
|
`;
|
|
23335
23415
|
}
|
|
23416
|
+
function encodeBridgePromptThoughtEvent(event) {
|
|
23417
|
+
return `${JSON.stringify(event)}
|
|
23418
|
+
`;
|
|
23419
|
+
}
|
|
23336
23420
|
function encodeBridgeSessionProgressEvent(event) {
|
|
23337
23421
|
return `${JSON.stringify(event)}
|
|
23338
23422
|
`;
|
|
@@ -23405,6 +23489,11 @@ class AcpxBridgeClient {
|
|
|
23405
23489
|
type: "prompt.tool_event",
|
|
23406
23490
|
event: message.toolEvent
|
|
23407
23491
|
});
|
|
23492
|
+
} else if (message.event === "prompt.thought") {
|
|
23493
|
+
pending.onEvent?.({
|
|
23494
|
+
type: "prompt.thought",
|
|
23495
|
+
text: message.text
|
|
23496
|
+
});
|
|
23408
23497
|
} else if (message.event === "session.progress") {
|
|
23409
23498
|
pending.onEvent?.({
|
|
23410
23499
|
type: "session.progress",
|
|
@@ -23754,6 +23843,12 @@ class AcpxBridgeTransport {
|
|
|
23754
23843
|
}
|
|
23755
23844
|
} : undefined);
|
|
23756
23845
|
}
|
|
23846
|
+
async tailSessionHistory(session, lines) {
|
|
23847
|
+
return await this.client.request("tailSessionHistory", {
|
|
23848
|
+
...this.toParams(session),
|
|
23849
|
+
lines
|
|
23850
|
+
});
|
|
23851
|
+
}
|
|
23757
23852
|
async prompt(session, text, reply, replyContext, options) {
|
|
23758
23853
|
const sink = reply ? createQuotaGatedReplySink({
|
|
23759
23854
|
reply,
|
|
@@ -23763,6 +23858,8 @@ class AcpxBridgeTransport {
|
|
|
23763
23858
|
let segmentChain = Promise.resolve();
|
|
23764
23859
|
let toolEventError;
|
|
23765
23860
|
let toolEventChain = Promise.resolve();
|
|
23861
|
+
let thoughtError;
|
|
23862
|
+
let thoughtChain = Promise.resolve();
|
|
23766
23863
|
let toolEventMode = resolveToolEventMode(options);
|
|
23767
23864
|
if ((toolEventMode === "structured" || toolEventMode === "both") && !options?.onToolEvent) {
|
|
23768
23865
|
toolEventMode = "text";
|
|
@@ -23795,9 +23892,20 @@ class AcpxBridgeTransport {
|
|
|
23795
23892
|
}
|
|
23796
23893
|
return;
|
|
23797
23894
|
}
|
|
23895
|
+
if (event.type === "prompt.thought") {
|
|
23896
|
+
const onThought = options?.onThought;
|
|
23897
|
+
if (onThought) {
|
|
23898
|
+
const thoughtText = event.text;
|
|
23899
|
+
thoughtChain = thoughtChain.then(() => onThought(thoughtText)).catch((error2) => {
|
|
23900
|
+
thoughtError ??= error2;
|
|
23901
|
+
});
|
|
23902
|
+
}
|
|
23903
|
+
return;
|
|
23904
|
+
}
|
|
23798
23905
|
});
|
|
23799
23906
|
await segmentChain;
|
|
23800
23907
|
await toolEventChain;
|
|
23908
|
+
await thoughtChain;
|
|
23801
23909
|
if (sink) {
|
|
23802
23910
|
const { overflowCount } = sink.finalize();
|
|
23803
23911
|
await sink.drain({ timeoutMs: 30000 });
|
|
@@ -23812,6 +23920,9 @@ class AcpxBridgeTransport {
|
|
|
23812
23920
|
if (toolEventError) {
|
|
23813
23921
|
throw toolEventError;
|
|
23814
23922
|
}
|
|
23923
|
+
if (thoughtError) {
|
|
23924
|
+
throw thoughtError;
|
|
23925
|
+
}
|
|
23815
23926
|
return { text: summary ? `${summary}
|
|
23816
23927
|
|
|
23817
23928
|
${result.text}` : "" };
|
|
@@ -23822,6 +23933,9 @@ ${result.text}` : "" };
|
|
|
23822
23933
|
if (toolEventError) {
|
|
23823
23934
|
throw toolEventError;
|
|
23824
23935
|
}
|
|
23936
|
+
if (thoughtError) {
|
|
23937
|
+
throw thoughtError;
|
|
23938
|
+
}
|
|
23825
23939
|
return result;
|
|
23826
23940
|
}
|
|
23827
23941
|
async setMode(session, modeId) {
|
|
@@ -24026,6 +24140,7 @@ var init_tool_kind_emoji = __esm(() => {
|
|
|
24026
24140
|
function createStreamingPromptState(formatToolCalls = false, options) {
|
|
24027
24141
|
let toolEventMode;
|
|
24028
24142
|
let onToolEvent;
|
|
24143
|
+
let onThought;
|
|
24029
24144
|
if (options === undefined) {
|
|
24030
24145
|
toolEventMode = "text";
|
|
24031
24146
|
onToolEvent = undefined;
|
|
@@ -24034,6 +24149,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
24034
24149
|
toolEventMode = "structured";
|
|
24035
24150
|
} else {
|
|
24036
24151
|
onToolEvent = options.onToolEvent;
|
|
24152
|
+
onThought = options.onThought;
|
|
24037
24153
|
toolEventMode = resolveToolEventMode({
|
|
24038
24154
|
toolEventMode: options.mode,
|
|
24039
24155
|
onToolEvent
|
|
@@ -24048,6 +24164,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
24048
24164
|
emittedToolCallIds: new Set,
|
|
24049
24165
|
toolEventMode,
|
|
24050
24166
|
onToolEvent,
|
|
24167
|
+
onThought,
|
|
24051
24168
|
finalize() {
|
|
24052
24169
|
if (this.pendingLine.trim().length > 0) {
|
|
24053
24170
|
parseStreamingChunks(this, this.pendingLine);
|
|
@@ -24106,6 +24223,14 @@ function parseStreamingChunks(state, line) {
|
|
|
24106
24223
|
}
|
|
24107
24224
|
return;
|
|
24108
24225
|
}
|
|
24226
|
+
const isThoughtChunk = update.sessionUpdate === "agent_thought_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
24227
|
+
if (isThoughtChunk) {
|
|
24228
|
+
const chunk2 = update.content.text;
|
|
24229
|
+
if (chunk2.length > 0) {
|
|
24230
|
+
state.onThought?.(chunk2);
|
|
24231
|
+
}
|
|
24232
|
+
return;
|
|
24233
|
+
}
|
|
24109
24234
|
const isMessageChunk = update.sessionUpdate === "agent_message_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
24110
24235
|
if (!isMessageChunk)
|
|
24111
24236
|
return;
|
|
@@ -24133,7 +24258,7 @@ function formatToolCallEvent(update, sessionUpdate) {
|
|
|
24133
24258
|
if (title.length === 0)
|
|
24134
24259
|
return null;
|
|
24135
24260
|
const emoji2 = TOOL_KIND_EMOJI[kind] ?? DEFAULT_TOOL_EMOJI;
|
|
24136
|
-
const inputSummary = summarizeToolInput(update.rawInput, title);
|
|
24261
|
+
const inputSummary = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
24137
24262
|
const status = readString(update, "status");
|
|
24138
24263
|
if (!inputSummary && status === "pending")
|
|
24139
24264
|
return null;
|
|
@@ -24164,15 +24289,23 @@ function buildToolUseEvent(update) {
|
|
|
24164
24289
|
})();
|
|
24165
24290
|
const title = (update.title ?? "").trim();
|
|
24166
24291
|
const toolName = title || "Tool";
|
|
24167
|
-
const summaryRaw = summarizeToolInput(update.rawInput, title);
|
|
24292
|
+
const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
24168
24293
|
const summary = summaryRaw && summaryRaw !== title ? summaryRaw : undefined;
|
|
24169
24294
|
const statusRaw = readString(update, "status");
|
|
24170
24295
|
const status = statusRaw === "completed" || statusRaw === "success" ? "success" : statusRaw === "failed" || statusRaw === "error" ? "error" : "running";
|
|
24296
|
+
const rawInput = update.rawInput;
|
|
24297
|
+
const content = update.content;
|
|
24298
|
+
const rawOutput = update.rawOutput;
|
|
24299
|
+
const locations = update.locations;
|
|
24171
24300
|
return {
|
|
24172
24301
|
toolCallId,
|
|
24173
24302
|
toolName,
|
|
24174
24303
|
kind,
|
|
24175
24304
|
...summary ? { summary } : {},
|
|
24305
|
+
...rawInput !== undefined ? { rawInput } : {},
|
|
24306
|
+
...content !== undefined ? { content } : {},
|
|
24307
|
+
...rawOutput !== undefined ? { rawOutput } : {},
|
|
24308
|
+
...locations !== undefined ? { locations } : {},
|
|
24176
24309
|
status
|
|
24177
24310
|
};
|
|
24178
24311
|
}
|
|
@@ -24333,6 +24466,8 @@ function buildQueueOwnerPayload(input) {
|
|
|
24333
24466
|
nonInteractivePermissions: input.nonInteractivePermissions,
|
|
24334
24467
|
ttlMs: input.ttlMs ?? 300000,
|
|
24335
24468
|
maxQueueDepth: input.maxQueueDepth ?? 16,
|
|
24469
|
+
...Number.isFinite(input.promptRetries) ? { promptRetries: input.promptRetries } : {},
|
|
24470
|
+
...input.sessionOptions ? { sessionOptions: input.sessionOptions } : {},
|
|
24336
24471
|
mcpServers: input.mcpServers
|
|
24337
24472
|
};
|
|
24338
24473
|
}
|
|
@@ -24585,6 +24720,7 @@ class AcpxCliTransport {
|
|
|
24585
24720
|
sessionInitTimeoutMs;
|
|
24586
24721
|
permissionMode;
|
|
24587
24722
|
nonInteractivePermissions;
|
|
24723
|
+
permissionPolicy;
|
|
24588
24724
|
runCommand;
|
|
24589
24725
|
runPtyCommand;
|
|
24590
24726
|
queueOwnerLauncher;
|
|
@@ -24594,6 +24730,7 @@ class AcpxCliTransport {
|
|
|
24594
24730
|
this.sessionInitTimeoutMs = options.sessionInitTimeoutMs ?? 120000;
|
|
24595
24731
|
this.permissionMode = options.permissionMode ?? "approve-all";
|
|
24596
24732
|
this.nonInteractivePermissions = options.nonInteractivePermissions ?? "deny";
|
|
24733
|
+
this.permissionPolicy = options.permissionPolicy;
|
|
24597
24734
|
this.runCommand = runCommand;
|
|
24598
24735
|
this.runPtyCommand = runPtyCommand;
|
|
24599
24736
|
this.queueOwnerLauncher = queueOwnerLauncher ?? new AcpxQueueOwnerLauncher({
|
|
@@ -24613,18 +24750,38 @@ class AcpxCliTransport {
|
|
|
24613
24750
|
timeoutMs: this.sessionInitTimeoutMs
|
|
24614
24751
|
});
|
|
24615
24752
|
}
|
|
24753
|
+
async tailSessionHistory(session, lines) {
|
|
24754
|
+
const candidates = [
|
|
24755
|
+
["sessions", "history", "quiet", "-s", session.transportSession, String(lines)],
|
|
24756
|
+
["sessions", "history", "quiet", session.transportSession, String(lines)],
|
|
24757
|
+
["sessions", "history", "-s", session.transportSession, "--tail", String(lines)],
|
|
24758
|
+
["sessions", "history", session.transportSession, "--tail", String(lines)],
|
|
24759
|
+
["sessions", "history", "--name", session.transportSession, "--tail", String(lines)]
|
|
24760
|
+
];
|
|
24761
|
+
let lastResult;
|
|
24762
|
+
for (const tail2 of candidates) {
|
|
24763
|
+
const args = this.buildArgs(session, tail2);
|
|
24764
|
+
const result = await this.runCommandWithTimeout(this.runCommand, args);
|
|
24765
|
+
if (result.code === 0) {
|
|
24766
|
+
return { text: result.stdout.trimEnd() };
|
|
24767
|
+
}
|
|
24768
|
+
lastResult = result;
|
|
24769
|
+
}
|
|
24770
|
+
const detail = lastResult ? normalizeCommandError(lastResult) ?? `command failed with exit code ${lastResult.code}` : "command failed";
|
|
24771
|
+
throw new Error(detail);
|
|
24772
|
+
}
|
|
24616
24773
|
async prompt(session, text, reply, replyContext, options) {
|
|
24617
24774
|
await this.launchMcpQueueOwnerIfNeeded(session);
|
|
24618
24775
|
const structuredPrompt = await createStructuredPromptFile(text, options?.media);
|
|
24619
24776
|
const args = this.buildPromptArgs(session, text, structuredPrompt?.filePath);
|
|
24620
24777
|
try {
|
|
24621
|
-
if (reply || options?.onSegment || options?.onToolEvent) {
|
|
24778
|
+
if (reply || options?.onSegment || options?.onToolEvent || options?.onThought) {
|
|
24622
24779
|
const formatToolCalls = (session.replyMode ?? "verbose") === "verbose";
|
|
24623
24780
|
let toolEventMode = resolveToolEventMode(options);
|
|
24624
24781
|
if ((toolEventMode === "structured" || toolEventMode === "both") && !options?.onToolEvent) {
|
|
24625
24782
|
toolEventMode = "text";
|
|
24626
24783
|
}
|
|
24627
|
-
const { result: result2, overflowCount } = await this.runStreamingPrompt(this.command, args, reply, formatToolCalls, toolEventMode, replyContext, options?.onSegment, options?.onToolEvent);
|
|
24784
|
+
const { result: result2, overflowCount } = await this.runStreamingPrompt(this.command, args, reply, formatToolCalls, toolEventMode, replyContext, options?.onSegment, options?.onToolEvent, options?.onThought);
|
|
24628
24785
|
const baseText = getPromptText(result2);
|
|
24629
24786
|
if (!reply) {
|
|
24630
24787
|
return { text: baseText };
|
|
@@ -24664,6 +24821,7 @@ ${baseText}` : "" };
|
|
|
24664
24821
|
async updatePermissionPolicy(policy) {
|
|
24665
24822
|
this.permissionMode = policy.permissionMode;
|
|
24666
24823
|
this.nonInteractivePermissions = policy.nonInteractivePermissions;
|
|
24824
|
+
this.permissionPolicy = policy.permissionPolicy;
|
|
24667
24825
|
}
|
|
24668
24826
|
async removeSession(session) {
|
|
24669
24827
|
const result = await this.runCommand(this.command, this.buildArgs(session, [
|
|
@@ -24761,7 +24919,7 @@ ${baseText}` : "" };
|
|
|
24761
24919
|
})
|
|
24762
24920
|
]);
|
|
24763
24921
|
}
|
|
24764
|
-
async runStreamingPrompt(command, args, reply, formatToolCalls = false, toolEventMode = "text", replyContext, onSegment, onToolEvent) {
|
|
24922
|
+
async runStreamingPrompt(command, args, reply, formatToolCalls = false, toolEventMode = "text", replyContext, onSegment, onToolEvent, onThought) {
|
|
24765
24923
|
const hooks = this.streamingHooks;
|
|
24766
24924
|
const doSpawn = hooks.spawnPrompt ?? ((cmd, spawnArgs) => spawn9(cmd, spawnArgs, { stdio: ["ignore", "pipe", "pipe"] }));
|
|
24767
24925
|
const setIntervalFn = hooks.setIntervalFn ?? ((fn, delay) => setInterval(fn, delay));
|
|
@@ -24779,7 +24937,10 @@ ${baseText}` : "" };
|
|
|
24779
24937
|
let segmentError;
|
|
24780
24938
|
let toolEventChain = Promise.resolve();
|
|
24781
24939
|
let toolEventError;
|
|
24940
|
+
let thoughtChain = Promise.resolve();
|
|
24941
|
+
let thoughtError;
|
|
24782
24942
|
const userOnToolEvent = onToolEvent;
|
|
24943
|
+
const userOnThought = onThought;
|
|
24783
24944
|
const state = createStreamingPromptState(formatToolCalls, {
|
|
24784
24945
|
mode: toolEventMode,
|
|
24785
24946
|
...userOnToolEvent ? {
|
|
@@ -24788,6 +24949,13 @@ ${baseText}` : "" };
|
|
|
24788
24949
|
toolEventError ??= error2;
|
|
24789
24950
|
});
|
|
24790
24951
|
}
|
|
24952
|
+
} : {},
|
|
24953
|
+
...userOnThought ? {
|
|
24954
|
+
onThought: (chunk) => {
|
|
24955
|
+
thoughtChain = thoughtChain.then(() => userOnThought(chunk)).catch((error2) => {
|
|
24956
|
+
thoughtError ??= error2;
|
|
24957
|
+
});
|
|
24958
|
+
}
|
|
24791
24959
|
} : {}
|
|
24792
24960
|
});
|
|
24793
24961
|
const sink = reply ? createQuotaGatedReplySink({
|
|
@@ -24840,7 +25008,8 @@ ${baseText}` : "" };
|
|
|
24840
25008
|
Promise.all([
|
|
24841
25009
|
sink?.drain({ timeoutMs: 30000 }) ?? Promise.resolve(),
|
|
24842
25010
|
segmentChain,
|
|
24843
|
-
toolEventChain
|
|
25011
|
+
toolEventChain,
|
|
25012
|
+
thoughtChain
|
|
24844
25013
|
]).then(() => {
|
|
24845
25014
|
const deferred = sink?.getPendingError();
|
|
24846
25015
|
if (deferred) {
|
|
@@ -24855,6 +25024,10 @@ ${baseText}` : "" };
|
|
|
24855
25024
|
reject(toolEventError);
|
|
24856
25025
|
return;
|
|
24857
25026
|
}
|
|
25027
|
+
if (thoughtError) {
|
|
25028
|
+
reject(thoughtError);
|
|
25029
|
+
return;
|
|
25030
|
+
}
|
|
24858
25031
|
resolve3({
|
|
24859
25032
|
result: { code: code ?? 1, stdout: stdout2, stderr },
|
|
24860
25033
|
overflowCount
|
|
@@ -24895,7 +25068,11 @@ ${baseText}` : "" };
|
|
|
24895
25068
|
}
|
|
24896
25069
|
buildPermissionArgs() {
|
|
24897
25070
|
const modeFlag = permissionModeToFlag(this.permissionMode);
|
|
24898
|
-
|
|
25071
|
+
const args = [modeFlag, "--non-interactive-permissions", this.nonInteractivePermissions];
|
|
25072
|
+
if (typeof this.permissionPolicy === "string" && this.permissionPolicy.trim().length > 0) {
|
|
25073
|
+
args.push("--permission-policy", this.permissionPolicy);
|
|
25074
|
+
}
|
|
25075
|
+
return args;
|
|
24899
25076
|
}
|
|
24900
25077
|
}
|
|
24901
25078
|
function isMissingAcpxSessionError(stderr, stdout2) {
|
|
@@ -25876,7 +26053,11 @@ import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
|
25876
26053
|
import { homedir as homedir10 } from "node:os";
|
|
25877
26054
|
async function checkDaemon(options = {}) {
|
|
25878
26055
|
const home = options.home ?? process.env.HOME ?? homedir10();
|
|
25879
|
-
const
|
|
26056
|
+
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
26057
|
+
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
26058
|
+
home,
|
|
26059
|
+
...runtimeDir ? { runtimeDir } : {}
|
|
26060
|
+
});
|
|
25880
26061
|
const controller = createDaemonController(paths, {
|
|
25881
26062
|
processExecPath: options.processExecPath ?? process.execPath,
|
|
25882
26063
|
cliEntryPath: options.cliEntryPath ?? resolveCliEntryPath(),
|
|
@@ -26028,7 +26209,11 @@ import { dirname as dirname14 } from "node:path";
|
|
|
26028
26209
|
import { homedir as homedir11 } from "node:os";
|
|
26029
26210
|
async function checkRuntime(options = {}) {
|
|
26030
26211
|
const home = options.home ?? process.env.HOME ?? homedir11();
|
|
26031
|
-
const
|
|
26212
|
+
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
26213
|
+
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
26214
|
+
home,
|
|
26215
|
+
...runtimeDir ? { runtimeDir } : {}
|
|
26216
|
+
});
|
|
26032
26217
|
const probe = options.probe ?? createRuntimeFsProbe();
|
|
26033
26218
|
const platform = options.platform ?? process.platform;
|
|
26034
26219
|
const checks3 = [
|
|
@@ -26591,10 +26776,12 @@ async function runDoctor(options = {}, deps = {}) {
|
|
|
26591
26776
|
resolveRuntimePaths: () => runtimePaths
|
|
26592
26777
|
}));
|
|
26593
26778
|
checks3.push(await (deps.checkRuntime ?? checkRuntime)({
|
|
26594
|
-
home
|
|
26779
|
+
home,
|
|
26780
|
+
configPath: runtimePaths.configPath
|
|
26595
26781
|
}));
|
|
26596
26782
|
checks3.push(await (deps.checkDaemon ?? checkDaemon)({
|
|
26597
|
-
home
|
|
26783
|
+
home,
|
|
26784
|
+
configPath: runtimePaths.configPath
|
|
26598
26785
|
}));
|
|
26599
26786
|
checks3.push(await (deps.checkWechat ?? checkWechat)({
|
|
26600
26787
|
verbose: options.verbose
|
|
@@ -42311,7 +42498,7 @@ async function runCli(args, deps = {}) {
|
|
|
42311
42498
|
case "mcp-stdio":
|
|
42312
42499
|
return await (deps.mcpStdio ?? ((subArgs) => defaultMcpStdio(subArgs, { stderr: deps.stderr })))(args.slice(1));
|
|
42313
42500
|
case "start": {
|
|
42314
|
-
const controller = deps.controller ?? createDefaultController();
|
|
42501
|
+
const controller = deps.controller ?? createDefaultController(deps);
|
|
42315
42502
|
try {
|
|
42316
42503
|
const isInteractive = deps.isInteractive ?? defaultIsInteractive;
|
|
42317
42504
|
const status = await controller.getStatus();
|
|
@@ -42354,7 +42541,7 @@ async function runCli(args, deps = {}) {
|
|
|
42354
42541
|
}
|
|
42355
42542
|
}
|
|
42356
42543
|
case "status": {
|
|
42357
|
-
const controller = deps.controller ?? createDefaultController();
|
|
42544
|
+
const controller = deps.controller ?? createDefaultController(deps);
|
|
42358
42545
|
const status = await controller.getStatus();
|
|
42359
42546
|
if (status.state === "indeterminate") {
|
|
42360
42547
|
print("weacpx 进程仍在运行,但状态元数据缺失");
|
|
@@ -42377,7 +42564,7 @@ async function runCli(args, deps = {}) {
|
|
|
42377
42564
|
return 0;
|
|
42378
42565
|
}
|
|
42379
42566
|
case "stop": {
|
|
42380
|
-
const controller = deps.controller ?? createDefaultController();
|
|
42567
|
+
const controller = deps.controller ?? createDefaultController(deps);
|
|
42381
42568
|
const result = await controller.stop();
|
|
42382
42569
|
if (result.detail === "not-running") {
|
|
42383
42570
|
print("weacpx 未运行");
|
|
@@ -42387,7 +42574,7 @@ async function runCli(args, deps = {}) {
|
|
|
42387
42574
|
return 0;
|
|
42388
42575
|
}
|
|
42389
42576
|
case "restart": {
|
|
42390
|
-
const controller = deps.controller ?? createDefaultController();
|
|
42577
|
+
const controller = deps.controller ?? createDefaultController(deps);
|
|
42391
42578
|
try {
|
|
42392
42579
|
return await restartDaemonCli(controller, print);
|
|
42393
42580
|
} catch (error2) {
|
|
@@ -42600,8 +42787,18 @@ async function agentRemove(rawName, print) {
|
|
|
42600
42787
|
print(`Agent「${name}」已删除`);
|
|
42601
42788
|
return 0;
|
|
42602
42789
|
}
|
|
42790
|
+
function resolveConfigPathForCurrentEnv() {
|
|
42791
|
+
return process.env.WEACPX_CONFIG ?? `${requireHome2()}/.weacpx/config.json`;
|
|
42792
|
+
}
|
|
42793
|
+
function resolveDaemonPathsForCurrentConfig() {
|
|
42794
|
+
const configPath = resolveConfigPathForCurrentEnv();
|
|
42795
|
+
return resolveDaemonPaths({
|
|
42796
|
+
home: requireHome2(),
|
|
42797
|
+
runtimeDir: resolveRuntimeDirFromConfigPath(configPath)
|
|
42798
|
+
});
|
|
42799
|
+
}
|
|
42603
42800
|
async function createCliConfigStore() {
|
|
42604
|
-
const configPath =
|
|
42801
|
+
const configPath = resolveConfigPathForCurrentEnv();
|
|
42605
42802
|
await ensureConfigExists(configPath);
|
|
42606
42803
|
return new ConfigStore(configPath);
|
|
42607
42804
|
}
|
|
@@ -42636,7 +42833,7 @@ async function defaultRun(options = {}) {
|
|
|
42636
42833
|
await loadConfiguredPlugins2({ plugins: config2.plugins });
|
|
42637
42834
|
const { createMessageChannels: createMessageChannels2 } = await Promise.resolve().then(() => (init_create_channel(), exports_create_channel));
|
|
42638
42835
|
const { MessageChannelRegistry: MessageChannelRegistry2 } = await Promise.resolve().then(() => (init_channel_registry(), exports_channel_registry));
|
|
42639
|
-
const daemonPaths =
|
|
42836
|
+
const daemonPaths = resolveDaemonPathsForCurrentConfig();
|
|
42640
42837
|
const daemonRuntime = new DaemonRuntime(daemonPaths, { pid: process.pid });
|
|
42641
42838
|
const { channelDeps } = await prepareChannelMedia2(runtimePaths.configPath, config2);
|
|
42642
42839
|
const channelRegistry = new MessageChannelRegistry2(createMessageChannels2(config2.channels, channelDeps));
|
|
@@ -42882,13 +43079,14 @@ async function defaultPromptSecret(message) {
|
|
|
42882
43079
|
process.stdin.on("data", onData);
|
|
42883
43080
|
});
|
|
42884
43081
|
}
|
|
42885
|
-
function createDefaultController() {
|
|
42886
|
-
const daemonPaths =
|
|
43082
|
+
function createDefaultController(deps = {}) {
|
|
43083
|
+
const daemonPaths = resolveDaemonPathsForCurrentConfig();
|
|
42887
43084
|
const controller = createDaemonController(daemonPaths, {
|
|
42888
43085
|
processExecPath: process.execPath,
|
|
42889
43086
|
cliEntryPath: resolveCliEntryPath2(),
|
|
42890
43087
|
cwd: process.cwd(),
|
|
42891
|
-
env: process.env
|
|
43088
|
+
env: process.env,
|
|
43089
|
+
...deps.isProcessRunning ? { isProcessRunning: deps.isProcessRunning } : {}
|
|
42892
43090
|
});
|
|
42893
43091
|
return {
|
|
42894
43092
|
getStatus: () => controller.getStatus(),
|
|
@@ -42944,8 +43142,8 @@ function printDaemonLogHints(print) {
|
|
|
42944
43142
|
}
|
|
42945
43143
|
function safeDaemonLogPaths() {
|
|
42946
43144
|
try {
|
|
42947
|
-
const configPath =
|
|
42948
|
-
const paths =
|
|
43145
|
+
const configPath = resolveConfigPathForCurrentEnv();
|
|
43146
|
+
const paths = resolveDaemonPathsForCurrentConfig();
|
|
42949
43147
|
return {
|
|
42950
43148
|
appLog: join16(dirname15(configPath), "runtime", "app.log"),
|
|
42951
43149
|
stderrLog: paths.stderrLog
|
package/dist/config/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface TransportConfig {
|
|
|
18
18
|
sessionInitTimeoutMs?: number;
|
|
19
19
|
permissionMode: PermissionMode;
|
|
20
20
|
nonInteractivePermissions: NonInteractivePermissions;
|
|
21
|
+
permissionPolicy?: string;
|
|
21
22
|
}
|
|
22
23
|
export type LoggingLevel = "error" | "info" | "debug";
|
|
23
24
|
export interface PerfLogConfig {
|
|
@@ -46,6 +46,8 @@ export interface ChatRequest {
|
|
|
46
46
|
abortSignal?: AbortSignal;
|
|
47
47
|
/** Structured tool-use side-channel; see PromptOptions.onToolEvent. */
|
|
48
48
|
onToolEvent?: (event: ToolUseEvent) => void | Promise<void>;
|
|
49
|
+
/** Structured thinking side-channel; see PromptOptions.onThought. */
|
|
50
|
+
onThought?: (chunk: string) => void | Promise<void>;
|
|
49
51
|
/**
|
|
50
52
|
* Optional per-turn performance tracing span. When `logging.perf.enabled` is
|
|
51
53
|
* true, the channel handler attaches a `PerfSpan` so downstream layers can
|
|
@@ -57,7 +57,7 @@ export type ResolvedWeixinAccount = {
|
|
|
57
57
|
/** true when a token has been obtained via QR login. */
|
|
58
58
|
configured: boolean;
|
|
59
59
|
};
|
|
60
|
-
/** List accountIds from the index file (written at QR login). */
|
|
60
|
+
/** List accountIds from the index file (written at QR login), with a credential-file fallback for legacy/broken indexes. */
|
|
61
61
|
export declare function listWeixinAccountIds(): string[];
|
|
62
62
|
/** Resolve a weixin account by ID, reading stored credentials. */
|
|
63
63
|
export declare function resolveWeixinAccount(accountId?: string | null): ResolvedWeixinAccount;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "weacpx",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "使用微信 ClawBot 随时随地通过 `acpx` 控制 Claude Code、Codex 等 Agents。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acpx",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
68
|
-
"acpx": "^0.
|
|
68
|
+
"acpx": "^0.8.0",
|
|
69
69
|
"node-pty": "^1.1.0",
|
|
70
70
|
"proper-lockfile": "^4.1.2",
|
|
71
71
|
"protobufjs": "^7.5.6",
|