@unlinearity/cli-wechat-bridge 1.0.2 → 1.0.4
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 +221 -223
- package/dist/bridge/bridge-adapter-common.js +95 -0
- package/dist/bridge/bridge-adapters.claude.js +1 -1
- package/dist/bridge/bridge-adapters.codex.js +26 -4
- package/dist/bridge/bridge-adapters.core.js +10 -1
- package/dist/bridge/bridge-adapters.opencode.js +395 -43
- package/dist/bridge/bridge-adapters.shared.js +4 -97
- package/dist/bridge/bridge-final-reply.js +18 -3
- package/dist/bridge/bridge-state.js +9 -3
- package/dist/bridge/bridge-utils.js +62 -8
- package/dist/bridge/claude-hooks.js +2 -2
- package/dist/bridge/wechat-bridge.js +111 -27
- package/dist/companion/codex-remote-client.js +3 -0
- package/dist/companion/local-companion-start.js +6 -1
- package/dist/companion/local-companion.js +11 -0
- package/dist/runtime/legacy-adapter-runtime.js +6 -0
- package/dist/utils/version-checker.js +1 -1
- package/dist/wechat/wechat-transport.js +46 -2
- package/package.json +10 -2
|
@@ -13,6 +13,9 @@ export function parseCliArgs(argv) {
|
|
|
13
13
|
const cliArgs = [];
|
|
14
14
|
for (let i = 0; i < argv.length; i += 1) {
|
|
15
15
|
const arg = argv[i];
|
|
16
|
+
if (!arg) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
16
19
|
const next = argv[i + 1];
|
|
17
20
|
if (arg === "--help" || arg === "-h") {
|
|
18
21
|
process.stdout.write([
|
|
@@ -87,6 +87,9 @@ export function parseCliArgs(argv) {
|
|
|
87
87
|
const cliArgs = [];
|
|
88
88
|
for (let i = 0; i < argv.length; i += 1) {
|
|
89
89
|
const arg = argv[i];
|
|
90
|
+
if (!arg) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
90
93
|
const next = argv[i + 1];
|
|
91
94
|
if (arg === "--help" || arg === "-h") {
|
|
92
95
|
process.stdout.write([
|
|
@@ -173,7 +176,9 @@ async function stopExistingBridge(lock, requestedAdapter) {
|
|
|
173
176
|
catch (error) {
|
|
174
177
|
if (isPidAlive(pid)) {
|
|
175
178
|
const message = error instanceof Error ? error.message : String(error);
|
|
176
|
-
throw new Error(`Failed to stop existing bridge pid=${pid}: ${message}
|
|
179
|
+
throw new Error(`Failed to stop existing bridge pid=${pid}: ${message}`, {
|
|
180
|
+
cause: error,
|
|
181
|
+
});
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
if (!(await waitForProcessExit(pid, 10_000))) {
|
|
@@ -16,6 +16,9 @@ function parseCliArgs(argv) {
|
|
|
16
16
|
const cliArgs = [];
|
|
17
17
|
for (let i = 0; i < argv.length; i += 1) {
|
|
18
18
|
const arg = argv[i];
|
|
19
|
+
if (!arg) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
19
22
|
const next = argv[i + 1];
|
|
20
23
|
if (arg === "--help" || arg === "-h") {
|
|
21
24
|
process.stdout.write([
|
|
@@ -199,6 +202,14 @@ export async function runLocalCompanion(options) {
|
|
|
199
202
|
publishState();
|
|
200
203
|
sendResponse(socket, message.id, true);
|
|
201
204
|
break;
|
|
205
|
+
case "create_session":
|
|
206
|
+
if (!adapter.createSession) {
|
|
207
|
+
throw new Error(`/${adapter.getState().kind} does not support creating sessions from WeChat.`);
|
|
208
|
+
}
|
|
209
|
+
await adapter.createSession();
|
|
210
|
+
publishState();
|
|
211
|
+
sendResponse(socket, message.id, true);
|
|
212
|
+
break;
|
|
202
213
|
case "interrupt":
|
|
203
214
|
sendResponse(socket, message.id, true, await adapter.interrupt());
|
|
204
215
|
break;
|
|
@@ -19,6 +19,12 @@ export class LegacyAdapterRuntime {
|
|
|
19
19
|
async resumeSession(sessionId) {
|
|
20
20
|
await this.adapter.resumeSession(sessionId);
|
|
21
21
|
}
|
|
22
|
+
async createSession() {
|
|
23
|
+
if (!this.adapter.createSession) {
|
|
24
|
+
throw new Error(`/${this.adapter.getState().kind} does not support creating sessions from WeChat.`);
|
|
25
|
+
}
|
|
26
|
+
await this.adapter.createSession();
|
|
27
|
+
}
|
|
22
28
|
async interrupt() {
|
|
23
29
|
return await this.adapter.interrupt();
|
|
24
30
|
}
|
|
@@ -88,6 +88,49 @@ function readJsonFile(filePath) {
|
|
|
88
88
|
function isRecord(value) {
|
|
89
89
|
return typeof value === "object" && value !== null;
|
|
90
90
|
}
|
|
91
|
+
function readNumericResponseField(response, key) {
|
|
92
|
+
const value = response[key];
|
|
93
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
if (typeof value === "string" && value.trim()) {
|
|
97
|
+
const parsed = Number(value);
|
|
98
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
function readStringResponseField(response, key) {
|
|
103
|
+
const value = response[key];
|
|
104
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
105
|
+
}
|
|
106
|
+
export function assertWechatApiResponseOk(endpoint, raw) {
|
|
107
|
+
const trimmed = raw.trim();
|
|
108
|
+
if (!trimmed) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
let response;
|
|
112
|
+
try {
|
|
113
|
+
response = JSON.parse(trimmed);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!isRecord(response)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const ret = readNumericResponseField(response, "ret");
|
|
122
|
+
const errcode = readNumericResponseField(response, "errcode");
|
|
123
|
+
const failed = (ret !== undefined && ret !== 0) ||
|
|
124
|
+
(errcode !== undefined && errcode !== 0);
|
|
125
|
+
if (!failed) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const errmsg = readStringResponseField(response, "errmsg") ??
|
|
129
|
+
readStringResponseField(response, "message") ??
|
|
130
|
+
readStringResponseField(response, "msg") ??
|
|
131
|
+
"";
|
|
132
|
+
throw new Error(`${endpoint} failed: ret=${ret} errcode=${errcode} errmsg=${errmsg}`);
|
|
133
|
+
}
|
|
91
134
|
function describeErrorNode(value) {
|
|
92
135
|
if (value instanceof Error) {
|
|
93
136
|
const error = value;
|
|
@@ -587,7 +630,7 @@ export class WeChatTransport {
|
|
|
587
630
|
if (rawMessage.context_token) {
|
|
588
631
|
this.cacheContextToken(senderId, rawMessage.context_token);
|
|
589
632
|
}
|
|
590
|
-
const createdAtMs = rawMessage.create_time_ms;
|
|
633
|
+
const createdAtMs = rawMessage.create_time_ms ?? 0;
|
|
591
634
|
if (typeof options.minCreatedAtMs === "number" &&
|
|
592
635
|
(!Number.isFinite(createdAtMs) || createdAtMs < options.minCreatedAtMs)) {
|
|
593
636
|
ignoredBacklogCount += 1;
|
|
@@ -736,7 +779,7 @@ export class WeChatTransport {
|
|
|
736
779
|
]);
|
|
737
780
|
}
|
|
738
781
|
async sendMessage(account, recipientId, contextToken, itemList) {
|
|
739
|
-
await apiFetch({
|
|
782
|
+
const raw = await apiFetch({
|
|
740
783
|
baseUrl: account.baseUrl,
|
|
741
784
|
endpoint: "ilink/bot/sendmessage",
|
|
742
785
|
body: JSON.stringify({
|
|
@@ -754,6 +797,7 @@ export class WeChatTransport {
|
|
|
754
797
|
token: account.token,
|
|
755
798
|
timeoutMs: SEND_TIMEOUT_MS,
|
|
756
799
|
});
|
|
800
|
+
assertWechatApiResponseOk("sendmessage", raw);
|
|
757
801
|
}
|
|
758
802
|
async prepareUpload(account, recipientId, filePath, mediaType, label) {
|
|
759
803
|
const stat = this.requireExistingFile(filePath);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unlinearity/cli-wechat-bridge",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "CLI WeChat Bridge for Codex, Claude Code, OpenCode, and PowerShell over WeChat",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -50,6 +50,11 @@
|
|
|
50
50
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
51
51
|
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
52
52
|
"prepack": "npm run build",
|
|
53
|
+
"lint": "eslint bin src test",
|
|
54
|
+
"lint:fix": "eslint bin src test --fix",
|
|
55
|
+
"typecheck:src": "tsc -p tsconfig.typecheck.src.json --noEmit --pretty false",
|
|
56
|
+
"quality": "npm run lint && npm run typecheck:src && bun test test && npm run build",
|
|
57
|
+
"smoke:global": "node scripts/smoke-global-install.mjs",
|
|
53
58
|
"setup": "node --no-warnings --experimental-strip-types src/wechat/setup.ts",
|
|
54
59
|
"start": "node --no-warnings --experimental-strip-types src/wechat/wechat-channel.ts",
|
|
55
60
|
"check": "node --no-warnings --experimental-strip-types src/wechat/wechat-channel.ts --check",
|
|
@@ -80,8 +85,11 @@
|
|
|
80
85
|
"qrcode-terminal": "^0.12.0"
|
|
81
86
|
},
|
|
82
87
|
"devDependencies": {
|
|
88
|
+
"@eslint/js": "^10.0.1",
|
|
83
89
|
"@types/bun": "latest",
|
|
84
|
-
"
|
|
90
|
+
"eslint": "^10.3.0",
|
|
91
|
+
"typescript": "^6.0.2",
|
|
92
|
+
"typescript-eslint": "^8.59.3"
|
|
85
93
|
},
|
|
86
94
|
"engines": {
|
|
87
95
|
"bun": ">=1.0.0",
|