@0xmaxma/claude-gateway 1.8.13 → 1.8.14

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.
@@ -0,0 +1,194 @@
1
+ export interface ILinkCredentials {
2
+ accountId: string;
3
+ token: string;
4
+ baseUrl: string;
5
+ }
6
+ export interface ILinkQrSession {
7
+ /** Data URI (or remote image URL) to render as the login QR. */
8
+ qrDataUri: string;
9
+ /** Opaque handle to poll for this specific login attempt's completion. */
10
+ loginSessionId: string;
11
+ }
12
+ export interface ILinkLinkResult {
13
+ linked: boolean;
14
+ credentials?: ILinkCredentials;
15
+ /**
16
+ * The raw status string Tencent returned (`wait`/`scaned`/`confirmed`/
17
+ * `expired`/`need_verifycode`/`verify_code_blocked`/`scaned_but_redirect`/
18
+ * `binded_redirect`), surfaced purely for operational logging — nothing
19
+ * downstream branches on it besides `linked` above. Added after a live
20
+ * link attempt where the confirm button was tapped but nothing here ever
21
+ * saw `confirmed`, with zero visibility into which of these statuses it
22
+ * actually got stuck on.
23
+ */
24
+ status?: string;
25
+ }
26
+ export interface ILinkUpdate {
27
+ /** iLink message id — used for at-least-once delivery de-duplication. */
28
+ id: string;
29
+ /** Sender's iLink user id. */
30
+ fromId: string;
31
+ /** Plain text body, when present. */
32
+ text?: string;
33
+ /** Best-effort display name, when iLink provides one. */
34
+ displayName?: string;
35
+ /** Server timestamp (ms since epoch), when provided. */
36
+ timestamp?: number;
37
+ /**
38
+ * Conversation context token this specific message carries (Tencent's
39
+ * `WeixinMessage.context_token`) — established by an INBOUND message, not
40
+ * minted by sending one. Must be echoed on the next `sendText` call to
41
+ * this same sender. See this module's doc comment for why `sendText`
42
+ * itself no longer returns one.
43
+ */
44
+ contextToken?: string;
45
+ /** Present when this message carries an inbound image (item type 2). Download+decrypt via `downloadWeixinImage()`. */
46
+ image?: ILinkImageRef;
47
+ /** Present when this message carries an inbound file (item type 4, e.g. a PDF). Download+decrypt via `downloadWeixinImage()`, same as an image. */
48
+ file?: ILinkFileRef;
49
+ }
50
+ /** Resolved download target for an inbound image, from `resolveWeixinImageRef()`. */
51
+ export interface ILinkImageRef {
52
+ url: string;
53
+ /** Absent means the bytes at `url` are already plaintext. */
54
+ aesKey?: Buffer;
55
+ /**
56
+ * Sender-declared plaintext byte count (`file_item.len` — files only, per
57
+ * protocol.md). When set and the decrypted buffer is longer than this,
58
+ * `downloadWeixinImage` keeps the trailing `expectedLength` bytes and
59
+ * drops the rest as a leading prefix — confirmed live 2026-09-11: a real
60
+ * decrypted PDF carried 3 extra bytes before its `%PDF-` header despite a
61
+ * byte-perfect key/cipher (images never show this, only files), so
62
+ * WeChat's file upload path evidently prepends a few bytes ahead of the
63
+ * real content that protocol.md doesn't document.
64
+ */
65
+ expectedLength?: number;
66
+ }
67
+ export interface ILinkClient {
68
+ /** Start a fresh QR login flow. */
69
+ requestLinkQr(): Promise<ILinkQrSession>;
70
+ /** Poll whether a QR login attempt has been completed (scanned + confirmed). */
71
+ pollLinkStatus(loginSessionId: string): Promise<ILinkLinkResult>;
72
+ /**
73
+ * Long-poll for new messages. Resolves with zero or more updates once
74
+ * either a message arrives or `timeoutSeconds` elapses (iLink's documented
75
+ * `getupdates` contract) — never rejects on a plain timeout, only on a real
76
+ * transport/auth failure.
77
+ */
78
+ getUpdates(creds: ILinkCredentials, timeoutSeconds: number): Promise<ILinkUpdate[]>;
79
+ /**
80
+ * Send a single already-chunked text message. `contextToken` is whatever
81
+ * the most recent INBOUND message from this recipient carried (undefined
82
+ * if they've never messaged first) — sending does not return a new one,
83
+ * per Tencent's documented `sendmessage` response (`{ret, errmsg}` only).
84
+ */
85
+ sendText(creds: ILinkCredentials, toId: string, text: string, contextToken?: string): Promise<void>;
86
+ /**
87
+ * Tell iLink's backend this channel client has started, before the first
88
+ * `getUpdates` call — confirmed via Tencent's own official client
89
+ * (`Tencent/openclaw-weixin`'s `src/channel.ts`, checked 2026-09-10): it
90
+ * calls this unconditionally before starting its poll loop, and
91
+ * protocol.md documents it as "notify the backend that the client
92
+ * started." This codebase never called it at all, which is the likely
93
+ * cause of `getUpdates` failing (Cloudflare 522/524) on the large
94
+ * majority of polls during live testing — never confirmed as THE fix
95
+ * (Tencent's own docs don't spell out what not calling it does), but it's
96
+ * a real gap versus the reference implementation, not a stretch. Failure
97
+ * here must never block startup — Tencent's own client only logs a
98
+ * warning and continues (see `notifyStart`'s call site in manager.ts).
99
+ */
100
+ notifyStart(creds: ILinkCredentials): Promise<void>;
101
+ /** Counterpart to notifyStart, sent on channel stop. Same non-blocking contract. */
102
+ notifyStop(creds: ILinkCredentials): Promise<void>;
103
+ }
104
+ /**
105
+ * Plugin version as `0x00MMNNPP` (major/minor/patch, one byte each) rendered
106
+ * as a decimal string, per protocol.md's `iLink-App-ClientVersion` spec.
107
+ */
108
+ export declare function encodeClientVersion(version: string): string;
109
+ /**
110
+ * Turn whatever `qrcode_img_content` actually is into a ready-to-`<img src>`
111
+ * PNG data URI. Confirmed shape (see module doc comment): a
112
+ * `liteapp.weixin.qq.com` URL that must itself be QR-encoded — it is data to
113
+ * scan, not a picture to show as-is.
114
+ */
115
+ export declare function normalizeQrImage(content: string): Promise<string>;
116
+ interface WeixinMessageItem {
117
+ type: number;
118
+ text_item?: {
119
+ text: string;
120
+ };
121
+ /**
122
+ * Present on a type=2 (image) item. `aeskey` (raw 32 hex chars) takes
123
+ * precedence over `media.aes_key` (base64 of either 16 raw bytes or a
124
+ * 32-char hex string) per protocol.md — see `resolveWeixinImageRef`.
125
+ */
126
+ image_item?: {
127
+ aeskey?: string;
128
+ media?: {
129
+ encrypt_query_param?: string;
130
+ aes_key?: string;
131
+ full_url?: string;
132
+ };
133
+ };
134
+ /**
135
+ * Present on a type=4 (file) item. Unlike `image_item`, protocol.md
136
+ * documents no top-level `aeskey` for files — the key comes from
137
+ * `media.aes_key` only. `file_name` is the attachment's real name
138
+ * (including extension), needed to stage it usefully.
139
+ */
140
+ file_item?: {
141
+ file_name?: string;
142
+ /** Plaintext byte count, as a decimal string, per protocol.md. */
143
+ len?: string;
144
+ media?: {
145
+ encrypt_query_param?: string;
146
+ aes_key?: string;
147
+ full_url?: string;
148
+ };
149
+ };
150
+ }
151
+ export declare function resolveWeixinImageRef(items: WeixinMessageItem[] | undefined): ILinkImageRef | undefined;
152
+ export interface ILinkFileRef extends ILinkImageRef {
153
+ /** Attachment's real filename (including extension), e.g. "report.pdf". */
154
+ fileName: string;
155
+ }
156
+ /** Resolve an inbound file item (type=4) — protocol.md has no top-level aeskey for files, only media.aes_key. */
157
+ export declare function resolveWeixinFileRef(items: WeixinMessageItem[] | undefined): ILinkFileRef | undefined;
158
+ /**
159
+ * AES-128-ECB decrypt with PERMISSIVE PKCS#7 unpadding: if the trailing
160
+ * padding doesn't validate, return the padded bytes as-is instead of
161
+ * throwing. Mirrors `NousResearch/hermes-agent`'s `_aes128_ecb_decrypt`
162
+ * exactly (confirmed live 2026-09-11) — Node's built-in auto-unpad
163
+ * (`setAutoPadding(true)`) throws "bad decrypt" on the same real-world edge
164
+ * cases Hermes-agent's own implementation was written to tolerate.
165
+ */
166
+ export declare function aes128EcbDecryptPermissive(ciphertext: Buffer, key: Buffer): Buffer;
167
+ export declare function downloadWeixinImage(ref: ILinkImageRef, opts?: {
168
+ timeoutMs?: number;
169
+ maxBytes?: number;
170
+ }): Promise<Buffer>;
171
+ /**
172
+ * Real implementation — talks to Tencent's iLink Bot API. See this module's
173
+ * doc comment for the two documented ambiguities (`qrcode_img_content`'s
174
+ * encoding, and the unhandled verification-code statuses) still to confirm
175
+ * against a real account.
176
+ */
177
+ export declare function createILinkClient(baseUrl?: string, botAgent?: string): ILinkClient;
178
+ /**
179
+ * Local-testing-only fake client — no network calls, no real iLink account
180
+ * needed. Simulates a QR scan completing after a few polls, then occasionally
181
+ * delivers one fake inbound message (carrying its own fake `contextToken`,
182
+ * exactly like the real protocol) so the pending-sender/access-control UI
183
+ * has something to show. Never wired up by default — see
184
+ * `isWeChatILinkFakeEnabled()` and its call site in AgentRunner.
185
+ *
186
+ * NOT a substitute for the real API contract — exists purely so the apps/web
187
+ * card's UI/UX (QR render, link→linked transition, DM allowlist, disconnect)
188
+ * can be manually verified end-to-end without a real WeChat account.
189
+ */
190
+ export declare function createFakeILinkClient(): ILinkClient;
191
+ /** Opt-in only, local dev/manual-testing use — see createFakeILinkClient's doc comment. */
192
+ export declare function isWeChatILinkFakeEnabled(): boolean;
193
+ export {};
194
+ //# sourceMappingURL=ilink-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ilink-client.d.ts","sourceRoot":"","sources":["../../src/wechat/ilink-client.ts"],"names":[],"mappings":"AAkDA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sHAAsH;IACtH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,mJAAmJ;IACnJ,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,gFAAgF;IAChF,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACjE;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACpF;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpG;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,oFAAoF;IACpF,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAQD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI3D;AAID;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQvE;AA0HD,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B;;;;OAIG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE;YACN,mBAAmB,CAAC,EAAE,MAAM,CAAC;YAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QACV,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,kEAAkE;QAClE,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE;YACN,mBAAmB,CAAC,EAAE,MAAM,CAAC;YAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;CACH;AAoHD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAIvG;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iHAAiH;AACjH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAWrG;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAWlF;AAWD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,aAAa,EAClB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,CA8KlF;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,CAwDnD;AAED,2FAA2F;AAC3F,wBAAgB,wBAAwB,IAAI,OAAO,CAElD"}