cli-wechat-bridge 1.1.8 → 1.2.0
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 +17 -4
- package/bin/_run-entry.mjs +6 -1
- package/bin/wechat-check-update.mjs +6 -1
- package/bin/wechat-claude.mjs +6 -1
- package/bin/wechat-codex.mjs +6 -1
- package/bin/wechat-daemon.mjs +6 -1
- package/bin/wechat-opencode.mjs +6 -1
- package/bin/wechat-pi.mjs +6 -1
- package/bin/wechat-setup.mjs +6 -1
- package/bin/wecom-check-update.mjs +6 -1
- package/bin/wecom-claude.mjs +6 -1
- package/bin/wecom-codex.mjs +6 -1
- package/bin/wecom-daemon.mjs +6 -1
- package/bin/wecom-opencode.mjs +6 -1
- package/bin/wecom-pi.mjs +6 -1
- package/bin/wecom-setup.mjs +6 -1
- package/dist/bridge/bridge-adapters.claude.js +6 -0
- package/dist/bridge/bridge-adapters.codex.js +6 -0
- package/dist/bridge/bridge-adapters.core.js +6 -0
- package/dist/bridge/bridge-adapters.opencode.js +6 -0
- package/dist/bridge/bridge-adapters.pi.js +6 -0
- package/dist/bridge/bridge-adapters.shared.js +6 -0
- package/dist/bridge/bridge-controller.js +6 -0
- package/dist/bridge/bridge-final-reply.js +6 -0
- package/dist/bridge/bridge-process-reaper.js +6 -0
- package/dist/bridge/bridge-state.js +6 -0
- package/dist/bridge/bridge-utils.js +6 -31
- package/dist/bridge/claude-hook.js +6 -0
- package/dist/bridge/native-terminal-control.js +6 -0
- package/dist/bridge/wechat-bridge.js +148 -241
- package/dist/bridge/wechat-forwarding.js +6 -0
- package/dist/bridge/wechat-outbound-queue.js +6 -0
- package/dist/channels/wechat/bridge-final-reply.js +13 -22
- package/dist/channels/wechat/index.js +6 -0
- package/dist/channels/wechat/wechat-driver.js +191 -0
- package/dist/channels/wechat/wechat-forwarding.js +18 -0
- package/dist/channels/wechat/wechat-outbound-queue.js +39 -0
- package/dist/channels/wecom/bridge-final-reply.js +6 -0
- package/dist/channels/wecom/setup-cli.js +6 -0
- package/dist/channels/wecom/setup.js +6 -0
- package/dist/channels/wecom/wecom-config.js +6 -0
- package/dist/channels/wecom/wecom-driver.js +106 -0
- package/dist/channels/wecom/wecom-media.js +6 -0
- package/dist/channels/wecom/wecom-transport.js +6 -0
- package/dist/commands/check-update.js +6 -0
- package/dist/companion/codex-remote-client.js +6 -0
- package/dist/companion/codex-visible-client-link.js +6 -0
- package/dist/companion/local-companion-link.js +6 -0
- package/dist/companion/local-companion-start.js +6 -0
- package/dist/companion/local-companion.js +6 -0
- package/dist/companion/opencode-tui-bridge-plugin.js +6 -0
- package/dist/companion/pi-tui-bridge-extension.js +6 -0
- package/dist/core/bridge-control.js +2 -0
- package/dist/core/bridge-defer.js +25 -0
- package/dist/core/channel-driver.js +1 -0
- package/dist/core/conversation-routing.js +11 -1
- package/dist/core/direct-run.js +6 -0
- package/dist/core/inbound-message-claims.js +6 -0
- package/dist/core/outbound-target.js +32 -0
- package/dist/core/text-utils.js +6 -0
- package/dist/core/turn-coordinator.js +85 -0
- package/dist/daemon/daemon-link.js +6 -0
- package/dist/daemon/emoji-bindings.js +6 -0
- package/dist/daemon/wechat-daemon.js +451 -173
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/messages-en.js +7 -1
- package/dist/i18n/messages-zh.js +7 -1
- package/dist/runtime/create-runtime-host.js +6 -0
- package/dist/utils/atomic-file.js +6 -0
- package/dist/utils/doctor.js +6 -0
- package/dist/utils/version-checker.js +6 -0
- package/dist/wechat/channel-config.js +6 -0
- package/dist/wechat/setup.js +6 -0
- package/dist/wechat/wechat-channel.js +6 -0
- package/dist/wechat/wechat-transport.js +73 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function shouldDeferCodexInboundMessage(params) {
|
|
2
|
+
return (params.adapter === "codex" &&
|
|
3
|
+
!params.hasPendingConfirmation &&
|
|
4
|
+
!params.hasSystemCommand &&
|
|
5
|
+
params.activeTurnOrigin === "local" &&
|
|
6
|
+
(params.status === "busy" || params.status === "awaiting_approval"));
|
|
7
|
+
}
|
|
8
|
+
export function canDrainDeferredCodexInboundQueue(params) {
|
|
9
|
+
return (params.adapter === "codex" &&
|
|
10
|
+
params.deferredCount > 0 &&
|
|
11
|
+
!params.hasPendingConfirmation &&
|
|
12
|
+
!params.hasPendingUserInput &&
|
|
13
|
+
!params.hasPendingApproval &&
|
|
14
|
+
!params.hasActiveTask &&
|
|
15
|
+
!params.activeTurnId &&
|
|
16
|
+
params.status !== "busy" &&
|
|
17
|
+
params.status !== "awaiting_approval" &&
|
|
18
|
+
params.status !== "awaiting_input");
|
|
19
|
+
}
|
|
20
|
+
export function formatDeferredCodexInboundQueueMessage(queuePosition) {
|
|
21
|
+
return `Queued for delivery after the current local Codex turn finishes. Queue position: ${queuePosition}.`;
|
|
22
|
+
}
|
|
23
|
+
export function isRetryableDeferredCodexDrainError(errorText) {
|
|
24
|
+
return /still working|approval request is pending|waiting for local terminal input/i.test(errorText);
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
8
|
/**
|
|
3
9
|
* Keeps the reply target scoped to one inbound async call chain. Different
|
|
@@ -19,6 +25,7 @@ export function tryBeginTurn(state, task, conversation) {
|
|
|
19
25
|
const lease = {
|
|
20
26
|
task,
|
|
21
27
|
previousConversation: state.activeConversation,
|
|
28
|
+
previousLastConversation: state.lastConversation,
|
|
22
29
|
};
|
|
23
30
|
state.activeTask = task;
|
|
24
31
|
if (conversation) {
|
|
@@ -27,12 +34,15 @@ export function tryBeginTurn(state, task, conversation) {
|
|
|
27
34
|
}
|
|
28
35
|
return lease;
|
|
29
36
|
}
|
|
30
|
-
export function rollbackTurn(state, lease) {
|
|
37
|
+
export function rollbackTurn(state, lease, options = {}) {
|
|
31
38
|
if (state.activeTask !== lease.task) {
|
|
32
39
|
return false;
|
|
33
40
|
}
|
|
34
41
|
state.activeTask = null;
|
|
35
42
|
state.activeConversation = lease.previousConversation;
|
|
43
|
+
if (options.restoreLastConversation) {
|
|
44
|
+
state.lastConversation = lease.previousLastConversation;
|
|
45
|
+
}
|
|
36
46
|
return true;
|
|
37
47
|
}
|
|
38
48
|
export function clearTurn(state, expectedTask) {
|
package/dist/core/direct-run.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
import path from "node:path";
|
|
2
8
|
import { fileURLToPath } from "node:url";
|
|
3
9
|
function normalizeComparablePath(filePath) {
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
import crypto from "node:crypto";
|
|
2
8
|
import fs from "node:fs";
|
|
3
9
|
import path from "node:path";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound target priority for standalone bridges:
|
|
3
|
+
* 1. an explicit override captured at enqueue time;
|
|
4
|
+
* 2. for the operator on multi-conversation channels, the pre-resolved turn
|
|
5
|
+
* target (callers pass `TurnCoordinator.resolveTarget(operatorConversation)`);
|
|
6
|
+
* 3. otherwise a direct conversation to the sender.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveOutboundConversationTarget(params) {
|
|
9
|
+
if (params.override) {
|
|
10
|
+
return params.override;
|
|
11
|
+
}
|
|
12
|
+
if (params.multiConversation && params.senderId === params.operatorId) {
|
|
13
|
+
return params.operatorTarget;
|
|
14
|
+
}
|
|
15
|
+
return params.directConversation(params.senderId);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Outbound target priority for daemon sends. Multi-conversation operators
|
|
19
|
+
* resolve through the current inbound conversation first, then the active
|
|
20
|
+
* slot's remembered target, then the daemon fallback conversation.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveDaemonOutboundTarget(params) {
|
|
23
|
+
if (params.override) {
|
|
24
|
+
return params.override;
|
|
25
|
+
}
|
|
26
|
+
if (params.multiConversation && params.senderId === params.operatorId) {
|
|
27
|
+
return params.inboundConversation
|
|
28
|
+
?? params.activeSlotTarget
|
|
29
|
+
?? params.fallbackConversation;
|
|
30
|
+
}
|
|
31
|
+
return params.directConversation(params.senderId);
|
|
32
|
+
}
|
package/dist/core/text-utils.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
const ANSI_ESCAPE_RE =
|
|
2
8
|
// eslint-disable-next-line no-control-regex
|
|
3
9
|
/\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { clearTurn, resolveConversationTarget, rollbackTurn, tryBeginTurn, } from "./conversation-routing.js";
|
|
2
|
+
/**
|
|
3
|
+
* Owns the active remote turn for one dispatch surface: a standalone bridge
|
|
4
|
+
* or one daemon adapter slot. Wraps the turn ownership state machine (busy
|
|
5
|
+
* rejection, dispatch rollback, conditional completion) so standalone and
|
|
6
|
+
* daemon share identical gating semantics instead of re-implementing them.
|
|
7
|
+
*/
|
|
8
|
+
export class TurnCoordinator {
|
|
9
|
+
state;
|
|
10
|
+
restoreLastConversationOnFailure;
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.state = {
|
|
13
|
+
activeTask: null,
|
|
14
|
+
lastConversation: options.initialLastConversation ?? null,
|
|
15
|
+
};
|
|
16
|
+
this.restoreLastConversationOnFailure = options.restoreLastConversationOnFailure ?? false;
|
|
17
|
+
}
|
|
18
|
+
get activeTask() {
|
|
19
|
+
return this.state.activeTask;
|
|
20
|
+
}
|
|
21
|
+
get hasActiveTask() {
|
|
22
|
+
return this.state.activeTask !== null;
|
|
23
|
+
}
|
|
24
|
+
get activeConversation() {
|
|
25
|
+
return this.state.activeConversation;
|
|
26
|
+
}
|
|
27
|
+
get lastConversation() {
|
|
28
|
+
return this.state.lastConversation;
|
|
29
|
+
}
|
|
30
|
+
beginTurn(task, conversation) {
|
|
31
|
+
return tryBeginTurn(this.state, task, conversation);
|
|
32
|
+
}
|
|
33
|
+
rollback(lease, options = {}) {
|
|
34
|
+
return rollbackTurn(this.state, lease, options);
|
|
35
|
+
}
|
|
36
|
+
complete(expectedTask) {
|
|
37
|
+
return clearTurn(this.state, expectedTask);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Replaces the active task unconditionally. Used when a command path
|
|
41
|
+
* (approval confirmation, resume) takes over a continuing turn rather
|
|
42
|
+
* than dispatching fresh input.
|
|
43
|
+
*/
|
|
44
|
+
setActiveTask(task) {
|
|
45
|
+
this.state.activeTask = task;
|
|
46
|
+
}
|
|
47
|
+
/** Binds a conversation as both active and remembered target. */
|
|
48
|
+
bindConversation(conversation) {
|
|
49
|
+
this.state.activeConversation = conversation;
|
|
50
|
+
this.state.lastConversation = conversation;
|
|
51
|
+
}
|
|
52
|
+
/** Records a conversation as the remembered fallback target only. */
|
|
53
|
+
observeConversation(conversation) {
|
|
54
|
+
this.state.lastConversation = conversation;
|
|
55
|
+
}
|
|
56
|
+
resolveTarget(fallback) {
|
|
57
|
+
return resolveConversationTarget({
|
|
58
|
+
active: this.state.activeConversation,
|
|
59
|
+
last: this.state.lastConversation,
|
|
60
|
+
fallback,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Busy-rejecting dispatch transaction: acquire the turn lease, forward the
|
|
65
|
+
* input, and roll the lease back when forwarding throws. A busy input runs
|
|
66
|
+
* `onBusy` (reminder) and returns without touching ownership.
|
|
67
|
+
*/
|
|
68
|
+
async dispatch(params) {
|
|
69
|
+
const lease = this.beginTurn(params.task, params.conversation);
|
|
70
|
+
if (!lease) {
|
|
71
|
+
await params.onBusy?.();
|
|
72
|
+
return { status: "busy" };
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await params.forward();
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.rollback(lease, {
|
|
79
|
+
restoreLastConversation: this.restoreLastConversationOnFailure,
|
|
80
|
+
});
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
return { status: "dispatched", task: params.task };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
import crypto from "node:crypto";
|
|
2
8
|
import fs from "node:fs";
|
|
3
9
|
import net from "node:net";
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// Copyright (c) 2026 UNLINEARITY <unlinearity@gmail.com>
|
|
3
|
+
// Source: https://github.com/UNLINEARITY/CLI-WeChat-Bridge
|
|
4
|
+
// This file is part of CLI-WeChat-Bridge. Modifications and derivative works
|
|
5
|
+
// must be released under AGPL-3.0-or-later with full source code; see
|
|
6
|
+
// LICENSE.txt. Network services built on it must offer source to users.
|
|
1
7
|
import fs from "node:fs";
|
|
2
8
|
import { EMOJI_BINDINGS_FILE } from "../wechat/channel-config.js";
|
|
3
9
|
import { t } from "../i18n/index.js";
|