weacpx 0.3.1 → 0.4.0-beta.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 +109 -26
- package/config.example.json +8 -1
- package/dist/bridge/bridge-main.js +188 -7
- package/dist/channels/channel-scope.d.ts +9 -0
- package/dist/channels/cli/provider.d.ts +73 -0
- package/dist/channels/cli/registry.d.ts +7 -0
- package/dist/channels/cli/weixin-provider.d.ts +2 -0
- package/dist/channels/create-channel.d.ts +16 -0
- package/dist/channels/media-store.d.ts +29 -0
- package/dist/channels/media-types.d.ts +28 -0
- package/dist/channels/outbound-media-safety.d.ts +7 -0
- package/dist/channels/plugin.d.ts +9 -0
- package/dist/channels/types.d.ts +61 -0
- package/dist/channels/weixin-channel.d.ts +22 -0
- package/dist/cli.js +14701 -8461
- package/dist/config/types.d.ts +64 -0
- package/dist/logging/app-logger.d.ts +23 -0
- package/dist/orchestration/orchestration-types.d.ts +156 -0
- package/dist/plugin-api.d.ts +8 -0
- package/dist/plugin-api.js +180 -0
- package/dist/plugins/compatibility.d.ts +16 -0
- package/dist/plugins/known-plugins.d.ts +9 -0
- package/dist/plugins/types.d.ts +18 -0
- package/dist/version.d.ts +1 -0
- package/dist/weixin/agent/interface.d.ts +54 -0
- package/dist/weixin/api/api.d.ts +48 -0
- package/dist/weixin/api/config-cache.d.ts +18 -0
- package/dist/weixin/api/session-guard.d.ts +15 -0
- package/dist/weixin/api/types.d.ts +201 -0
- package/dist/weixin/auth/accounts.d.ts +63 -0
- package/dist/weixin/auth/login-qr.d.ts +31 -0
- package/dist/weixin/bot.d.ts +54 -0
- package/dist/weixin/cdn/aes-ecb.d.ts +6 -0
- package/dist/weixin/cdn/cdn-upload.d.ts +17 -0
- package/dist/weixin/cdn/cdn-url.d.ts +11 -0
- package/dist/weixin/cdn/pic-decrypt.d.ts +9 -0
- package/dist/weixin/cdn/upload.d.ts +42 -0
- package/dist/weixin/index.d.ts +6 -0
- package/dist/weixin/media/media-download.d.ts +18 -0
- package/dist/weixin/media/mime.d.ts +6 -0
- package/dist/weixin/media/silk-transcode.d.ts +8 -0
- package/dist/weixin/messaging/conversation-executor.d.ts +7 -0
- package/dist/weixin/messaging/debug-mode.d.ts +9 -0
- package/dist/weixin/messaging/deliver-coordinator-message.d.ts +22 -0
- package/dist/weixin/messaging/deliver-orchestration-task-notice.d.ts +18 -0
- package/dist/weixin/messaging/deliver-orchestration-task-progress.d.ts +16 -0
- package/dist/weixin/messaging/error-notice.d.ts +13 -0
- package/dist/weixin/messaging/execute-chat-turn.d.ts +12 -0
- package/dist/weixin/messaging/final-heads-up.d.ts +5 -0
- package/dist/weixin/messaging/handle-weixin-message-turn.d.ts +30 -0
- package/dist/weixin/messaging/inbound.d.ts +63 -0
- package/dist/weixin/messaging/orchestration-notice-accounts.d.ts +2 -0
- package/dist/weixin/messaging/quota-errors.d.ts +8 -0
- package/dist/weixin/messaging/quota-manager.d.ts +44 -0
- package/dist/weixin/messaging/send-errors.d.ts +39 -0
- package/dist/weixin/messaging/send-media.d.ts +23 -0
- package/dist/weixin/messaging/send-orchestration-notice.d.ts +10 -0
- package/dist/weixin/messaging/send.d.ts +71 -0
- package/dist/weixin/messaging/slash-commands.d.ts +40 -0
- package/dist/weixin/monitor/consumer-lock.d.ts +24 -0
- package/dist/weixin/monitor/monitor.d.ts +28 -0
- package/dist/weixin/storage/state-dir.d.ts +2 -0
- package/dist/weixin/storage/sync-buf.d.ts +20 -0
- package/dist/weixin/util/logger.d.ts +14 -0
- package/dist/weixin/util/random.d.ts +10 -0
- package/dist/weixin/util/redact.d.ts +21 -0
- package/package.json +41 -17
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weixin protocol types (mirrors proto: GetUpdatesReq/Resp, WeixinMessage, SendMessageReq).
|
|
3
|
+
* API uses JSON over HTTP; bytes fields are base64 strings in JSON.
|
|
4
|
+
*/
|
|
5
|
+
/** Common request metadata attached to every CGI request. */
|
|
6
|
+
export interface BaseInfo {
|
|
7
|
+
channel_version?: string;
|
|
8
|
+
}
|
|
9
|
+
/** proto: UploadMediaType */
|
|
10
|
+
export declare const UploadMediaType: {
|
|
11
|
+
readonly IMAGE: 1;
|
|
12
|
+
readonly VIDEO: 2;
|
|
13
|
+
readonly FILE: 3;
|
|
14
|
+
readonly VOICE: 4;
|
|
15
|
+
};
|
|
16
|
+
export interface GetUploadUrlReq {
|
|
17
|
+
filekey?: string;
|
|
18
|
+
/** proto field 2: media_type, see UploadMediaType */
|
|
19
|
+
media_type?: number;
|
|
20
|
+
to_user_id?: string;
|
|
21
|
+
/** 原文件明文大小 */
|
|
22
|
+
rawsize?: number;
|
|
23
|
+
/** 原文件明文 MD5 */
|
|
24
|
+
rawfilemd5?: string;
|
|
25
|
+
/** 原文件密文大小(AES-128-ECB 加密后) */
|
|
26
|
+
filesize?: number;
|
|
27
|
+
/** 缩略图明文大小(IMAGE/VIDEO 时必填) */
|
|
28
|
+
thumb_rawsize?: number;
|
|
29
|
+
/** 缩略图明文 MD5(IMAGE/VIDEO 时必填) */
|
|
30
|
+
thumb_rawfilemd5?: string;
|
|
31
|
+
/** 缩略图密文大小(IMAGE/VIDEO 时必填) */
|
|
32
|
+
thumb_filesize?: number;
|
|
33
|
+
/** 不需要缩略图上传 URL,默认 false */
|
|
34
|
+
no_need_thumb?: boolean;
|
|
35
|
+
/** 加密 key */
|
|
36
|
+
aeskey?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface GetUploadUrlResp {
|
|
39
|
+
/** 原图上传加密参数 */
|
|
40
|
+
upload_param?: string;
|
|
41
|
+
/** 缩略图上传加密参数,无缩略图时为空 */
|
|
42
|
+
thumb_upload_param?: string;
|
|
43
|
+
/** 完整上传 URL(服务端直接返回,无需客户端拼接) */
|
|
44
|
+
upload_full_url?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare const MessageType: {
|
|
47
|
+
readonly NONE: 0;
|
|
48
|
+
readonly USER: 1;
|
|
49
|
+
readonly BOT: 2;
|
|
50
|
+
};
|
|
51
|
+
export declare const MessageItemType: {
|
|
52
|
+
readonly NONE: 0;
|
|
53
|
+
readonly TEXT: 1;
|
|
54
|
+
readonly IMAGE: 2;
|
|
55
|
+
readonly VOICE: 3;
|
|
56
|
+
readonly FILE: 4;
|
|
57
|
+
readonly VIDEO: 5;
|
|
58
|
+
};
|
|
59
|
+
export declare const MessageState: {
|
|
60
|
+
readonly NEW: 0;
|
|
61
|
+
readonly GENERATING: 1;
|
|
62
|
+
readonly FINISH: 2;
|
|
63
|
+
};
|
|
64
|
+
export interface TextItem {
|
|
65
|
+
text?: string;
|
|
66
|
+
}
|
|
67
|
+
/** CDN media reference; aes_key is base64-encoded bytes in JSON. */
|
|
68
|
+
export interface CDNMedia {
|
|
69
|
+
encrypt_query_param?: string;
|
|
70
|
+
aes_key?: string;
|
|
71
|
+
/** 加密类型: 0=只加密fileid, 1=打包缩略图/中图等信息 */
|
|
72
|
+
encrypt_type?: number;
|
|
73
|
+
/** 完整下载 URL(服务端直接返回,无需客户端拼接) */
|
|
74
|
+
full_url?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface ImageItem {
|
|
77
|
+
/** 原图 CDN 引用 */
|
|
78
|
+
media?: CDNMedia;
|
|
79
|
+
/** 缩略图 CDN 引用 */
|
|
80
|
+
thumb_media?: CDNMedia;
|
|
81
|
+
/** Raw AES-128 key as hex string (16 bytes); preferred over media.aes_key for inbound decryption. */
|
|
82
|
+
aeskey?: string;
|
|
83
|
+
url?: string;
|
|
84
|
+
mid_size?: number;
|
|
85
|
+
thumb_size?: number;
|
|
86
|
+
thumb_height?: number;
|
|
87
|
+
thumb_width?: number;
|
|
88
|
+
hd_size?: number;
|
|
89
|
+
}
|
|
90
|
+
export interface VoiceItem {
|
|
91
|
+
media?: CDNMedia;
|
|
92
|
+
/** 语音编码类型:1=pcm 2=adpcm 3=feature 4=speex 5=amr 6=silk 7=mp3 8=ogg-speex */
|
|
93
|
+
encode_type?: number;
|
|
94
|
+
bits_per_sample?: number;
|
|
95
|
+
/** 采样率 (Hz) */
|
|
96
|
+
sample_rate?: number;
|
|
97
|
+
/** 语音长度 (毫秒) */
|
|
98
|
+
playtime?: number;
|
|
99
|
+
/** 语音转文字内容 */
|
|
100
|
+
text?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface FileItem {
|
|
103
|
+
media?: CDNMedia;
|
|
104
|
+
file_name?: string;
|
|
105
|
+
md5?: string;
|
|
106
|
+
len?: string;
|
|
107
|
+
}
|
|
108
|
+
export interface VideoItem {
|
|
109
|
+
media?: CDNMedia;
|
|
110
|
+
video_size?: number;
|
|
111
|
+
play_length?: number;
|
|
112
|
+
video_md5?: string;
|
|
113
|
+
thumb_media?: CDNMedia;
|
|
114
|
+
thumb_size?: number;
|
|
115
|
+
thumb_height?: number;
|
|
116
|
+
thumb_width?: number;
|
|
117
|
+
}
|
|
118
|
+
export interface RefMessage {
|
|
119
|
+
message_item?: MessageItem;
|
|
120
|
+
title?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface MessageItem {
|
|
123
|
+
type?: number;
|
|
124
|
+
create_time_ms?: number;
|
|
125
|
+
update_time_ms?: number;
|
|
126
|
+
is_completed?: boolean;
|
|
127
|
+
msg_id?: string;
|
|
128
|
+
ref_msg?: RefMessage;
|
|
129
|
+
text_item?: TextItem;
|
|
130
|
+
image_item?: ImageItem;
|
|
131
|
+
voice_item?: VoiceItem;
|
|
132
|
+
file_item?: FileItem;
|
|
133
|
+
video_item?: VideoItem;
|
|
134
|
+
}
|
|
135
|
+
/** Unified message (proto: WeixinMessage). Replaces the old split Message + MessageContent + FullMessage. */
|
|
136
|
+
export interface WeixinMessage {
|
|
137
|
+
seq?: number;
|
|
138
|
+
message_id?: number;
|
|
139
|
+
from_user_id?: string;
|
|
140
|
+
to_user_id?: string;
|
|
141
|
+
client_id?: string;
|
|
142
|
+
create_time_ms?: number;
|
|
143
|
+
update_time_ms?: number;
|
|
144
|
+
delete_time_ms?: number;
|
|
145
|
+
session_id?: string;
|
|
146
|
+
group_id?: string;
|
|
147
|
+
message_type?: number;
|
|
148
|
+
message_state?: number;
|
|
149
|
+
item_list?: MessageItem[];
|
|
150
|
+
context_token?: string;
|
|
151
|
+
}
|
|
152
|
+
/** GetUpdates request: bytes fields are base64 strings in JSON. */
|
|
153
|
+
export interface GetUpdatesReq {
|
|
154
|
+
/** @deprecated compat only, will be removed */
|
|
155
|
+
sync_buf?: string;
|
|
156
|
+
/** Full context buf cached locally; send "" when none (first request or after reset). */
|
|
157
|
+
get_updates_buf?: string;
|
|
158
|
+
}
|
|
159
|
+
/** GetUpdates response: bytes fields are base64 strings in JSON. */
|
|
160
|
+
export interface GetUpdatesResp {
|
|
161
|
+
ret?: number;
|
|
162
|
+
/** Error code returned by the server (e.g. -14 = session timeout). Present when request fails. */
|
|
163
|
+
errcode?: number;
|
|
164
|
+
errmsg?: string;
|
|
165
|
+
msgs?: WeixinMessage[];
|
|
166
|
+
/** @deprecated compat only */
|
|
167
|
+
sync_buf?: string;
|
|
168
|
+
/** Full context buf to cache locally and send on next request. */
|
|
169
|
+
get_updates_buf?: string;
|
|
170
|
+
/** Server-suggested timeout (ms) for the next getUpdates long-poll. */
|
|
171
|
+
longpolling_timeout_ms?: number;
|
|
172
|
+
}
|
|
173
|
+
/** SendMessage request: wraps a single WeixinMessage. */
|
|
174
|
+
export interface SendMessageReq {
|
|
175
|
+
msg?: WeixinMessage;
|
|
176
|
+
}
|
|
177
|
+
export interface SendMessageResp {
|
|
178
|
+
}
|
|
179
|
+
/** Typing status: 1 = typing (default), 2 = cancel typing. */
|
|
180
|
+
export declare const TypingStatus: {
|
|
181
|
+
readonly TYPING: 1;
|
|
182
|
+
readonly CANCEL: 2;
|
|
183
|
+
};
|
|
184
|
+
/** SendTyping request: send a typing indicator to a user. */
|
|
185
|
+
export interface SendTypingReq {
|
|
186
|
+
ilink_user_id?: string;
|
|
187
|
+
typing_ticket?: string;
|
|
188
|
+
/** 1=typing (default), 2=cancel typing */
|
|
189
|
+
status?: number;
|
|
190
|
+
}
|
|
191
|
+
export interface SendTypingResp {
|
|
192
|
+
ret?: number;
|
|
193
|
+
errmsg?: string;
|
|
194
|
+
}
|
|
195
|
+
/** GetConfig response: bot config including typing_ticket. */
|
|
196
|
+
export interface GetConfigResp {
|
|
197
|
+
ret?: number;
|
|
198
|
+
errmsg?: string;
|
|
199
|
+
/** Base64-encoded typing ticket for sendTyping. */
|
|
200
|
+
typing_ticket?: string;
|
|
201
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export declare const DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com";
|
|
2
|
+
export declare const CDN_BASE_URL = "https://novac2c.cdn.weixin.qq.com/c2c";
|
|
3
|
+
/** Normalize an account ID to a filesystem-safe string. */
|
|
4
|
+
export declare function normalizeAccountId(raw: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Pattern-based reverse of normalizeWeixinAccountId for known weixin ID suffixes.
|
|
7
|
+
* Used only as a compatibility fallback when loading accounts / sync bufs stored
|
|
8
|
+
* under the old raw ID.
|
|
9
|
+
* e.g. "b0f5860fdecb-im-bot" → "b0f5860fdecb@im.bot"
|
|
10
|
+
*/
|
|
11
|
+
export declare function deriveRawAccountId(normalizedId: string): string | undefined;
|
|
12
|
+
/** Returns all accountIds registered via QR login. */
|
|
13
|
+
export declare function listIndexedWeixinAccountIds(): string[];
|
|
14
|
+
/** Register accountId as the sole account in the persistent index. */
|
|
15
|
+
export declare function registerWeixinAccountId(accountId: string): void;
|
|
16
|
+
/** Unified per-account data: token + baseUrl in one file. */
|
|
17
|
+
export type WeixinAccountData = {
|
|
18
|
+
token?: string;
|
|
19
|
+
savedAt?: string;
|
|
20
|
+
baseUrl?: string;
|
|
21
|
+
/** Last linked Weixin user id from QR login (optional). */
|
|
22
|
+
userId?: string;
|
|
23
|
+
};
|
|
24
|
+
/** Load account data by ID, with compatibility fallbacks. */
|
|
25
|
+
export declare function loadWeixinAccount(accountId: string): WeixinAccountData | null;
|
|
26
|
+
/**
|
|
27
|
+
* Persist account data after QR login (merges into existing file).
|
|
28
|
+
* - token: overwritten when provided.
|
|
29
|
+
* - baseUrl: stored when non-empty; resolveWeixinAccount falls back to DEFAULT_BASE_URL.
|
|
30
|
+
* - userId: set when `update.userId` is provided; omitted from file when cleared to empty.
|
|
31
|
+
*/
|
|
32
|
+
export declare function saveWeixinAccount(accountId: string, update: {
|
|
33
|
+
token?: string;
|
|
34
|
+
baseUrl?: string;
|
|
35
|
+
userId?: string;
|
|
36
|
+
}): void;
|
|
37
|
+
/** Remove account data file. */
|
|
38
|
+
export declare function clearWeixinAccount(accountId: string): void;
|
|
39
|
+
/** Remove all account data files and clear the account index. */
|
|
40
|
+
export declare function clearAllWeixinAccounts(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Read `routeTag` from openclaw.json (for callers without an `OpenClawConfig` object).
|
|
43
|
+
* Checks per-account `channels.<id>.accounts[accountId].routeTag` first, then section-level
|
|
44
|
+
* `channels.<id>.routeTag`. Matches `feat_weixin_extension` behavior; channel key is `"openclaw-weixin"`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadConfigRouteTag(accountId?: string): string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* No-op stub — config reload is now handled externally via `openclaw gateway restart`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function triggerWeixinChannelReload(): Promise<void>;
|
|
51
|
+
export type ResolvedWeixinAccount = {
|
|
52
|
+
accountId: string;
|
|
53
|
+
baseUrl: string;
|
|
54
|
+
cdnBaseUrl: string;
|
|
55
|
+
token?: string;
|
|
56
|
+
enabled: boolean;
|
|
57
|
+
/** true when a token has been obtained via QR login. */
|
|
58
|
+
configured: boolean;
|
|
59
|
+
};
|
|
60
|
+
/** List accountIds from the index file (written at QR login). */
|
|
61
|
+
export declare function listWeixinAccountIds(): string[];
|
|
62
|
+
/** Resolve a weixin account by ID, reading stored credentials. */
|
|
63
|
+
export declare function resolveWeixinAccount(accountId?: string | null): ResolvedWeixinAccount;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Default `bot_type` for ilink get_bot_qrcode / get_qrcode_status (this channel build). */
|
|
2
|
+
export declare const DEFAULT_ILINK_BOT_TYPE = "3";
|
|
3
|
+
export type WeixinQrStartResult = {
|
|
4
|
+
qrcodeUrl?: string;
|
|
5
|
+
message: string;
|
|
6
|
+
sessionKey: string;
|
|
7
|
+
};
|
|
8
|
+
export type WeixinQrWaitResult = {
|
|
9
|
+
connected: boolean;
|
|
10
|
+
botToken?: string;
|
|
11
|
+
accountId?: string;
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
/** The user ID of the person who scanned the QR code; add to allowFrom. */
|
|
14
|
+
userId?: string;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function startWeixinLoginWithQr(opts: {
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
force?: boolean;
|
|
21
|
+
accountId?: string;
|
|
22
|
+
apiBaseUrl: string;
|
|
23
|
+
botType?: string;
|
|
24
|
+
}): Promise<WeixinQrStartResult>;
|
|
25
|
+
export declare function waitForWeixinLogin(opts: {
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
verbose?: boolean;
|
|
28
|
+
sessionKey: string;
|
|
29
|
+
apiBaseUrl: string;
|
|
30
|
+
botType?: string;
|
|
31
|
+
}): Promise<WeixinQrWaitResult>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Agent } from "./agent/interface.js";
|
|
2
|
+
import type { PendingFinalChunk } from "./messaging/quota-manager.js";
|
|
3
|
+
import type { RuntimeMediaStore } from "../channels/media-store.js";
|
|
4
|
+
export type LoginOptions = {
|
|
5
|
+
/** Override the API base URL. */
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
/** Log callback (defaults to console.log). */
|
|
8
|
+
log?: (msg: string) => void;
|
|
9
|
+
};
|
|
10
|
+
export type StartOptions = {
|
|
11
|
+
/** Account ID to use. Auto-selects the first registered account if omitted. */
|
|
12
|
+
accountId?: string;
|
|
13
|
+
/** Additional allowed root directories for outbound media paths. */
|
|
14
|
+
allowedMediaRoots?: string[];
|
|
15
|
+
/** AbortSignal to stop the bot. */
|
|
16
|
+
abortSignal?: AbortSignal;
|
|
17
|
+
/** Log callback (defaults to console.log). */
|
|
18
|
+
log?: (msg: string) => void;
|
|
19
|
+
/** Reset outbound quota when an inbound message arrives. */
|
|
20
|
+
onInbound?: (chatKey: string) => void;
|
|
21
|
+
/** Reserve the per-chat final-tier slot before sending the final reply.
|
|
22
|
+
* Returns false when the final tier (FINAL_BUDGET) is exhausted; callers
|
|
23
|
+
* must drop the send and log when this happens. */
|
|
24
|
+
reserveFinal?: (chatKey: string) => boolean;
|
|
25
|
+
finalRemaining?: (chatKey: string) => number;
|
|
26
|
+
hasPendingFinal?: (chatKey: string) => boolean;
|
|
27
|
+
drainPendingFinal?: (chatKey: string, available: number) => PendingFinalChunk[];
|
|
28
|
+
prependPendingFinal?: (chatKey: string, chunks: PendingFinalChunk[]) => void;
|
|
29
|
+
enqueuePendingFinal?: (chatKey: string, chunks: PendingFinalChunk[]) => void;
|
|
30
|
+
dropPendingFinal?: (chatKey: string) => void;
|
|
31
|
+
mediaStore?: RuntimeMediaStore;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Interactive QR-code login. Prints the QR code to the terminal and waits
|
|
35
|
+
* for the user to scan it with WeChat.
|
|
36
|
+
*
|
|
37
|
+
* Returns the normalized account ID on success.
|
|
38
|
+
*/
|
|
39
|
+
export declare function login(opts?: LoginOptions): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Remove all stored WeChat account credentials.
|
|
42
|
+
*/
|
|
43
|
+
export declare function logout(opts?: {
|
|
44
|
+
log?: (msg: string) => void;
|
|
45
|
+
}): void;
|
|
46
|
+
/**
|
|
47
|
+
* Check whether at least one WeChat account is logged in and configured.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isLoggedIn(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Start the bot — long-polls for new messages and dispatches them to the agent.
|
|
52
|
+
* Blocks until the abort signal fires or an unrecoverable error occurs.
|
|
53
|
+
*/
|
|
54
|
+
export declare function start(agent: Agent, opts?: StartOptions): Promise<void>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Encrypt buffer with AES-128-ECB (PKCS7 padding is default). */
|
|
2
|
+
export declare function encryptAesEcb(plaintext: Buffer, key: Buffer): Buffer;
|
|
3
|
+
/** Decrypt buffer with AES-128-ECB (PKCS7 padding). */
|
|
4
|
+
export declare function decryptAesEcb(ciphertext: Buffer, key: Buffer): Buffer;
|
|
5
|
+
/** Compute AES-128-ECB ciphertext size (PKCS7 padding to 16-byte boundary). */
|
|
6
|
+
export declare function aesEcbPaddedSize(plaintextSize: number): number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload one buffer to the Weixin CDN with AES-128-ECB encryption.
|
|
3
|
+
* Returns the download encrypted_query_param from the CDN response.
|
|
4
|
+
* Retries up to UPLOAD_MAX_RETRIES times on server errors; client errors (4xx) abort immediately.
|
|
5
|
+
*/
|
|
6
|
+
export declare function uploadBufferToCdn(params: {
|
|
7
|
+
buf: Buffer;
|
|
8
|
+
/** From getUploadUrl.upload_full_url; POST target when set (takes precedence over uploadParam). */
|
|
9
|
+
uploadFullUrl?: string;
|
|
10
|
+
uploadParam?: string;
|
|
11
|
+
filekey: string;
|
|
12
|
+
cdnBaseUrl: string;
|
|
13
|
+
label: string;
|
|
14
|
+
aeskey: Buffer;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
downloadParam: string;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified CDN URL construction for Weixin CDN upload/download.
|
|
3
|
+
*/
|
|
4
|
+
/** Build a CDN download URL from encrypt_query_param. */
|
|
5
|
+
export declare function buildCdnDownloadUrl(encryptedQueryParam: string, cdnBaseUrl: string): string;
|
|
6
|
+
/** Build a CDN upload URL from upload_param and filekey. */
|
|
7
|
+
export declare function buildCdnUploadUrl(params: {
|
|
8
|
+
cdnBaseUrl: string;
|
|
9
|
+
uploadParam: string;
|
|
10
|
+
filekey: string;
|
|
11
|
+
}): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download and AES-128-ECB decrypt a CDN media file. Returns plaintext Buffer.
|
|
3
|
+
* aesKeyBase64: CDNMedia.aes_key JSON field (see parseAesKey for supported formats).
|
|
4
|
+
*/
|
|
5
|
+
export declare function downloadAndDecryptBuffer(encryptedQueryParam: string, aesKeyBase64: string, cdnBaseUrl: string, label: string, fullUrl?: string, maxBytes?: number): Promise<Buffer>;
|
|
6
|
+
/**
|
|
7
|
+
* Download plain (unencrypted) bytes from the CDN. Returns the raw Buffer.
|
|
8
|
+
*/
|
|
9
|
+
export declare function downloadPlainCdnBuffer(encryptedQueryParam: string, cdnBaseUrl: string, label: string, fullUrl?: string, maxBytes?: number): Promise<Buffer>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { WeixinApiOptions } from "../api/api.js";
|
|
2
|
+
export type UploadedFileInfo = {
|
|
3
|
+
filekey: string;
|
|
4
|
+
/** 由 upload_param 上传后 CDN 返回的下载加密参数; fill into ImageItem.media.encrypt_query_param */
|
|
5
|
+
downloadEncryptedQueryParam: string;
|
|
6
|
+
/** AES-128-ECB key, hex-encoded; convert to base64 for CDNMedia.aes_key */
|
|
7
|
+
aeskey: string;
|
|
8
|
+
/** Plaintext file size in bytes */
|
|
9
|
+
fileSize: number;
|
|
10
|
+
/** Ciphertext file size in bytes (AES-128-ECB with PKCS7 padding); use for ImageItem.hd_size / mid_size */
|
|
11
|
+
fileSizeCiphertext: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Download a remote media URL (image, video, file) to a local temp file in destDir.
|
|
15
|
+
* Returns the local file path; extension is inferred from Content-Type / URL.
|
|
16
|
+
*/
|
|
17
|
+
export declare function downloadRemoteImageToTemp(url: string, destDir: string): Promise<string>;
|
|
18
|
+
/** Upload a local image file to the Weixin CDN with AES-128-ECB encryption. */
|
|
19
|
+
export declare function uploadFileToWeixin(params: {
|
|
20
|
+
filePath: string;
|
|
21
|
+
toUserId: string;
|
|
22
|
+
opts: WeixinApiOptions;
|
|
23
|
+
cdnBaseUrl: string;
|
|
24
|
+
}): Promise<UploadedFileInfo>;
|
|
25
|
+
/** Upload a local video file to the Weixin CDN. */
|
|
26
|
+
export declare function uploadVideoToWeixin(params: {
|
|
27
|
+
filePath: string;
|
|
28
|
+
toUserId: string;
|
|
29
|
+
opts: WeixinApiOptions;
|
|
30
|
+
cdnBaseUrl: string;
|
|
31
|
+
}): Promise<UploadedFileInfo>;
|
|
32
|
+
/**
|
|
33
|
+
* Upload a local file attachment (non-image, non-video) to the Weixin CDN.
|
|
34
|
+
* Uses media_type=FILE; no thumbnail required.
|
|
35
|
+
*/
|
|
36
|
+
export declare function uploadFileAttachmentToWeixin(params: {
|
|
37
|
+
filePath: string;
|
|
38
|
+
fileName: string;
|
|
39
|
+
toUserId: string;
|
|
40
|
+
opts: WeixinApiOptions;
|
|
41
|
+
cdnBaseUrl: string;
|
|
42
|
+
}): Promise<UploadedFileInfo>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { Agent, ChatRequest, ChatResponse } from "./agent/interface.js";
|
|
2
|
+
export { login, start, logout, isLoggedIn } from "./bot.js";
|
|
3
|
+
export type { LoginOptions, StartOptions } from "./bot.js";
|
|
4
|
+
export { sendMessageWeixin, markdownToPlainText } from "./messaging/send.js";
|
|
5
|
+
export { getContextToken } from "./messaging/inbound.js";
|
|
6
|
+
export { resolveWeixinAccount, listWeixinAccountIds, clearAllWeixinAccounts } from "./auth/accounts.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WeixinInboundMediaOpts } from "../messaging/inbound.js";
|
|
2
|
+
import type { WeixinMessage } from "../api/types.js";
|
|
3
|
+
/** Persist a buffer via the framework's unified media store. */
|
|
4
|
+
type SaveMediaFn = (buffer: Buffer, contentType?: string, subdir?: string, maxBytes?: number, originalFilename?: string) => Promise<{
|
|
5
|
+
path: string;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* Download and decrypt media from a single MessageItem.
|
|
9
|
+
* Returns the populated WeixinInboundMediaOpts fields; empty object on unsupported type or failure.
|
|
10
|
+
*/
|
|
11
|
+
export declare function downloadMediaFromItem(item: WeixinMessage["item_list"] extends (infer T)[] | undefined ? T : never, deps: {
|
|
12
|
+
cdnBaseUrl: string;
|
|
13
|
+
saveMedia: SaveMediaFn;
|
|
14
|
+
log: (msg: string) => void;
|
|
15
|
+
errLog: (msg: string) => void;
|
|
16
|
+
label: string;
|
|
17
|
+
}): Promise<WeixinInboundMediaOpts>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Get MIME type from filename extension. Returns "application/octet-stream" for unknown extensions. */
|
|
2
|
+
export declare function getMimeFromFilename(filename: string): string;
|
|
3
|
+
/** Get file extension from MIME type. Returns ".bin" for unknown types. */
|
|
4
|
+
export declare function getExtensionFromMime(mimeType: string): string;
|
|
5
|
+
/** Get file extension from Content-Type header or URL path. Returns ".bin" for unknown. */
|
|
6
|
+
export declare function getExtensionFromContentTypeOrUrl(contentType: string | null, url: string): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Try to transcode a SILK audio buffer to WAV using silk-wasm.
|
|
3
|
+
* silk-wasm's decode() returns { data: Uint8Array (pcm_s16le), duration: number }.
|
|
4
|
+
*
|
|
5
|
+
* Returns a WAV Buffer on success, or null if silk-wasm is unavailable or decoding fails.
|
|
6
|
+
* Callers should fall back to passing the raw SILK file when null is returned.
|
|
7
|
+
*/
|
|
8
|
+
export declare function silkToWav(silkBuf: Buffer): Promise<Buffer | null>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type ConversationExecutorLane = "normal" | "control";
|
|
2
|
+
type ConversationTask<T> = () => Promise<T>;
|
|
3
|
+
export type ConversationExecutor = {
|
|
4
|
+
run<T>(conversationId: string, lane: ConversationExecutorLane, task: ConversationTask<T>): Promise<T>;
|
|
5
|
+
};
|
|
6
|
+
export declare function createConversationExecutor(): ConversationExecutor;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Toggle debug mode for a bot account. Returns the new state. */
|
|
2
|
+
export declare function toggleDebugMode(accountId: string): boolean;
|
|
3
|
+
/** Check whether debug mode is active for a bot account. */
|
|
4
|
+
export declare function isDebugMode(accountId: string): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Reset internal state — only for tests.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function _resetForTest(): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AppLogger } from "../../logging/app-logger";
|
|
2
|
+
import { sendMessageWeixin } from "./send.js";
|
|
3
|
+
export interface DeliverCoordinatorMessageInput {
|
|
4
|
+
coordinatorSession: string;
|
|
5
|
+
chatKey: string;
|
|
6
|
+
accountId?: string;
|
|
7
|
+
replyContextToken?: string;
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DeliverCoordinatorMessageDeps {
|
|
11
|
+
listAccountIds: () => string[];
|
|
12
|
+
resolveAccount: (accountId: string) => {
|
|
13
|
+
accountId: string;
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
token?: string;
|
|
16
|
+
};
|
|
17
|
+
getContextToken: (accountId: string, userId: string) => string | undefined;
|
|
18
|
+
sendMessage?: typeof sendMessageWeixin;
|
|
19
|
+
reserveMidSegment?: (chatKey: string) => boolean;
|
|
20
|
+
logger: AppLogger;
|
|
21
|
+
}
|
|
22
|
+
export declare function deliverCoordinatorMessage(input: DeliverCoordinatorMessageInput, deps: DeliverCoordinatorMessageDeps): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AppLogger } from "../../logging/app-logger";
|
|
2
|
+
import type { OrchestrationTaskRecord } from "../../orchestration/orchestration-types";
|
|
3
|
+
import { sendOrchestrationTaskNotice } from "./send-orchestration-notice.js";
|
|
4
|
+
export interface DeliverOrchestrationTaskNoticeDeps {
|
|
5
|
+
listAccountIds: () => string[];
|
|
6
|
+
resolveAccount: (accountId: string) => {
|
|
7
|
+
accountId: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token?: string;
|
|
10
|
+
};
|
|
11
|
+
getContextToken: (accountId: string, userId: string) => string | undefined;
|
|
12
|
+
markDelivered: (taskId: string, accountId: string) => Promise<void>;
|
|
13
|
+
markFailed: (taskId: string, errorMessage: string) => Promise<void>;
|
|
14
|
+
sendNotice?: typeof sendOrchestrationTaskNotice;
|
|
15
|
+
reserveFinal?: (chatKey: string) => boolean;
|
|
16
|
+
logger: AppLogger;
|
|
17
|
+
}
|
|
18
|
+
export declare function deliverOrchestrationTaskNotice(task: OrchestrationTaskRecord, deps: DeliverOrchestrationTaskNoticeDeps): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AppLogger } from "../../logging/app-logger";
|
|
2
|
+
import type { OrchestrationTaskRecord } from "../../orchestration/orchestration-types";
|
|
3
|
+
import { sendMessageWeixin } from "./send.js";
|
|
4
|
+
export interface DeliverOrchestrationTaskProgressDeps {
|
|
5
|
+
listAccountIds: () => string[];
|
|
6
|
+
resolveAccount: (accountId: string) => {
|
|
7
|
+
accountId: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token?: string;
|
|
10
|
+
};
|
|
11
|
+
getContextToken: (accountId: string, userId: string) => string | undefined;
|
|
12
|
+
sendMessage?: typeof sendMessageWeixin;
|
|
13
|
+
reserveMidSegment?: (chatKey: string) => boolean;
|
|
14
|
+
logger: AppLogger;
|
|
15
|
+
}
|
|
16
|
+
export declare function deliverOrchestrationTaskProgress(task: OrchestrationTaskRecord, text: string, deps: DeliverOrchestrationTaskProgressDeps): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send a plain-text error notice back to the user.
|
|
3
|
+
* Fire-and-forget: errors are logged but never thrown, so callers stay unaffected.
|
|
4
|
+
* No-op when contextToken is absent (we have no conversation reference to reply into).
|
|
5
|
+
*/
|
|
6
|
+
export declare function sendWeixinErrorNotice(params: {
|
|
7
|
+
to: string;
|
|
8
|
+
contextToken: string | undefined;
|
|
9
|
+
message: string;
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
token?: string;
|
|
12
|
+
errLog: (m: string) => void;
|
|
13
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Agent, ChatRequest, ChatResponse } from "../agent/interface.js";
|
|
2
|
+
export interface ExecuteChatTurnParams {
|
|
3
|
+
agent: Agent;
|
|
4
|
+
request: Omit<ChatRequest, "reply">;
|
|
5
|
+
onReplySegment?: (text: string) => Promise<boolean | void>;
|
|
6
|
+
}
|
|
7
|
+
export interface ExecutedChatTurn {
|
|
8
|
+
text?: string;
|
|
9
|
+
media?: ChatResponse["media"];
|
|
10
|
+
usedReply: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function executeChatTurn(params: ExecuteChatTurnParams): Promise<ExecutedChatTurn>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Agent } from "../agent/interface.js";
|
|
2
|
+
import type { WeixinMessage } from "../api/types.js";
|
|
3
|
+
import { RuntimeMediaStore } from "../../channels/media-store.js";
|
|
4
|
+
import { downloadMediaFromItem } from "../media/media-download.js";
|
|
5
|
+
import type { PendingFinalChunk } from "./quota-manager.js";
|
|
6
|
+
export declare function chunkFinalText(text: string, maxBytes: number): string[];
|
|
7
|
+
export declare function resolveMediaTempDir(customRoot?: string): string;
|
|
8
|
+
export type HandleWeixinMessageTurnDeps = {
|
|
9
|
+
accountId: string;
|
|
10
|
+
agent: Agent;
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
cdnBaseUrl: string;
|
|
13
|
+
token?: string;
|
|
14
|
+
typingTicket?: string;
|
|
15
|
+
log: (msg: string) => void;
|
|
16
|
+
errLog: (msg: string) => void;
|
|
17
|
+
mediaTempDir?: string;
|
|
18
|
+
onInbound?: (chatKey: string) => void;
|
|
19
|
+
reserveFinal?: (chatKey: string) => boolean;
|
|
20
|
+
finalRemaining?: (chatKey: string) => number;
|
|
21
|
+
enqueuePendingFinal?: (chatKey: string, chunks: PendingFinalChunk[]) => void;
|
|
22
|
+
hasPendingFinal?: (chatKey: string) => boolean;
|
|
23
|
+
drainPendingFinal?: (chatKey: string, available: number) => PendingFinalChunk[];
|
|
24
|
+
prependPendingFinal?: (chatKey: string, chunks: PendingFinalChunk[]) => void;
|
|
25
|
+
mediaStore?: RuntimeMediaStore;
|
|
26
|
+
downloadMediaFromItemFn?: typeof downloadMediaFromItem;
|
|
27
|
+
allowedMediaRoots?: string[];
|
|
28
|
+
};
|
|
29
|
+
export declare function getWeixinMessageTurnLane(full: WeixinMessage): "normal" | "control";
|
|
30
|
+
export declare function handleWeixinMessageTurn(full: WeixinMessage, deps: HandleWeixinMessageTurnDeps): Promise<void>;
|