wechat-acp 0.1.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/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/bin/wechat-acp.d.ts +14 -0
- package/dist/bin/wechat-acp.d.ts.map +1 -0
- package/dist/bin/wechat-acp.js +270 -0
- package/dist/bin/wechat-acp.js.map +1 -0
- package/dist/package.json +55 -0
- package/dist/src/acp/agent-manager.d.ts +21 -0
- package/dist/src/acp/agent-manager.d.ts.map +1 -0
- package/dist/src/acp/agent-manager.js +73 -0
- package/dist/src/acp/agent-manager.js.map +1 -0
- package/dist/src/acp/client.d.ts +28 -0
- package/dist/src/acp/client.d.ts.map +1 -0
- package/dist/src/acp/client.js +121 -0
- package/dist/src/acp/client.js.map +1 -0
- package/dist/src/acp/session.d.ts +51 -0
- package/dist/src/acp/session.d.ts.map +1 -0
- package/dist/src/acp/session.js +173 -0
- package/dist/src/acp/session.js.map +1 -0
- package/dist/src/adapter/inbound.d.ts +10 -0
- package/dist/src/adapter/inbound.d.ts.map +1 -0
- package/dist/src/adapter/inbound.js +146 -0
- package/dist/src/adapter/inbound.js.map +1 -0
- package/dist/src/adapter/outbound.d.ts +9 -0
- package/dist/src/adapter/outbound.d.ts.map +1 -0
- package/dist/src/adapter/outbound.js +25 -0
- package/dist/src/adapter/outbound.js.map +1 -0
- package/dist/src/bridge.d.ts +28 -0
- package/dist/src/bridge.d.ts.map +1 -0
- package/dist/src/bridge.js +171 -0
- package/dist/src/bridge.js.map +1 -0
- package/dist/src/config.d.ts +61 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +114 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/weixin/api.d.ts +50 -0
- package/dist/src/weixin/api.d.ts.map +1 -0
- package/dist/src/weixin/api.js +84 -0
- package/dist/src/weixin/api.js.map +1 -0
- package/dist/src/weixin/auth.d.ts +20 -0
- package/dist/src/weixin/auth.d.ts.map +1 -0
- package/dist/src/weixin/auth.js +84 -0
- package/dist/src/weixin/auth.js.map +1 -0
- package/dist/src/weixin/media.d.ts +23 -0
- package/dist/src/weixin/media.d.ts.map +1 -0
- package/dist/src/weixin/media.js +58 -0
- package/dist/src/weixin/media.js.map +1 -0
- package/dist/src/weixin/monitor.d.ts +16 -0
- package/dist/src/weixin/monitor.d.ts.map +1 -0
- package/dist/src/weixin/monitor.js +111 -0
- package/dist/src/weixin/monitor.js.map +1 -0
- package/dist/src/weixin/send.d.ts +14 -0
- package/dist/src/weixin/send.d.ts.map +1 -0
- package/dist/src/weixin/send.js +51 -0
- package/dist/src/weixin/send.js.map +1 -0
- package/dist/src/weixin/types.d.ts +148 -0
- package/dist/src/weixin/types.d.ts.map +1 -0
- package/dist/src/weixin/types.js +33 -0
- package/dist/src/weixin/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/weixin/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES-128-ECB encrypt/decrypt for WeChat CDN media.
|
|
3
|
+
* Adapted from @tencent-weixin/openclaw-weixin cdn/aes-ecb.ts
|
|
4
|
+
*/
|
|
5
|
+
import type { CDNMedia } from "./types.js";
|
|
6
|
+
export declare function encryptAesEcb(plaintext: Buffer, key: Buffer): Buffer;
|
|
7
|
+
export declare function decryptAesEcb(ciphertext: Buffer, key: Buffer): Buffer;
|
|
8
|
+
/**
|
|
9
|
+
* Parse the AES key from CDN media reference.
|
|
10
|
+
* The key can be either:
|
|
11
|
+
* - base64 → 16 raw bytes (use directly)
|
|
12
|
+
* - base64 → 32 hex chars → parse hex → 16 bytes
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseAesKey(media: CDNMedia): Buffer | null;
|
|
15
|
+
export declare function downloadAndDecrypt(encryptQueryParam: string, aesKey: Buffer, cdnBaseUrl: string): Promise<Buffer>;
|
|
16
|
+
export declare function uploadToCdn(params: {
|
|
17
|
+
buffer: Buffer;
|
|
18
|
+
uploadParam: string;
|
|
19
|
+
aesKey: Buffer;
|
|
20
|
+
filekey: string;
|
|
21
|
+
cdnBaseUrl: string;
|
|
22
|
+
}): Promise<string>;
|
|
23
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../src/weixin/media.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAa1D;AAED,wBAAsB,kBAAkB,CACtC,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CAclB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES-128-ECB encrypt/decrypt for WeChat CDN media.
|
|
3
|
+
* Adapted from @tencent-weixin/openclaw-weixin cdn/aes-ecb.ts
|
|
4
|
+
*/
|
|
5
|
+
import crypto from "node:crypto";
|
|
6
|
+
export function encryptAesEcb(plaintext, key) {
|
|
7
|
+
const cipher = crypto.createCipheriv("aes-128-ecb", key, null);
|
|
8
|
+
return Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
9
|
+
}
|
|
10
|
+
export function decryptAesEcb(ciphertext, key) {
|
|
11
|
+
const decipher = crypto.createDecipheriv("aes-128-ecb", key, null);
|
|
12
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse the AES key from CDN media reference.
|
|
16
|
+
* The key can be either:
|
|
17
|
+
* - base64 → 16 raw bytes (use directly)
|
|
18
|
+
* - base64 → 32 hex chars → parse hex → 16 bytes
|
|
19
|
+
*/
|
|
20
|
+
export function parseAesKey(media) {
|
|
21
|
+
const raw = media.aes_key;
|
|
22
|
+
if (!raw)
|
|
23
|
+
return null;
|
|
24
|
+
const decoded = Buffer.from(raw, "base64");
|
|
25
|
+
if (decoded.length === 16)
|
|
26
|
+
return decoded;
|
|
27
|
+
if (decoded.length === 32) {
|
|
28
|
+
const hexStr = decoded.toString("ascii");
|
|
29
|
+
if (/^[0-9a-fA-F]{32}$/.test(hexStr)) {
|
|
30
|
+
return Buffer.from(hexStr, "hex");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return decoded.subarray(0, 16);
|
|
34
|
+
}
|
|
35
|
+
export async function downloadAndDecrypt(encryptQueryParam, aesKey, cdnBaseUrl) {
|
|
36
|
+
const url = `${cdnBaseUrl}/download?encrypted_query_param=${encodeURIComponent(encryptQueryParam)}`;
|
|
37
|
+
const res = await fetch(url);
|
|
38
|
+
if (!res.ok)
|
|
39
|
+
throw new Error(`CDN download failed: HTTP ${res.status}`);
|
|
40
|
+
const ciphertext = Buffer.from(await res.arrayBuffer());
|
|
41
|
+
return decryptAesEcb(ciphertext, aesKey);
|
|
42
|
+
}
|
|
43
|
+
export async function uploadToCdn(params) {
|
|
44
|
+
const encrypted = encryptAesEcb(params.buffer, params.aesKey);
|
|
45
|
+
const url = `${params.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(params.uploadParam)}&filekey=${encodeURIComponent(params.filekey)}`;
|
|
46
|
+
const res = await fetch(url, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
49
|
+
body: encrypted,
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok)
|
|
52
|
+
throw new Error(`CDN upload failed: HTTP ${res.status}`);
|
|
53
|
+
const downloadParam = res.headers.get("x-encrypted-param");
|
|
54
|
+
if (!downloadParam)
|
|
55
|
+
throw new Error("CDN upload: missing x-encrypted-param header");
|
|
56
|
+
return downloadParam;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../../src/weixin/media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat long-poll monitor loop.
|
|
3
|
+
* Polls getUpdates, dispatches messages via callback.
|
|
4
|
+
*/
|
|
5
|
+
import type { WeixinMessage } from "./types.js";
|
|
6
|
+
export interface MonitorOpts {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
token?: string;
|
|
9
|
+
storageDir: string;
|
|
10
|
+
abortSignal?: AbortSignal;
|
|
11
|
+
longPollTimeoutMs?: number;
|
|
12
|
+
log: (msg: string) => void;
|
|
13
|
+
onMessage: (msg: WeixinMessage) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function startMonitor(opts: MonitorOpts): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../../src/weixin/monitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AAQhE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,SAAS,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;CACzC;AA8BD,wBAAsB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA+EnE"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat long-poll monitor loop.
|
|
3
|
+
* Polls getUpdates, dispatches messages via callback.
|
|
4
|
+
*/
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { getUpdates } from "./api.js";
|
|
8
|
+
const DEFAULT_LONG_POLL_TIMEOUT_MS = 35_000;
|
|
9
|
+
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
10
|
+
const BACKOFF_DELAY_MS = 30_000;
|
|
11
|
+
const RETRY_DELAY_MS = 2_000;
|
|
12
|
+
const SESSION_EXPIRED_ERRCODE = -14;
|
|
13
|
+
function getSyncBufPath(storageDir) {
|
|
14
|
+
return path.join(storageDir, "sync-buf.json");
|
|
15
|
+
}
|
|
16
|
+
function loadSyncBuf(storageDir) {
|
|
17
|
+
const p = getSyncBufPath(storageDir);
|
|
18
|
+
if (!fs.existsSync(p))
|
|
19
|
+
return "";
|
|
20
|
+
try {
|
|
21
|
+
const data = JSON.parse(fs.readFileSync(p, "utf-8"));
|
|
22
|
+
return data.get_updates_buf ?? "";
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function saveSyncBuf(storageDir, buf) {
|
|
29
|
+
fs.mkdirSync(storageDir, { recursive: true });
|
|
30
|
+
fs.writeFileSync(getSyncBufPath(storageDir), JSON.stringify({ get_updates_buf: buf }), "utf-8");
|
|
31
|
+
}
|
|
32
|
+
function sleep(ms, signal) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
if (signal?.aborted) {
|
|
35
|
+
reject(new Error("aborted"));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const t = setTimeout(resolve, ms);
|
|
39
|
+
signal?.addEventListener("abort", () => { clearTimeout(t); reject(new Error("aborted")); }, { once: true });
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export async function startMonitor(opts) {
|
|
43
|
+
const { baseUrl, token, storageDir, abortSignal, log, onMessage } = opts;
|
|
44
|
+
let getUpdatesBuf = loadSyncBuf(storageDir);
|
|
45
|
+
if (getUpdatesBuf) {
|
|
46
|
+
log(`Resuming from previous sync buf (${getUpdatesBuf.length} bytes)`);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
log("No previous sync buf, starting fresh");
|
|
50
|
+
}
|
|
51
|
+
let nextTimeoutMs = opts.longPollTimeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS;
|
|
52
|
+
let consecutiveFailures = 0;
|
|
53
|
+
while (!abortSignal?.aborted) {
|
|
54
|
+
try {
|
|
55
|
+
const resp = await getUpdates({
|
|
56
|
+
baseUrl,
|
|
57
|
+
token,
|
|
58
|
+
get_updates_buf: getUpdatesBuf,
|
|
59
|
+
timeoutMs: nextTimeoutMs,
|
|
60
|
+
});
|
|
61
|
+
if (resp.longpolling_timeout_ms != null && resp.longpolling_timeout_ms > 0) {
|
|
62
|
+
nextTimeoutMs = resp.longpolling_timeout_ms;
|
|
63
|
+
}
|
|
64
|
+
const isApiError = (resp.ret !== undefined && resp.ret !== 0) ||
|
|
65
|
+
(resp.errcode !== undefined && resp.errcode !== 0);
|
|
66
|
+
if (isApiError) {
|
|
67
|
+
const isSessionExpired = resp.errcode === SESSION_EXPIRED_ERRCODE || resp.ret === SESSION_EXPIRED_ERRCODE;
|
|
68
|
+
if (isSessionExpired) {
|
|
69
|
+
log(`Session expired (errcode ${SESSION_EXPIRED_ERRCODE}), pausing 1 hour...`);
|
|
70
|
+
consecutiveFailures = 0;
|
|
71
|
+
await sleep(60 * 60_000, abortSignal);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
consecutiveFailures++;
|
|
75
|
+
log(`getUpdates failed: ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg ?? ""} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})`);
|
|
76
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
77
|
+
log(`${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off ${BACKOFF_DELAY_MS / 1000}s`);
|
|
78
|
+
consecutiveFailures = 0;
|
|
79
|
+
await sleep(BACKOFF_DELAY_MS, abortSignal);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
await sleep(RETRY_DELAY_MS, abortSignal);
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
consecutiveFailures = 0;
|
|
87
|
+
if (resp.get_updates_buf != null && resp.get_updates_buf !== "") {
|
|
88
|
+
saveSyncBuf(storageDir, resp.get_updates_buf);
|
|
89
|
+
getUpdatesBuf = resp.get_updates_buf;
|
|
90
|
+
}
|
|
91
|
+
for (const msg of resp.msgs ?? []) {
|
|
92
|
+
onMessage(msg);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (abortSignal?.aborted)
|
|
97
|
+
return;
|
|
98
|
+
consecutiveFailures++;
|
|
99
|
+
log(`getUpdates error (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${String(err)}`);
|
|
100
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
101
|
+
log(`${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off ${BACKOFF_DELAY_MS / 1000}s`);
|
|
102
|
+
consecutiveFailures = 0;
|
|
103
|
+
await sleep(BACKOFF_DELAY_MS, abortSignal);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
await sleep(RETRY_DELAY_MS, abortSignal);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../src/weixin/monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send messages via WeChat iLink API.
|
|
3
|
+
*/
|
|
4
|
+
export interface WeixinSendOpts {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
token?: string;
|
|
7
|
+
contextToken?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function sendTextMessage(to: string, text: string, opts: WeixinSendOpts): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Split text into segments of max length, respecting line breaks where possible.
|
|
12
|
+
*/
|
|
13
|
+
export declare function splitText(text: string, maxLen: number): string[];
|
|
14
|
+
//# sourceMappingURL=send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../../src/weixin/send.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBhE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send messages via WeChat iLink API.
|
|
3
|
+
*/
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import { sendMessage } from "./api.js";
|
|
6
|
+
import { MessageType, MessageState } from "./types.js";
|
|
7
|
+
export async function sendTextMessage(to, text, opts) {
|
|
8
|
+
if (!opts.contextToken) {
|
|
9
|
+
throw new Error("contextToken is required to send a message");
|
|
10
|
+
}
|
|
11
|
+
const clientId = `wechat-acp-${crypto.randomUUID()}`;
|
|
12
|
+
await sendMessage({
|
|
13
|
+
baseUrl: opts.baseUrl,
|
|
14
|
+
token: opts.token,
|
|
15
|
+
body: {
|
|
16
|
+
msg: {
|
|
17
|
+
from_user_id: "",
|
|
18
|
+
to_user_id: to,
|
|
19
|
+
client_id: clientId,
|
|
20
|
+
message_type: MessageType.BOT,
|
|
21
|
+
message_state: MessageState.FINISH,
|
|
22
|
+
context_token: opts.contextToken,
|
|
23
|
+
item_list: [{ type: 1, text_item: { text } }],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return clientId;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Split text into segments of max length, respecting line breaks where possible.
|
|
31
|
+
*/
|
|
32
|
+
export function splitText(text, maxLen) {
|
|
33
|
+
if (text.length <= maxLen)
|
|
34
|
+
return [text];
|
|
35
|
+
const segments = [];
|
|
36
|
+
let remaining = text;
|
|
37
|
+
while (remaining.length > 0) {
|
|
38
|
+
if (remaining.length <= maxLen) {
|
|
39
|
+
segments.push(remaining);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
// Try to break at a newline
|
|
43
|
+
let breakAt = remaining.lastIndexOf("\n", maxLen);
|
|
44
|
+
if (breakAt <= 0)
|
|
45
|
+
breakAt = maxLen;
|
|
46
|
+
segments.push(remaining.substring(0, breakAt));
|
|
47
|
+
remaining = remaining.substring(breakAt).replace(/^\n/, "");
|
|
48
|
+
}
|
|
49
|
+
return segments;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../../src/weixin/send.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQvD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAU,EACV,IAAY,EACZ,IAAoB;IAEpB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;IACrD,MAAM,WAAW,CAAC;QAChB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE;YACJ,GAAG,EAAE;gBACH,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE,EAAE;gBACd,SAAS,EAAE,QAAQ;gBACnB,YAAY,EAAE,WAAW,CAAC,GAAG;gBAC7B,aAAa,EAAE,YAAY,CAAC,MAAM;gBAClC,aAAa,EAAE,IAAI,CAAC,YAAY;gBAChC,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;aAC9C;SACF;KACF,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,MAAc;IACpD,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,SAAS,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,MAAM;QACR,CAAC;QAED,4BAA4B;QAC5B,IAAI,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,OAAO,IAAI,CAAC;YAAE,OAAO,GAAG,MAAM,CAAC;QAEnC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/C,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat iLink protocol types.
|
|
3
|
+
* Adapted from @tencent-weixin/openclaw-weixin api/types.ts
|
|
4
|
+
*/
|
|
5
|
+
export interface BaseInfo {
|
|
6
|
+
channel_version?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const UploadMediaType: {
|
|
9
|
+
readonly IMAGE: 1;
|
|
10
|
+
readonly VIDEO: 2;
|
|
11
|
+
readonly FILE: 3;
|
|
12
|
+
readonly VOICE: 4;
|
|
13
|
+
};
|
|
14
|
+
export declare const MessageType: {
|
|
15
|
+
readonly NONE: 0;
|
|
16
|
+
readonly USER: 1;
|
|
17
|
+
readonly BOT: 2;
|
|
18
|
+
};
|
|
19
|
+
export declare const MessageItemType: {
|
|
20
|
+
readonly NONE: 0;
|
|
21
|
+
readonly TEXT: 1;
|
|
22
|
+
readonly IMAGE: 2;
|
|
23
|
+
readonly VOICE: 3;
|
|
24
|
+
readonly FILE: 4;
|
|
25
|
+
readonly VIDEO: 5;
|
|
26
|
+
};
|
|
27
|
+
export declare const MessageState: {
|
|
28
|
+
readonly NEW: 0;
|
|
29
|
+
readonly GENERATING: 1;
|
|
30
|
+
readonly FINISH: 2;
|
|
31
|
+
};
|
|
32
|
+
export declare const TypingStatus: {
|
|
33
|
+
readonly TYPING: 1;
|
|
34
|
+
readonly CANCEL: 2;
|
|
35
|
+
};
|
|
36
|
+
export interface TextItem {
|
|
37
|
+
text?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CDNMedia {
|
|
40
|
+
encrypt_query_param?: string;
|
|
41
|
+
aes_key?: string;
|
|
42
|
+
encrypt_type?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface ImageItem {
|
|
45
|
+
media?: CDNMedia;
|
|
46
|
+
thumb_media?: CDNMedia;
|
|
47
|
+
aeskey?: string;
|
|
48
|
+
url?: string;
|
|
49
|
+
mid_size?: number;
|
|
50
|
+
thumb_size?: number;
|
|
51
|
+
thumb_height?: number;
|
|
52
|
+
thumb_width?: number;
|
|
53
|
+
hd_size?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface VoiceItem {
|
|
56
|
+
media?: CDNMedia;
|
|
57
|
+
encode_type?: number;
|
|
58
|
+
bits_per_sample?: number;
|
|
59
|
+
sample_rate?: number;
|
|
60
|
+
playtime?: number;
|
|
61
|
+
text?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface FileItem {
|
|
64
|
+
media?: CDNMedia;
|
|
65
|
+
file_name?: string;
|
|
66
|
+
md5?: string;
|
|
67
|
+
len?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface VideoItem {
|
|
70
|
+
media?: CDNMedia;
|
|
71
|
+
video_size?: number;
|
|
72
|
+
play_length?: number;
|
|
73
|
+
video_md5?: string;
|
|
74
|
+
thumb_media?: CDNMedia;
|
|
75
|
+
thumb_size?: number;
|
|
76
|
+
thumb_height?: number;
|
|
77
|
+
thumb_width?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface RefMessage {
|
|
80
|
+
message_item?: MessageItem;
|
|
81
|
+
title?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface MessageItem {
|
|
84
|
+
type?: number;
|
|
85
|
+
create_time_ms?: number;
|
|
86
|
+
update_time_ms?: number;
|
|
87
|
+
is_completed?: boolean;
|
|
88
|
+
msg_id?: string;
|
|
89
|
+
ref_msg?: RefMessage;
|
|
90
|
+
text_item?: TextItem;
|
|
91
|
+
image_item?: ImageItem;
|
|
92
|
+
voice_item?: VoiceItem;
|
|
93
|
+
file_item?: FileItem;
|
|
94
|
+
video_item?: VideoItem;
|
|
95
|
+
}
|
|
96
|
+
export interface WeixinMessage {
|
|
97
|
+
seq?: number;
|
|
98
|
+
message_id?: number;
|
|
99
|
+
from_user_id?: string;
|
|
100
|
+
to_user_id?: string;
|
|
101
|
+
client_id?: string;
|
|
102
|
+
create_time_ms?: number;
|
|
103
|
+
update_time_ms?: number;
|
|
104
|
+
delete_time_ms?: number;
|
|
105
|
+
session_id?: string;
|
|
106
|
+
group_id?: string;
|
|
107
|
+
message_type?: number;
|
|
108
|
+
message_state?: number;
|
|
109
|
+
item_list?: MessageItem[];
|
|
110
|
+
context_token?: string;
|
|
111
|
+
}
|
|
112
|
+
export interface GetUpdatesResp {
|
|
113
|
+
ret?: number;
|
|
114
|
+
errcode?: number;
|
|
115
|
+
errmsg?: string;
|
|
116
|
+
msgs?: WeixinMessage[];
|
|
117
|
+
get_updates_buf?: string;
|
|
118
|
+
longpolling_timeout_ms?: number;
|
|
119
|
+
}
|
|
120
|
+
export interface SendMessageReq {
|
|
121
|
+
msg?: WeixinMessage;
|
|
122
|
+
}
|
|
123
|
+
export interface GetUploadUrlReq {
|
|
124
|
+
filekey?: string;
|
|
125
|
+
media_type?: number;
|
|
126
|
+
to_user_id?: string;
|
|
127
|
+
rawsize?: number;
|
|
128
|
+
rawfilemd5?: string;
|
|
129
|
+
filesize?: number;
|
|
130
|
+
thumb_rawsize?: number;
|
|
131
|
+
thumb_rawfilemd5?: string;
|
|
132
|
+
thumb_filesize?: number;
|
|
133
|
+
no_need_thumb?: boolean;
|
|
134
|
+
aeskey?: string;
|
|
135
|
+
}
|
|
136
|
+
export interface GetUploadUrlResp {
|
|
137
|
+
upload_param?: string;
|
|
138
|
+
thumb_upload_param?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface SendTypingReq {
|
|
141
|
+
ilink_user_id: string;
|
|
142
|
+
typing_ticket: string;
|
|
143
|
+
status: number;
|
|
144
|
+
}
|
|
145
|
+
export interface GetConfigResp {
|
|
146
|
+
typing_ticket?: string;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/weixin/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat iLink protocol types.
|
|
3
|
+
* Adapted from @tencent-weixin/openclaw-weixin api/types.ts
|
|
4
|
+
*/
|
|
5
|
+
export const UploadMediaType = {
|
|
6
|
+
IMAGE: 1,
|
|
7
|
+
VIDEO: 2,
|
|
8
|
+
FILE: 3,
|
|
9
|
+
VOICE: 4,
|
|
10
|
+
};
|
|
11
|
+
export const MessageType = {
|
|
12
|
+
NONE: 0,
|
|
13
|
+
USER: 1,
|
|
14
|
+
BOT: 2,
|
|
15
|
+
};
|
|
16
|
+
export const MessageItemType = {
|
|
17
|
+
NONE: 0,
|
|
18
|
+
TEXT: 1,
|
|
19
|
+
IMAGE: 2,
|
|
20
|
+
VOICE: 3,
|
|
21
|
+
FILE: 4,
|
|
22
|
+
VIDEO: 5,
|
|
23
|
+
};
|
|
24
|
+
export const MessageState = {
|
|
25
|
+
NEW: 0,
|
|
26
|
+
GENERATING: 1,
|
|
27
|
+
FINISH: 2,
|
|
28
|
+
};
|
|
29
|
+
export const TypingStatus = {
|
|
30
|
+
TYPING: 1,
|
|
31
|
+
CANCEL: 2,
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/weixin/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACA,CAAC;AAEX,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;CACE,CAAC;AAEX,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACA,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,GAAG,EAAE,CAAC;IACN,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;CACD,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;CACD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wechat-acp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Bridge WeChat to any ACP-compatible AI agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/",
|
|
8
|
+
"README.md",
|
|
9
|
+
"package.json"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"wechat-acp": "./dist/bin/wechat-acp.js"
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/src/index.js",
|
|
15
|
+
"types": "./dist/src/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/src/index.js",
|
|
19
|
+
"types": "./dist/src/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"prepack": "npm run build",
|
|
25
|
+
"start": "node dist/bin/wechat-acp.js",
|
|
26
|
+
"dev": "tsc --watch"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@agentclientprotocol/sdk": "^0.16.1",
|
|
30
|
+
"qrcode-terminal": "^0.12.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"typescript": "^5.5.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20.0.0"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/formulahendry/wechat-acp.git"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/formulahendry/wechat-acp#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/formulahendry/wechat-acp/issues"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"keywords": [
|
|
49
|
+
"wechat",
|
|
50
|
+
"acp",
|
|
51
|
+
"agent-client-protocol",
|
|
52
|
+
"ai-agent",
|
|
53
|
+
"bridge"
|
|
54
|
+
]
|
|
55
|
+
}
|