@unlinearity/cli-wechat-bridge 1.0.9 → 1.1.1
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 +30 -0
- package/dist/bridge/bridge-adapters.claude.js +186 -5
- package/dist/bridge/bridge-adapters.codex.js +58 -24
- package/dist/bridge/bridge-adapters.core.js +39 -5
- package/dist/bridge/bridge-adapters.opencode.js +6 -2
- package/dist/bridge/bridge-adapters.shared.js +104 -1
- package/dist/bridge/bridge-adapters.shell.js +1 -1
- package/dist/bridge/bridge-utils.js +36 -12
- package/dist/bridge/claude-hooks.js +9 -16
- package/dist/bridge/wechat-bridge.js +64 -10
- package/dist/companion/local-companion.js +1 -0
- package/dist/daemon/emoji-bindings.js +31 -0
- package/dist/daemon/wechat-daemon.js +61 -75
- package/dist/i18n/index.js +32 -0
- package/dist/i18n/messages-en.js +125 -0
- package/dist/i18n/messages-zh.js +125 -0
- package/dist/runtime/legacy-adapter-runtime.js +3 -0
- package/dist/utils/doctor.js +540 -0
- package/dist/wechat/channel-config.js +2 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { execFileSync, spawn } from "node:child_process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { resolveDefaultAdapterCommand, } from "../bridge/bridge-adapters.js";
|
|
8
|
+
import { t } from "../i18n/index.js";
|
|
8
9
|
import { delay, getSharedSessionIdFromAdapterState, quoteWindowsCommandArg, } from "../bridge/bridge-adapters.shared.js";
|
|
9
10
|
import { BridgeController } from "../bridge/bridge-controller.js";
|
|
10
11
|
import { forwardWechatFinalReply } from "../bridge/bridge-final-reply.js";
|
|
@@ -14,7 +15,7 @@ import { buildOneTimeCode, buildWechatInboundPrompt, formatApprovalMessage, form
|
|
|
14
15
|
import { formatUserFacingBridgeFatalError, formatUserFacingInboundError, formatWechatContextTokenStaleLogEntry, formatWechatSendFailureLogEntry, isRetryableWechatSendError, shouldForwardBridgeEventToWechat, } from "../bridge/wechat-bridge.js";
|
|
15
16
|
import { BRIDGE_LOCK_FILE, BRIDGE_LOG_FILE, ensureChannelDataDir, migrateLegacyChannelFiles, } from "../wechat/channel-config.js";
|
|
16
17
|
import { ensureWechatCredentials } from "../wechat/setup.js";
|
|
17
|
-
import { listBindings, loadEmojiBindings, removeBinding, resolveEmojiCommand, setBinding, } from "./emoji-bindings.js";
|
|
18
|
+
import { formatBindCommandUsage, formatBindingsListMessage, isBindCommandPrefix, listBindings, loadEmojiBindings, parseEmojiBindingsCommand, removeBinding, resolveEmojiCommand, setBinding, } from "./emoji-bindings.js";
|
|
18
19
|
import { classifyWechatTransportError, DEFAULT_LONG_POLL_TIMEOUT_MS, describeWechatTransportError, isWechatContextTokenStaleError, WeChatTransport, } from "../wechat/wechat-transport.js";
|
|
19
20
|
import { createRuntimeHost, } from "../runtime/create-runtime-host.js";
|
|
20
21
|
import { clearLocalCompanionEndpoint, clearLocalCompanionOccupancy, readLocalCompanionEndpoint, } from "../companion/local-companion-link.js";
|
|
@@ -136,22 +137,6 @@ export function parseDaemonSwitchCommand(text) {
|
|
|
136
137
|
return null;
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
|
-
export function parseEmojiBindingsCommand(text) {
|
|
140
|
-
const trimmed = text.trim();
|
|
141
|
-
const lower = trimmed.toLowerCase();
|
|
142
|
-
if (lower === "/bindings") {
|
|
143
|
-
return { type: "list" };
|
|
144
|
-
}
|
|
145
|
-
const bindMatch = trimmed.match(/^\/bind\s+(\[[^\]]+\])\s+(.+)$/i);
|
|
146
|
-
if (bindMatch) {
|
|
147
|
-
return { type: "bind", emoji: bindMatch[1], command: bindMatch[2].trim() };
|
|
148
|
-
}
|
|
149
|
-
const unbindMatch = trimmed.match(/^\/unbind\s+(\[[^\]]+\])$/i);
|
|
150
|
-
if (unbindMatch) {
|
|
151
|
-
return { type: "unbind", emoji: unbindMatch[1] };
|
|
152
|
-
}
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
140
|
export function defaultDaemonSessionStartMode(adapter) {
|
|
156
141
|
return adapter === "claude" || adapter === "opencode" ? "new" : "restore";
|
|
157
142
|
}
|
|
@@ -538,7 +523,7 @@ class WechatDaemon {
|
|
|
538
523
|
status: slot.runtime.getState().status,
|
|
539
524
|
cwd: this.cwd,
|
|
540
525
|
companionPid: endpoint?.companionPid,
|
|
541
|
-
pendingApproval:
|
|
526
|
+
pendingApproval: slot.pendingConfirmations.length > 0,
|
|
542
527
|
pendingUserInput: Boolean(slot.pendingUserInput),
|
|
543
528
|
};
|
|
544
529
|
}),
|
|
@@ -559,6 +544,13 @@ class WechatDaemon {
|
|
|
559
544
|
log(`Working directory: ${this.cwd}`);
|
|
560
545
|
log("Switch from WeChat with /codex, /claude, or /opencode.");
|
|
561
546
|
appendDaemonLog(`started: cwd=${this.cwd}`);
|
|
547
|
+
const activeSlot = this.getActiveSlot();
|
|
548
|
+
const welcomeText = t("daemon.welcome", {
|
|
549
|
+
cwd: this.cwd,
|
|
550
|
+
adapter: activeSlot?.adapter ?? "none",
|
|
551
|
+
bindings: formatBindingsListMessage(listBindings()),
|
|
552
|
+
});
|
|
553
|
+
await this.queueWechatMessage(this.authorizedUserId, welcomeText);
|
|
562
554
|
while (!this.shutdownPromise) {
|
|
563
555
|
let pollResult;
|
|
564
556
|
try {
|
|
@@ -773,7 +765,7 @@ class WechatDaemon {
|
|
|
773
765
|
outputBatcher: new OutputBatcher(async (text) => {
|
|
774
766
|
await this.queueWechatMessage(this.authorizedUserId, prefixDaemonAdapterMessage(adapter, text));
|
|
775
767
|
}),
|
|
776
|
-
|
|
768
|
+
pendingConfirmations: [],
|
|
777
769
|
pendingUserInput: null,
|
|
778
770
|
activeTask: null,
|
|
779
771
|
lastOutputAt: 0,
|
|
@@ -789,7 +781,7 @@ class WechatDaemon {
|
|
|
789
781
|
async startFreshSlotSession(slot) {
|
|
790
782
|
await slot.outputBatcher.flushNow();
|
|
791
783
|
slot.outputBatcher.clear();
|
|
792
|
-
slot.
|
|
784
|
+
slot.pendingConfirmations = [];
|
|
793
785
|
slot.pendingUserInput = null;
|
|
794
786
|
slot.activeTask = null;
|
|
795
787
|
if (slot.adapter === "claude") {
|
|
@@ -806,8 +798,8 @@ class WechatDaemon {
|
|
|
806
798
|
handleSlotEvent(slot, event) {
|
|
807
799
|
slot.controller.syncLocalClientEndpoint();
|
|
808
800
|
const adapterState = slot.runtime.getState();
|
|
809
|
-
if (slot.
|
|
810
|
-
slot.
|
|
801
|
+
if (slot.pendingConfirmations.length > 0 && !adapterState.pendingApproval) {
|
|
802
|
+
slot.pendingConfirmations = [];
|
|
811
803
|
}
|
|
812
804
|
if (slot.pendingUserInput && !adapterState.pendingUserInput) {
|
|
813
805
|
slot.pendingUserInput = null;
|
|
@@ -869,7 +861,7 @@ class WechatDaemon {
|
|
|
869
861
|
case "approval_required":
|
|
870
862
|
this.trackWechatForwardTask(slot.outputBatcher.flushNow().then(async () => {
|
|
871
863
|
const pending = toPendingApproval(event);
|
|
872
|
-
slot.
|
|
864
|
+
slot.pendingConfirmations.push(pending);
|
|
873
865
|
appendDaemonLog(`approval_required: adapter=${slot.adapter} source=${pending.source} command=${truncatePreview(pending.commandPreview)}`);
|
|
874
866
|
await this.queueWechatMessage(this.authorizedUserId, prefixDaemonAdapterMessage(slot.adapter, formatApprovalMessage(pending, adapterState)), "approval_required");
|
|
875
867
|
}));
|
|
@@ -918,14 +910,14 @@ class WechatDaemon {
|
|
|
918
910
|
break;
|
|
919
911
|
case "task_complete":
|
|
920
912
|
this.trackWechatForwardTask(slot.outputBatcher.flushNow().then(() => {
|
|
921
|
-
slot.
|
|
913
|
+
slot.pendingConfirmations = [];
|
|
922
914
|
slot.pendingUserInput = null;
|
|
923
915
|
slot.activeTask = null;
|
|
924
916
|
}));
|
|
925
917
|
break;
|
|
926
918
|
case "task_failed":
|
|
927
919
|
this.trackWechatForwardTask(slot.outputBatcher.flushNow().then(async () => {
|
|
928
|
-
slot.
|
|
920
|
+
slot.pendingConfirmations = [];
|
|
929
921
|
slot.pendingUserInput = null;
|
|
930
922
|
slot.activeTask = null;
|
|
931
923
|
await this.queueWechatMessage(this.authorizedUserId, prefixDaemonAdapterMessage(slot.adapter, formatTaskFailedMessage(slot.adapter, event.message)), "task_failed");
|
|
@@ -934,7 +926,7 @@ class WechatDaemon {
|
|
|
934
926
|
case "fatal_error":
|
|
935
927
|
logError(`${slot.adapter}: ${event.message}`);
|
|
936
928
|
appendDaemonLog(`fatal_error: adapter=${slot.adapter} message=${event.message}`);
|
|
937
|
-
slot.
|
|
929
|
+
slot.pendingConfirmations = [];
|
|
938
930
|
slot.pendingUserInput = null;
|
|
939
931
|
slot.activeTask = null;
|
|
940
932
|
this.trackWechatForwardTask(slot.outputBatcher.flushNow().then(async () => {
|
|
@@ -1000,6 +992,10 @@ class WechatDaemon {
|
|
|
1000
992
|
await this.handleEmojiBindingsCommand(message.senderId, bindingsCmd);
|
|
1001
993
|
return;
|
|
1002
994
|
}
|
|
995
|
+
if (isBindCommandPrefix(message.text)) {
|
|
996
|
+
await this.queueWechatMessage(message.senderId, formatBindCommandUsage());
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
1003
999
|
const slot = this.getActiveSlot();
|
|
1004
1000
|
if (!slot) {
|
|
1005
1001
|
await this.queueWechatMessage(message.senderId, formatNoActiveAdapterMessage());
|
|
@@ -1007,15 +1003,15 @@ class WechatDaemon {
|
|
|
1007
1003
|
}
|
|
1008
1004
|
const command = parseWechatControlCommand(message.text, {
|
|
1009
1005
|
adapter: slot.adapter,
|
|
1010
|
-
hasPendingConfirmation:
|
|
1006
|
+
hasPendingConfirmation: slot.pendingConfirmations.length > 0,
|
|
1011
1007
|
hasPendingUserInput: Boolean(slot.pendingUserInput),
|
|
1012
1008
|
});
|
|
1013
1009
|
if (command) {
|
|
1014
1010
|
await this.handleSystemCommand(message, slot, command);
|
|
1015
1011
|
return;
|
|
1016
1012
|
}
|
|
1017
|
-
if (slot.
|
|
1018
|
-
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, formatPendingApprovalReminder(slot.
|
|
1013
|
+
if (slot.pendingConfirmations.length > 0) {
|
|
1014
|
+
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, formatPendingApprovalReminder(slot.pendingConfirmations[0], slot.runtime.getState())));
|
|
1019
1015
|
return;
|
|
1020
1016
|
}
|
|
1021
1017
|
if (slot.pendingUserInput) {
|
|
@@ -1032,13 +1028,7 @@ class WechatDaemon {
|
|
|
1032
1028
|
async handleEmojiBindingsCommand(senderId, cmd) {
|
|
1033
1029
|
switch (cmd.type) {
|
|
1034
1030
|
case "list": {
|
|
1035
|
-
|
|
1036
|
-
if (map.size === 0) {
|
|
1037
|
-
await this.queueWechatMessage(senderId, "No emoji bindings configured.");
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
const lines = Array.from(map.entries()).map(([emoji, command]) => `${emoji} → ${command}`);
|
|
1041
|
-
await this.queueWechatMessage(senderId, `Emoji bindings:\n${lines.join("\n")}`);
|
|
1031
|
+
await this.queueWechatMessage(senderId, formatBindingsListMessage(listBindings()));
|
|
1042
1032
|
return;
|
|
1043
1033
|
}
|
|
1044
1034
|
case "bind": {
|
|
@@ -1070,7 +1060,7 @@ class WechatDaemon {
|
|
|
1070
1060
|
}
|
|
1071
1061
|
await activeSlot.outputBatcher.flushNow();
|
|
1072
1062
|
activeSlot.outputBatcher.clear();
|
|
1073
|
-
activeSlot.
|
|
1063
|
+
activeSlot.pendingConfirmations = [];
|
|
1074
1064
|
activeSlot.pendingUserInput = null;
|
|
1075
1065
|
await activeSlot.runtime.createSession();
|
|
1076
1066
|
appendDaemonLog(`new_session: adapter=${activeSlot.adapter}`);
|
|
@@ -1085,14 +1075,14 @@ class WechatDaemon {
|
|
|
1085
1075
|
case "reset":
|
|
1086
1076
|
await activeSlot.outputBatcher.flushNow();
|
|
1087
1077
|
activeSlot.outputBatcher.clear();
|
|
1088
|
-
activeSlot.
|
|
1078
|
+
activeSlot.pendingConfirmations = [];
|
|
1089
1079
|
activeSlot.pendingUserInput = null;
|
|
1090
1080
|
await activeSlot.runtime.reset();
|
|
1091
1081
|
appendDaemonLog(`reset: adapter=${activeSlot.adapter}`);
|
|
1092
1082
|
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(activeSlot.adapter, "Worker session has been reset."));
|
|
1093
1083
|
return;
|
|
1094
1084
|
case "confirm":
|
|
1095
|
-
await this.confirmPendingApproval(message, activeSlot
|
|
1085
|
+
await this.confirmPendingApproval(message, activeSlot);
|
|
1096
1086
|
return;
|
|
1097
1087
|
case "deny":
|
|
1098
1088
|
await this.denyPendingApproval(message, activeSlot);
|
|
@@ -1102,51 +1092,42 @@ class WechatDaemon {
|
|
|
1102
1092
|
return;
|
|
1103
1093
|
}
|
|
1104
1094
|
}
|
|
1105
|
-
async confirmPendingApproval(message, activeSlot
|
|
1106
|
-
const slot = this.resolvePendingApprovalSlot(activeSlot
|
|
1107
|
-
if (!slot) {
|
|
1108
|
-
await this.queueWechatMessage(message.senderId, "No matching pending approval request.");
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
const pending = slot.pendingConfirmation;
|
|
1112
|
-
if (!pending) {
|
|
1095
|
+
async confirmPendingApproval(message, activeSlot) {
|
|
1096
|
+
const slot = this.resolvePendingApprovalSlot(activeSlot);
|
|
1097
|
+
if (!slot || slot.pendingConfirmations.length === 0) {
|
|
1113
1098
|
await this.queueWechatMessage(message.senderId, "No pending approval request.");
|
|
1114
1099
|
return;
|
|
1115
1100
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
return;
|
|
1119
|
-
}
|
|
1120
|
-
const confirmed = await slot.runtime.resolveApproval("confirm");
|
|
1121
|
-
if (!confirmed) {
|
|
1101
|
+
const count = await slot.runtime.resolveAllApprovals("confirm");
|
|
1102
|
+
if (!count) {
|
|
1122
1103
|
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, "The worker could not apply this approval request."));
|
|
1123
1104
|
return;
|
|
1124
1105
|
}
|
|
1125
|
-
slot.
|
|
1106
|
+
const preview = slot.pendingConfirmations[0]?.commandPreview ?? "";
|
|
1107
|
+
slot.pendingConfirmations = [];
|
|
1126
1108
|
slot.activeTask = {
|
|
1127
1109
|
startedAt: Date.now(),
|
|
1128
|
-
inputPreview:
|
|
1110
|
+
inputPreview: preview,
|
|
1129
1111
|
};
|
|
1130
|
-
appendDaemonLog(`approval_confirmed: adapter=${slot.adapter} command=${truncatePreview(
|
|
1131
|
-
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter,
|
|
1112
|
+
appendDaemonLog(`approval_confirmed: adapter=${slot.adapter} count=${count} command=${truncatePreview(preview)}`);
|
|
1113
|
+
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, count > 1
|
|
1114
|
+
? `${count} approvals confirmed. Continuing...`
|
|
1115
|
+
: "Approval confirmed. Continuing..."));
|
|
1132
1116
|
}
|
|
1133
1117
|
async denyPendingApproval(message, activeSlot) {
|
|
1134
|
-
const slot =
|
|
1135
|
-
|
|
1136
|
-
: Array.from(this.slots.values()).find((entry) => entry.pendingConfirmation) ?? activeSlot;
|
|
1137
|
-
const pending = slot.pendingConfirmation;
|
|
1138
|
-
if (!pending) {
|
|
1118
|
+
const slot = this.resolvePendingApprovalSlot(activeSlot);
|
|
1119
|
+
if (!slot || slot.pendingConfirmations.length === 0) {
|
|
1139
1120
|
await this.queueWechatMessage(message.senderId, "No pending approval request.");
|
|
1140
1121
|
return;
|
|
1141
1122
|
}
|
|
1142
|
-
const
|
|
1143
|
-
if (!
|
|
1123
|
+
const count = await slot.runtime.resolveAllApprovals("deny");
|
|
1124
|
+
if (!count) {
|
|
1144
1125
|
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, "The worker could not deny this approval request cleanly."));
|
|
1145
1126
|
return;
|
|
1146
1127
|
}
|
|
1147
|
-
slot.
|
|
1148
|
-
appendDaemonLog(`approval_denied: adapter=${slot.adapter}
|
|
1149
|
-
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, "Approval denied."));
|
|
1128
|
+
slot.pendingConfirmations = [];
|
|
1129
|
+
appendDaemonLog(`approval_denied: adapter=${slot.adapter} count=${count}`);
|
|
1130
|
+
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(slot.adapter, count > 1 ? `${count} approvals denied.` : "Approval denied."));
|
|
1150
1131
|
}
|
|
1151
1132
|
async answerPendingUserInput(message, activeSlot, raw) {
|
|
1152
1133
|
const pending = activeSlot.pendingUserInput;
|
|
@@ -1172,18 +1153,18 @@ class WechatDaemon {
|
|
|
1172
1153
|
appendDaemonLog(`user_input_answered: adapter=${activeSlot.adapter} preview=${parsed.preview}`);
|
|
1173
1154
|
await this.queueWechatMessage(message.senderId, prefixDaemonAdapterMessage(activeSlot.adapter, "Answer submitted. Continuing..."));
|
|
1174
1155
|
}
|
|
1175
|
-
resolvePendingApprovalSlot(activeSlot
|
|
1176
|
-
if (
|
|
1177
|
-
return (Array.from(this.slots.values()).find((slot) => slot.pendingConfirmation?.code === code) ?? null);
|
|
1178
|
-
}
|
|
1179
|
-
if (activeSlot.pendingConfirmation && this.countPendingApprovals() <= 1) {
|
|
1156
|
+
resolvePendingApprovalSlot(activeSlot) {
|
|
1157
|
+
if (activeSlot.pendingConfirmations.length > 0) {
|
|
1180
1158
|
return activeSlot;
|
|
1181
1159
|
}
|
|
1182
|
-
return null;
|
|
1160
|
+
return (Array.from(this.slots.values()).find((slot) => slot.pendingConfirmations.length > 0) ?? null);
|
|
1183
1161
|
}
|
|
1184
1162
|
countPendingApprovals() {
|
|
1185
|
-
|
|
1186
|
-
|
|
1163
|
+
let count = 0;
|
|
1164
|
+
for (const slot of this.slots.values()) {
|
|
1165
|
+
count += slot.pendingConfirmations.length;
|
|
1166
|
+
}
|
|
1167
|
+
return count;
|
|
1187
1168
|
}
|
|
1188
1169
|
getActiveSlot() {
|
|
1189
1170
|
if (!this.activeAdapter) {
|
|
@@ -1599,6 +1580,11 @@ export async function runDaemon(options) {
|
|
|
1599
1580
|
await daemon.runPollLoop();
|
|
1600
1581
|
}
|
|
1601
1582
|
export async function main(argv = process.argv.slice(2)) {
|
|
1583
|
+
if (argv.includes("--doctor")) {
|
|
1584
|
+
const { runDoctorCheck } = await import("../utils/doctor.js");
|
|
1585
|
+
await runDoctorCheck(argv, { mode: "daemon" });
|
|
1586
|
+
process.exit(0);
|
|
1587
|
+
}
|
|
1602
1588
|
try {
|
|
1603
1589
|
await runDaemon(parseDaemonCliArgs(argv));
|
|
1604
1590
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { messages as zhMessages } from "./messages-zh.js";
|
|
2
|
+
import { messages as enMessages } from "./messages-en.js";
|
|
3
|
+
const catalogs = {
|
|
4
|
+
zh: zhMessages,
|
|
5
|
+
en: enMessages,
|
|
6
|
+
};
|
|
7
|
+
let currentLocale = "zh";
|
|
8
|
+
export function getLocale() {
|
|
9
|
+
return currentLocale;
|
|
10
|
+
}
|
|
11
|
+
export function setLocale(locale) {
|
|
12
|
+
currentLocale = locale;
|
|
13
|
+
}
|
|
14
|
+
export function initLocaleFromEnv(env = process.env) {
|
|
15
|
+
const value = env.CLI_BRIDGE_LANG?.trim().toLowerCase();
|
|
16
|
+
if (value === "en" || value === "english") {
|
|
17
|
+
currentLocale = "en";
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
currentLocale = "zh";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function t(key, params) {
|
|
24
|
+
const catalog = catalogs[currentLocale];
|
|
25
|
+
let message = catalog[key] ?? catalogs.en[key] ?? key;
|
|
26
|
+
if (params) {
|
|
27
|
+
for (const [name, value] of Object.entries(params)) {
|
|
28
|
+
message = message.replaceAll(`{${name}}`, String(value));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return message;
|
|
32
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export const messages = {
|
|
2
|
+
// === Bridge welcome & control ===
|
|
3
|
+
"bridge.welcome": "WeChat Bridge ready ({adapter}).\nCWD: {cwd}\n\nCommands: /stop, /confirm, /deny, /status, /new\n{bindings}\n\nManage: /bind [emoji] cmd, /unbind [emoji], /bindings",
|
|
4
|
+
"bridge.stopped": "Bridge stopped.",
|
|
5
|
+
"bridge.interrupt.sent": "Interrupt signal sent.",
|
|
6
|
+
"bridge.interrupt.notBusy": "No active task to interrupt.",
|
|
7
|
+
"bridge.reset.done": "Worker session has been reset.",
|
|
8
|
+
"bridge.status.notRunning": "{adapter} adapter is not running.",
|
|
9
|
+
"bridge.status.busy": "{adapter} is still working on the previous request. Wait for it to finish or send /interrupt.",
|
|
10
|
+
"bridge.newSession.done": "New session started.",
|
|
11
|
+
"bridge.fatalError": "Bridge error: {message}",
|
|
12
|
+
// === Daemon welcome & control ===
|
|
13
|
+
"daemon.welcome": "WeChat Daemon ready.\nCWD: {cwd}\nActive: {adapter}\n\nCommands: /claude, /codex, /opencode, /stop, /confirm, /deny, /status\n{bindings}\n\nManage: /bind [emoji] cmd, /unbind [emoji], /bindings",
|
|
14
|
+
"daemon.noActiveAdapter": "No active terminal is selected. Send /codex, /claude, or /opencode to start one.",
|
|
15
|
+
"daemon.switchResult.new": "Started a new visible CLI.",
|
|
16
|
+
"daemon.switchResult.reused": "Reused the existing visible CLI.",
|
|
17
|
+
// === Approval ===
|
|
18
|
+
"approval.prompt": "{adapter} permission request.\n{summary}\n\nReply /confirm or /deny.",
|
|
19
|
+
"approval.confirmed": "Approval confirmed. Continuing...",
|
|
20
|
+
"approval.denied": "Approval denied.",
|
|
21
|
+
"approval.noPending": "No pending approval request.",
|
|
22
|
+
"approval.batchConfirmed": "Batch confirmed {count} approval(s).",
|
|
23
|
+
"approval.batchDenied": "Batch denied {count} approval(s).",
|
|
24
|
+
// === Hook health check ===
|
|
25
|
+
"hook.healthCheck.warning": "[Warning] No hook events received from Claude after 15s.\nThe hook system may not be working — Claude output will not reach WeChat.",
|
|
26
|
+
"hook.healthCheck.logHint": "\nCheck: {logPath}",
|
|
27
|
+
"hook.healthCheck.fixes": "\nCommon fixes:\n- Ensure Node.js >= 22.6.0: node --version\n- Reinstall: npm install -g cli-wechat-bridge@latest\n- Check firewall: allow localhost TCP connections",
|
|
28
|
+
// === PTY fallback ===
|
|
29
|
+
"pty.fallback.warning": "[Warning] PTY unavailable — using fallback mode (TERM=dumb).\nCore features (messaging, approvals, session management) work normally; terminal rendering (colors, progress bars) may be degraded.\nFix: Linux install build-essential python3 | Windows run npm rebuild node-pty | macOS run xcode-select --install\nRun --doctor for detailed environment info.\n",
|
|
30
|
+
// === Spawn diagnostic ===
|
|
31
|
+
"spawn.diagnostic.title": "Failed to start CLI process: {target}\nError: {error}",
|
|
32
|
+
"spawn.diagnostic.fixesHeader": "\nPossible fixes:",
|
|
33
|
+
"spawn.diagnostic.nodePty": "- The node-pty native module is incompatible with your Node.js version.\n- Run: npm rebuild node-pty\n- Or reinstall: npm install -g cli-wechat-bridge@latest",
|
|
34
|
+
"spawn.diagnostic.xcode": "- Ensure Xcode CLI tools are installed: xcode-select --install",
|
|
35
|
+
"spawn.diagnostic.linuxBuildTools": "- Linux requires build tools for node-pty: sudo apt install build-essential python3\n- Then reinstall: npm install -g cli-wechat-bridge@latest",
|
|
36
|
+
"spawn.diagnostic.notFound": "- The command \"{target}\" was not found on PATH.\n- Verify it is installed and accessible from your terminal.",
|
|
37
|
+
"spawn.diagnostic.generic": "- Reinstall: npm install -g cli-wechat-bridge@latest",
|
|
38
|
+
"spawn.diagnostic.nodeVersion": "- Ensure Node.js >= 22.6.0: node --version",
|
|
39
|
+
"spawn.diagnostic.winFull": "- Ensure Windows 10 build 18309+ (run 'winver' to check)\n- Install Visual C++ Redistributable: https://aka.ms/vs/17/release/vc_redist.x64.exe\n- Run: npm rebuild node-pty\n- Try running as Administrator",
|
|
40
|
+
// === Emoji bindings ===
|
|
41
|
+
"binding.usage": "Invalid format.\nUsage: /bind [emoji] command\nExample: /bind 🚀 deploy --prod",
|
|
42
|
+
"binding.bound": "Bound {emoji} → {command}",
|
|
43
|
+
"binding.unbound": "Unbound {emoji}.",
|
|
44
|
+
"binding.notFound": "No binding found for {emoji}.",
|
|
45
|
+
"binding.listEmpty": "No emoji bindings configured.",
|
|
46
|
+
"binding.listHeader": "Emoji bindings:",
|
|
47
|
+
// === Version checker ===
|
|
48
|
+
"update.available": "[Update Available] Version {latest} is available (current: {current}).\nRun: npm install -g cli-wechat-bridge@latest",
|
|
49
|
+
// === Doctor ===
|
|
50
|
+
"doctor.title": "CLI WeChat Bridge Doctor",
|
|
51
|
+
"doctor.section.environment": "Environment",
|
|
52
|
+
"doctor.section.adapterCli": "Adapter commands",
|
|
53
|
+
"doctor.section.data": "Data",
|
|
54
|
+
"doctor.section.runtime": "Runtime",
|
|
55
|
+
"doctor.label.node": "Node.js",
|
|
56
|
+
"doctor.label.platform": "Platform",
|
|
57
|
+
"doctor.label.winBuild": "Windows build",
|
|
58
|
+
"doctor.label.nodePty": "node-pty",
|
|
59
|
+
"doctor.label.shell": "shell",
|
|
60
|
+
"doctor.label.dataDir": "Data dir",
|
|
61
|
+
"doctor.label.credentials": "Credentials",
|
|
62
|
+
"doctor.label.mode": "Mode",
|
|
63
|
+
"doctor.label.cwd": "Cwd",
|
|
64
|
+
"doctor.label.adapter": "Adapter",
|
|
65
|
+
"doctor.label.daemon": "Daemon",
|
|
66
|
+
"doctor.label.bridgeLock": "Bridge lock",
|
|
67
|
+
"doctor.label.workspaceEndpoint": "Workspace endpoint ({adapter})",
|
|
68
|
+
"doctor.label.legacyEndpoint": "Legacy endpoint",
|
|
69
|
+
"doctor.winBuildConpty": "(ConPTY requires build 18309+)",
|
|
70
|
+
"doctor.nodePty.loaded": "loaded",
|
|
71
|
+
"doctor.nodePty.fix": "Fix: {fix}",
|
|
72
|
+
"doctor.adapterCli.shellNative": "uses the local shell; no other adapter CLI is checked.",
|
|
73
|
+
"doctor.adapterCli.notFound": "not found{optional}",
|
|
74
|
+
"doctor.dataDirMissing": "(will be created on first run)",
|
|
75
|
+
"doctor.credentialsFound": "found",
|
|
76
|
+
"doctor.credentialsMissing": "not found (run wechat-setup first)",
|
|
77
|
+
"doctor.mode.bridge": "standalone bridge",
|
|
78
|
+
"doctor.mode.generic": "generic",
|
|
79
|
+
"doctor.notSpecified": "(not specified)",
|
|
80
|
+
"doctor.none": "none",
|
|
81
|
+
"doctor.unknown": "unknown",
|
|
82
|
+
"doctor.yes": "yes",
|
|
83
|
+
"doctor.no": "no",
|
|
84
|
+
"doctor.optional": "(optional)",
|
|
85
|
+
"doctor.invalidShape": "unexpected file shape",
|
|
86
|
+
"doctor.file": "File: {file}",
|
|
87
|
+
"doctor.issue": "Issue: {issue}.",
|
|
88
|
+
"doctor.daemon.invalid": "invalid endpoint file ({error})",
|
|
89
|
+
"doctor.daemon.stale": "stale endpoint pid={pid} cwd={cwd} port={port}",
|
|
90
|
+
"doctor.daemon.staleStartup": "Startup: bridge and daemon startup paths will clear stale daemon endpoint state before continuing.",
|
|
91
|
+
"doctor.daemon.live": "live pid={pid} cwd={cwd} port={port}",
|
|
92
|
+
"doctor.daemon.liveBridgeStartup": "Startup: standalone bridge will refuse to start while this daemon is live.",
|
|
93
|
+
"doctor.daemon.liveDaemonStartup": "Startup: daemon startup will request shutdown of this daemon before binding.",
|
|
94
|
+
"doctor.lock.invalid": "invalid lock file ({error})",
|
|
95
|
+
"doctor.lock.stale": "stale",
|
|
96
|
+
"doctor.lock.staleDaemonStartup": "daemon startup will clear this stale single-bridge lock.",
|
|
97
|
+
"doctor.lock.staleBridgeStartup": "the next standalone bridge start will replace this stale lock.",
|
|
98
|
+
"doctor.lock.reclaimable": "reclaimable",
|
|
99
|
+
"doctor.lock.parent": "pid={pid} alive={alive}",
|
|
100
|
+
"doctor.lock.detail.pid": "pid",
|
|
101
|
+
"doctor.lock.detail.adapter": "adapter",
|
|
102
|
+
"doctor.lock.detail.cwd": "cwd",
|
|
103
|
+
"doctor.lock.detail.lifecycle": "lifecycle",
|
|
104
|
+
"doctor.lock.detail.startedAt": "started at",
|
|
105
|
+
"doctor.lock.detail.parent": "parent",
|
|
106
|
+
"doctor.lock.detail.startup": "startup",
|
|
107
|
+
"doctor.lock.detail.note": "note",
|
|
108
|
+
"doctor.lock.reclaimableDaemonStartup": "daemon startup will stop or clear this orphaned single bridge before continuing.",
|
|
109
|
+
"doctor.lock.reclaimableBridgeStartup": "standalone bridge startup can reclaim this companion-bound or legacy lock because its parent is gone.",
|
|
110
|
+
"doctor.lock.live": "live",
|
|
111
|
+
"doctor.lock.liveDaemonStartup": "daemon startup will stop this single bridge before continuing.",
|
|
112
|
+
"doctor.lock.liveBridgeStartup": "standalone bridge will fail with a lock conflict until this process exits.",
|
|
113
|
+
"doctor.lock.cwdDifferent": "lock cwd differs from requested cwd ({cwd}); single-bridge lock is global.",
|
|
114
|
+
"doctor.lock.adapterDifferent": "lock adapter={lockAdapter} differs from requested adapter={requestedAdapter}.",
|
|
115
|
+
"doctor.endpoint.legacySame": "same as adapter endpoint",
|
|
116
|
+
"doctor.endpoint.summary": "instance={instanceId} kind={kind} port={port} reachable={reachable}",
|
|
117
|
+
"doctor.endpoint.owner": "ownerPid={ownerPid} ownerAlive={ownerAlive} companionPid={companionPid} companionAlive={companionAlive} status={status}",
|
|
118
|
+
"doctor.endpoint.issue.kind": "endpoint kind={kind} differs from requested adapter={adapter}",
|
|
119
|
+
"doctor.endpoint.issue.cwd": "endpoint cwd differs from requested cwd ({cwd})",
|
|
120
|
+
"doctor.endpoint.issue.port": "endpoint port {port} is not reachable",
|
|
121
|
+
"doctor.endpoint.issue.ownerDead": "bridge owner pid={pid} is dead",
|
|
122
|
+
"doctor.endpoint.issue.companionDead": "companion pid={pid} is dead",
|
|
123
|
+
"doctor.endpoint.issue.workerStatus": "visible worker status={status}",
|
|
124
|
+
"doctor.endpoint.issue.instanceMismatch": "endpoint instanceId does not match bridge lock instanceId",
|
|
125
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export const messages = {
|
|
2
|
+
// === 桥接欢迎 & 控制 ===
|
|
3
|
+
"bridge.welcome": "微信桥接就绪 ({adapter})。\n工作目录: {cwd}\n\n命令: /stop, /confirm, /deny, /status, /new\n{bindings}\n\n管理: /bind [表情] 命令, /unbind [表情], /bindings",
|
|
4
|
+
"bridge.stopped": "桥接已停止。",
|
|
5
|
+
"bridge.interrupt.sent": "已发送中断信号。",
|
|
6
|
+
"bridge.interrupt.notBusy": "没有正在执行的任务可中断。",
|
|
7
|
+
"bridge.reset.done": "会话已重置。",
|
|
8
|
+
"bridge.status.notRunning": "{adapter} 适配器未运行。",
|
|
9
|
+
"bridge.status.busy": "{adapter} 仍在处理上一个请求。请等待完成或发送 /interrupt。",
|
|
10
|
+
"bridge.newSession.done": "已开始新会话。",
|
|
11
|
+
"bridge.fatalError": "桥接错误: {message}",
|
|
12
|
+
// === Daemon 欢迎 & 控制 ===
|
|
13
|
+
"daemon.welcome": "微信 Daemon 就绪。\n工作目录: {cwd}\n当前: {adapter}\n\n命令: /claude, /codex, /opencode, /stop, /confirm, /deny, /status\n{bindings}\n\n管理: /bind [表情] 命令, /unbind [表情], /bindings",
|
|
14
|
+
"daemon.noActiveAdapter": "未选择活跃终端。发送 /codex、/claude 或 /opencode 启动一个。",
|
|
15
|
+
"daemon.switchResult.new": "已启动新的可见 CLI。",
|
|
16
|
+
"daemon.switchResult.reused": "已复用现有的可见 CLI。",
|
|
17
|
+
// === 审批 ===
|
|
18
|
+
"approval.prompt": "{adapter} 权限请求。\n{summary}\n\n回复 /confirm 或 /deny。",
|
|
19
|
+
"approval.confirmed": "已确认审批,继续执行...",
|
|
20
|
+
"approval.denied": "已拒绝审批。",
|
|
21
|
+
"approval.noPending": "没有待处理的审批请求。",
|
|
22
|
+
"approval.batchConfirmed": "已批量确认 {count} 个审批。",
|
|
23
|
+
"approval.batchDenied": "已批量拒绝 {count} 个审批。",
|
|
24
|
+
// === Hook 健康检查 ===
|
|
25
|
+
"hook.healthCheck.warning": "[警告] 15 秒内未收到 Claude hook 事件。\nhook 系统可能未正常工作 — Claude 的输出将无法到达微信。",
|
|
26
|
+
"hook.healthCheck.logHint": "\n查看日志: {logPath}",
|
|
27
|
+
"hook.healthCheck.fixes": "\n常见修复方法:\n- 确保 Node.js >= 22.6.0: node --version\n- 重新安装: npm install -g cli-wechat-bridge@latest\n- 检查防火墙: 允许 localhost TCP 连接",
|
|
28
|
+
// === PTY 回退 ===
|
|
29
|
+
"pty.fallback.warning": "[警告] PTY 不可用 — 已切换到回退模式(TERM=dumb)。\n核心功能(消息收发、审批、会话管理)正常工作;终端渲染(颜色、进度条)可能受限。\n修复方法: Linux 安装 build-essential python3 | Windows 运行 npm rebuild node-pty | macOS 运行 xcode-select --install\n运行 --doctor 查看详细环境信息。\n",
|
|
30
|
+
// === 启动诊断 ===
|
|
31
|
+
"spawn.diagnostic.title": "无法启动 CLI 进程: {target}\n错误: {error}",
|
|
32
|
+
"spawn.diagnostic.fixesHeader": "\n可能的修复方法:",
|
|
33
|
+
"spawn.diagnostic.nodePty": "- node-pty 原生模块与当前 Node.js 版本不兼容。\n- 运行: npm rebuild node-pty\n- 或重新安装: npm install -g cli-wechat-bridge@latest",
|
|
34
|
+
"spawn.diagnostic.xcode": "- 确保已安装 Xcode 命令行工具: xcode-select --install",
|
|
35
|
+
"spawn.diagnostic.linuxBuildTools": "- Linux 需要编译工具来构建 node-pty: sudo apt install build-essential python3\n- 然后重新安装: npm install -g cli-wechat-bridge@latest",
|
|
36
|
+
"spawn.diagnostic.notFound": "- 命令 \"{target}\" 未在 PATH 中找到。\n- 请确认已安装并可从终端访问。",
|
|
37
|
+
"spawn.diagnostic.generic": "- 重新安装: npm install -g cli-wechat-bridge@latest",
|
|
38
|
+
"spawn.diagnostic.nodeVersion": "- 确保 Node.js >= 22.6.0: node --version",
|
|
39
|
+
"spawn.diagnostic.winFull": "- 确保 Windows 10 build 18309+(运行 winver 查看)\n- 安装 Visual C++ Redistributable: https://aka.ms/vs/17/release/vc_redist.x64.exe\n- 运行: npm rebuild node-pty\n- 尝试以管理员身份运行",
|
|
40
|
+
// === Emoji 绑定 ===
|
|
41
|
+
"binding.usage": "格式错误。\n用法: /bind [表情] 命令\n示例: /bind 🚀 deploy --prod",
|
|
42
|
+
"binding.bound": "已绑定 {emoji} → {command}",
|
|
43
|
+
"binding.unbound": "已解绑 {emoji}。",
|
|
44
|
+
"binding.notFound": "未找到 {emoji} 的绑定。",
|
|
45
|
+
"binding.listEmpty": "未配置 emoji 绑定。",
|
|
46
|
+
"binding.listHeader": "Emoji 绑定列表:",
|
|
47
|
+
// === 版本检查 ===
|
|
48
|
+
"update.available": "[有新版本] 版本 {latest} 可用(当前: {current})。\n运行: npm install -g cli-wechat-bridge@latest",
|
|
49
|
+
// === Doctor ===
|
|
50
|
+
"doctor.title": "CLI WeChat Bridge 诊断",
|
|
51
|
+
"doctor.section.environment": "环境",
|
|
52
|
+
"doctor.section.adapterCli": "适配器命令",
|
|
53
|
+
"doctor.section.data": "数据",
|
|
54
|
+
"doctor.section.runtime": "运行时",
|
|
55
|
+
"doctor.label.node": "Node.js",
|
|
56
|
+
"doctor.label.platform": "平台",
|
|
57
|
+
"doctor.label.winBuild": "Windows build",
|
|
58
|
+
"doctor.label.nodePty": "node-pty",
|
|
59
|
+
"doctor.label.shell": "shell",
|
|
60
|
+
"doctor.label.dataDir": "数据目录",
|
|
61
|
+
"doctor.label.credentials": "凭据",
|
|
62
|
+
"doctor.label.mode": "模式",
|
|
63
|
+
"doctor.label.cwd": "目录",
|
|
64
|
+
"doctor.label.adapter": "适配器",
|
|
65
|
+
"doctor.label.daemon": "守护进程",
|
|
66
|
+
"doctor.label.bridgeLock": "桥接锁",
|
|
67
|
+
"doctor.label.workspaceEndpoint": "工作区端点 ({adapter})",
|
|
68
|
+
"doctor.label.legacyEndpoint": "旧端点",
|
|
69
|
+
"doctor.winBuildConpty": "(ConPTY 需要 build 18309+)",
|
|
70
|
+
"doctor.nodePty.loaded": "已加载",
|
|
71
|
+
"doctor.nodePty.fix": "修复: {fix}",
|
|
72
|
+
"doctor.adapterCli.shellNative": "使用本机 shell,无需检查其它适配器 CLI。",
|
|
73
|
+
"doctor.adapterCli.notFound": "未找到{optional}",
|
|
74
|
+
"doctor.dataDirMissing": "(首次运行会创建)",
|
|
75
|
+
"doctor.credentialsFound": "已找到",
|
|
76
|
+
"doctor.credentialsMissing": "未找到 (先运行 wechat-setup)",
|
|
77
|
+
"doctor.mode.bridge": "独立桥接",
|
|
78
|
+
"doctor.mode.generic": "通用",
|
|
79
|
+
"doctor.notSpecified": "(未指定)",
|
|
80
|
+
"doctor.none": "无",
|
|
81
|
+
"doctor.unknown": "未知",
|
|
82
|
+
"doctor.yes": "是",
|
|
83
|
+
"doctor.no": "否",
|
|
84
|
+
"doctor.optional": "(可选)",
|
|
85
|
+
"doctor.invalidShape": "文件结构不符合预期",
|
|
86
|
+
"doctor.file": "文件: {file}",
|
|
87
|
+
"doctor.issue": "问题: {issue}。",
|
|
88
|
+
"doctor.daemon.invalid": "端点文件无效 ({error})",
|
|
89
|
+
"doctor.daemon.stale": "过期端点 pid={pid} cwd={cwd} port={port}",
|
|
90
|
+
"doctor.daemon.staleStartup": "启动行为: 桥接和守护进程启动路径会先清理过期守护进程端点。",
|
|
91
|
+
"doctor.daemon.live": "运行中 pid={pid} cwd={cwd} port={port}",
|
|
92
|
+
"doctor.daemon.liveBridgeStartup": "启动行为: 守护进程运行中时,独立桥接会拒绝启动。",
|
|
93
|
+
"doctor.daemon.liveDaemonStartup": "启动行为: 守护进程启动会先请求关闭这个旧守护进程再绑定。",
|
|
94
|
+
"doctor.lock.invalid": "锁文件无效 ({error})",
|
|
95
|
+
"doctor.lock.stale": "过期",
|
|
96
|
+
"doctor.lock.staleDaemonStartup": "守护进程启动会清理这个过期的单桥接锁。",
|
|
97
|
+
"doctor.lock.staleBridgeStartup": "下次独立桥接启动会替换这个过期锁。",
|
|
98
|
+
"doctor.lock.reclaimable": "可回收",
|
|
99
|
+
"doctor.lock.parent": "pid={pid} alive={alive}",
|
|
100
|
+
"doctor.lock.detail.pid": "pid",
|
|
101
|
+
"doctor.lock.detail.adapter": "适配器",
|
|
102
|
+
"doctor.lock.detail.cwd": "目录",
|
|
103
|
+
"doctor.lock.detail.lifecycle": "生命周期",
|
|
104
|
+
"doctor.lock.detail.startedAt": "启动时间",
|
|
105
|
+
"doctor.lock.detail.parent": "父进程",
|
|
106
|
+
"doctor.lock.detail.startup": "启动行为",
|
|
107
|
+
"doctor.lock.detail.note": "注意",
|
|
108
|
+
"doctor.lock.reclaimableDaemonStartup": "守护进程启动会先停止或清理这个孤儿单桥接。",
|
|
109
|
+
"doctor.lock.reclaimableBridgeStartup": "独立桥接可回收这个父进程已退出的锁。",
|
|
110
|
+
"doctor.lock.live": "运行中",
|
|
111
|
+
"doctor.lock.liveDaemonStartup": "守护进程启动会先停止这个单桥接。",
|
|
112
|
+
"doctor.lock.liveBridgeStartup": "该进程退出前,独立桥接会因锁冲突启动失败。",
|
|
113
|
+
"doctor.lock.cwdDifferent": "锁 cwd 与请求 cwd 不同 ({cwd});单桥接锁是全局的。",
|
|
114
|
+
"doctor.lock.adapterDifferent": "锁 adapter={lockAdapter} 与请求 adapter={requestedAdapter} 不同。",
|
|
115
|
+
"doctor.endpoint.legacySame": "与适配器端点相同",
|
|
116
|
+
"doctor.endpoint.summary": "实例={instanceId} 类型={kind} 端口={port} 可达={reachable}",
|
|
117
|
+
"doctor.endpoint.owner": "ownerPid={ownerPid} ownerAlive={ownerAlive} companionPid={companionPid} companionAlive={companionAlive} 状态={status}",
|
|
118
|
+
"doctor.endpoint.issue.kind": "端点类型 {kind} 与请求适配器 {adapter} 不同",
|
|
119
|
+
"doctor.endpoint.issue.cwd": "端点 cwd 与请求 cwd 不同 ({cwd})",
|
|
120
|
+
"doctor.endpoint.issue.port": "端点端口 {port} 不可达",
|
|
121
|
+
"doctor.endpoint.issue.ownerDead": "桥接 owner pid={pid} 已退出",
|
|
122
|
+
"doctor.endpoint.issue.companionDead": "companion pid={pid} 已退出",
|
|
123
|
+
"doctor.endpoint.issue.workerStatus": "可见端 worker 状态={status}",
|
|
124
|
+
"doctor.endpoint.issue.instanceMismatch": "端点 instanceId 与桥接锁 instanceId 不一致",
|
|
125
|
+
};
|
|
@@ -34,6 +34,9 @@ export class LegacyAdapterRuntime {
|
|
|
34
34
|
async resolveApproval(action) {
|
|
35
35
|
return await this.adapter.resolveApproval(action);
|
|
36
36
|
}
|
|
37
|
+
async resolveAllApprovals(action) {
|
|
38
|
+
return await this.adapter.resolveAllApprovals(action);
|
|
39
|
+
}
|
|
37
40
|
async submitUserInput(answers) {
|
|
38
41
|
return await this.adapter.submitUserInput(answers);
|
|
39
42
|
}
|