tgo-widget-miniprogram 1.0.0 → 1.1.1

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.
@@ -1,30 +1,965 @@
1
- /**
2
- * Chat state management (Observable singleton)
3
- * Ported from tgo-widget-app chatStore.ts
4
- */
5
- var IMService = require('../services/wukongim')
6
- var visitorService = require('../services/visitor')
7
- var historyService = require('../services/messageHistory')
8
- var chatService = require('../services/chat')
9
- var uploadService = require('../services/upload')
10
- var systemInfoAdapter = require('../adapters/systemInfo')
11
- var types = require('./types')
12
- var platformStore = require('./platformStore')
13
- var uidUtil = require('../utils/uid')
14
- var jsonRenderUtils = require('../utils/jsonRender')
15
-
16
- // Module-level unsub guards
17
- var offMsg = null
18
- var offStatus = null
19
- var offCustom = null
20
-
21
- // Stream timeout
22
- var streamTimer = null
23
- var STREAM_TIMEOUT_MS = 60000
24
-
25
- // Per-clientMsgNo MixedStreamParser instances
26
- var activeParsers = {}
27
-
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // node_modules/easyjssdk/dist/cjs/index.js
7
+ var require_cjs = __commonJS({
8
+ "node_modules/easyjssdk/dist/cjs/index.js"(exports2) {
9
+ "use strict";
10
+ Object.defineProperty(exports2, "__esModule", { value: true });
11
+ exports2.WKIMDeviceFlag = exports2.WKIMEvent = exports2.WKIMChannelType = exports2.WKIM = exports2.DeviceFlag = exports2.ReasonCode = exports2.Event = exports2.ChannelType = exports2.currentPlatform = exports2.PlatformType = void 0;
12
+ var WS_CONNECTING = 0;
13
+ var WS_OPEN = 1;
14
+ var WS_CLOSING = 2;
15
+ var WS_CLOSED = 3;
16
+ var PlatformType;
17
+ (function(PlatformType2) {
18
+ PlatformType2["Browser"] = "browser";
19
+ PlatformType2["NodeJS"] = "nodejs";
20
+ PlatformType2["WeChat"] = "wechat";
21
+ PlatformType2["Alipay"] = "alipay";
22
+ PlatformType2["UniApp"] = "uniapp";
23
+ })(PlatformType || (exports2.PlatformType = PlatformType = {}));
24
+ var WeChatWebSocketAdapter = class {
25
+ constructor(url) {
26
+ this.socketTask = null;
27
+ this._readyState = WS_CONNECTING;
28
+ this.onopen = null;
29
+ this.onmessage = null;
30
+ this.onerror = null;
31
+ this.onclose = null;
32
+ if (typeof wx === "undefined") {
33
+ throw new Error("WeChat Mini Program environment not detected");
34
+ }
35
+ this.socketTask = wx.connectSocket({
36
+ url,
37
+ success: () => {
38
+ console.log("WeChat WebSocket connecting...");
39
+ },
40
+ fail: (err) => {
41
+ console.error("WeChat WebSocket connection failed:", err);
42
+ this._readyState = WS_CLOSED;
43
+ if (this.onerror) {
44
+ this.onerror({ message: err.errMsg || "Connection failed" });
45
+ }
46
+ }
47
+ });
48
+ this.socketTask.onOpen((res) => {
49
+ this._readyState = WS_OPEN;
50
+ if (this.onopen) {
51
+ this.onopen(res);
52
+ }
53
+ });
54
+ this.socketTask.onMessage((res) => {
55
+ if (this.onmessage) {
56
+ const data = res.data instanceof ArrayBuffer ? new TextDecoder().decode(res.data) : res.data;
57
+ this.onmessage({ data });
58
+ }
59
+ });
60
+ this.socketTask.onError((res) => {
61
+ console.error("WeChat WebSocket error:", res);
62
+ if (this.onerror) {
63
+ this.onerror({ message: res.errMsg || "WebSocket error" });
64
+ }
65
+ });
66
+ this.socketTask.onClose((res) => {
67
+ this._readyState = WS_CLOSED;
68
+ if (this.onclose) {
69
+ this.onclose({ code: res.code || 1e3, reason: res.reason || "" });
70
+ }
71
+ });
72
+ }
73
+ get readyState() {
74
+ return this._readyState;
75
+ }
76
+ send(data) {
77
+ if (this._readyState !== WS_OPEN || !this.socketTask) {
78
+ throw new Error("WebSocket is not open");
79
+ }
80
+ this.socketTask.send({
81
+ data,
82
+ fail: (err) => {
83
+ console.error("WeChat WebSocket send failed:", err);
84
+ if (this.onerror) {
85
+ this.onerror({ message: "Send failed" });
86
+ }
87
+ }
88
+ });
89
+ }
90
+ close(code, reason) {
91
+ if (this._readyState === WS_CLOSED || this._readyState === WS_CLOSING) {
92
+ return;
93
+ }
94
+ this._readyState = WS_CLOSING;
95
+ if (this.socketTask) {
96
+ this.socketTask.close({
97
+ code: code || 1e3,
98
+ reason: reason || "",
99
+ fail: (err) => {
100
+ console.error("WeChat WebSocket close failed:", err);
101
+ }
102
+ });
103
+ }
104
+ }
105
+ };
106
+ var AlipayWebSocketAdapter = class {
107
+ constructor(url) {
108
+ this._readyState = WS_CONNECTING;
109
+ this.boundOnOpen = null;
110
+ this.boundOnMessage = null;
111
+ this.boundOnError = null;
112
+ this.boundOnClose = null;
113
+ this.onopen = null;
114
+ this.onmessage = null;
115
+ this.onerror = null;
116
+ this.onclose = null;
117
+ if (typeof my === "undefined") {
118
+ throw new Error("Alipay Mini Program environment not detected");
119
+ }
120
+ this.boundOnOpen = (res) => {
121
+ this._readyState = WS_OPEN;
122
+ if (this.onopen) {
123
+ this.onopen(res);
124
+ }
125
+ };
126
+ this.boundOnMessage = (res) => {
127
+ if (this.onmessage) {
128
+ const data = res.data instanceof ArrayBuffer ? new TextDecoder().decode(res.data) : res.data;
129
+ this.onmessage({ data });
130
+ }
131
+ };
132
+ this.boundOnError = (res) => {
133
+ console.error("Alipay WebSocket error:", res);
134
+ if (this.onerror) {
135
+ this.onerror({ message: res.errorMessage || "WebSocket error" });
136
+ }
137
+ };
138
+ this.boundOnClose = (res) => {
139
+ this._readyState = WS_CLOSED;
140
+ this.cleanup();
141
+ if (this.onclose) {
142
+ this.onclose({ code: res.code || 1e3, reason: res.reason || "" });
143
+ }
144
+ };
145
+ my.onSocketOpen(this.boundOnOpen);
146
+ my.onSocketMessage(this.boundOnMessage);
147
+ my.onSocketError(this.boundOnError);
148
+ my.onSocketClose(this.boundOnClose);
149
+ my.connectSocket({
150
+ url,
151
+ success: () => {
152
+ console.log("Alipay WebSocket connecting...");
153
+ },
154
+ fail: (err) => {
155
+ console.error("Alipay WebSocket connection failed:", err);
156
+ this._readyState = WS_CLOSED;
157
+ this.cleanup();
158
+ if (this.onerror) {
159
+ this.onerror({ message: err.errorMessage || "Connection failed" });
160
+ }
161
+ }
162
+ });
163
+ }
164
+ get readyState() {
165
+ return this._readyState;
166
+ }
167
+ send(data) {
168
+ if (typeof my === "undefined") {
169
+ throw new Error("Alipay Mini Program environment not detected");
170
+ }
171
+ if (this._readyState !== WS_OPEN) {
172
+ throw new Error("WebSocket is not open");
173
+ }
174
+ my.sendSocketMessage({
175
+ data,
176
+ fail: (err) => {
177
+ console.error("Alipay WebSocket send failed:", err);
178
+ if (this.onerror) {
179
+ this.onerror({ message: "Send failed" });
180
+ }
181
+ }
182
+ });
183
+ }
184
+ close(code, reason) {
185
+ if (typeof my === "undefined") {
186
+ return;
187
+ }
188
+ if (this._readyState === WS_CLOSED || this._readyState === WS_CLOSING) {
189
+ return;
190
+ }
191
+ this._readyState = WS_CLOSING;
192
+ my.closeSocket({
193
+ code: code || 1e3,
194
+ reason: reason || "",
195
+ fail: (err) => {
196
+ console.error("Alipay WebSocket close failed:", err);
197
+ }
198
+ });
199
+ }
200
+ cleanup() {
201
+ if (typeof my !== "undefined") {
202
+ my.offSocketOpen(this.boundOnOpen);
203
+ my.offSocketMessage(this.boundOnMessage);
204
+ my.offSocketError(this.boundOnError);
205
+ my.offSocketClose(this.boundOnClose);
206
+ this.boundOnOpen = null;
207
+ this.boundOnMessage = null;
208
+ this.boundOnError = null;
209
+ this.boundOnClose = null;
210
+ }
211
+ }
212
+ };
213
+ var UniAppWebSocketAdapter = class {
214
+ constructor(url) {
215
+ this.socketTask = null;
216
+ this._readyState = WS_CONNECTING;
217
+ this.onopen = null;
218
+ this.onmessage = null;
219
+ this.onerror = null;
220
+ this.onclose = null;
221
+ if (typeof uni === "undefined") {
222
+ throw new Error("UniApp environment not detected");
223
+ }
224
+ this.socketTask = uni.connectSocket({
225
+ url,
226
+ success: () => {
227
+ console.log("UniApp WebSocket connecting...");
228
+ },
229
+ fail: (err) => {
230
+ console.error("UniApp WebSocket connection failed:", err);
231
+ this._readyState = WS_CLOSED;
232
+ if (this.onerror) {
233
+ this.onerror({ message: err.errMsg || "Connection failed" });
234
+ }
235
+ }
236
+ });
237
+ this.socketTask.onOpen((res) => {
238
+ this._readyState = WS_OPEN;
239
+ if (this.onopen) {
240
+ this.onopen(res);
241
+ }
242
+ });
243
+ this.socketTask.onMessage((res) => {
244
+ if (this.onmessage) {
245
+ const data = res.data instanceof ArrayBuffer ? new TextDecoder().decode(res.data) : res.data;
246
+ this.onmessage({ data });
247
+ }
248
+ });
249
+ this.socketTask.onError((res) => {
250
+ console.error("UniApp WebSocket error:", res);
251
+ if (this.onerror) {
252
+ this.onerror({ message: res.errMsg || "WebSocket error" });
253
+ }
254
+ });
255
+ this.socketTask.onClose((res) => {
256
+ this._readyState = WS_CLOSED;
257
+ if (this.onclose) {
258
+ this.onclose({ code: res.code || 1e3, reason: res.reason || "" });
259
+ }
260
+ });
261
+ }
262
+ get readyState() {
263
+ return this._readyState;
264
+ }
265
+ send(data) {
266
+ if (this._readyState !== WS_OPEN || !this.socketTask) {
267
+ throw new Error("WebSocket is not open");
268
+ }
269
+ this.socketTask.send({
270
+ data,
271
+ fail: (err) => {
272
+ console.error("UniApp WebSocket send failed:", err);
273
+ if (this.onerror) {
274
+ this.onerror({ message: "Send failed" });
275
+ }
276
+ }
277
+ });
278
+ }
279
+ close(code, reason) {
280
+ if (this._readyState === WS_CLOSED || this._readyState === WS_CLOSING) {
281
+ return;
282
+ }
283
+ this._readyState = WS_CLOSING;
284
+ if (this.socketTask) {
285
+ this.socketTask.close({
286
+ code: code || 1e3,
287
+ reason: reason || "",
288
+ fail: (err) => {
289
+ console.error("UniApp WebSocket close failed:", err);
290
+ }
291
+ });
292
+ }
293
+ }
294
+ };
295
+ function detectPlatform() {
296
+ if (typeof uni !== "undefined" && typeof uni.connectSocket === "function") {
297
+ return PlatformType.UniApp;
298
+ }
299
+ if (typeof wx !== "undefined" && typeof wx.connectSocket === "function") {
300
+ return PlatformType.WeChat;
301
+ }
302
+ if (typeof my !== "undefined" && typeof my.connectSocket === "function") {
303
+ return PlatformType.Alipay;
304
+ }
305
+ if (typeof WebSocket !== "undefined") {
306
+ return PlatformType.Browser;
307
+ }
308
+ return PlatformType.NodeJS;
309
+ }
310
+ var currentPlatform = detectPlatform();
311
+ exports2.currentPlatform = currentPlatform;
312
+ function createWebSocket(url) {
313
+ switch (currentPlatform) {
314
+ case PlatformType.UniApp:
315
+ return new UniAppWebSocketAdapter(url);
316
+ case PlatformType.WeChat:
317
+ return new WeChatWebSocketAdapter(url);
318
+ case PlatformType.Alipay:
319
+ return new AlipayWebSocketAdapter(url);
320
+ case PlatformType.Browser:
321
+ return new WebSocket(url);
322
+ case PlatformType.NodeJS:
323
+ default:
324
+ try {
325
+ const dynamicRequire = new Function("mod", "return require(mod)");
326
+ const Ws = dynamicRequire("ws");
327
+ const WsImpl = Ws.WebSocket || Ws;
328
+ return new WsImpl(url);
329
+ } catch (e) {
330
+ throw new Error("WebSocket is not available in this environment. Install 'ws' package for Node.js.");
331
+ }
332
+ }
333
+ }
334
+ var ChannelType;
335
+ (function(ChannelType2) {
336
+ ChannelType2[ChannelType2["Person"] = 1] = "Person";
337
+ ChannelType2[ChannelType2["Group"] = 2] = "Group";
338
+ ChannelType2[ChannelType2["CustomerService"] = 3] = "CustomerService";
339
+ ChannelType2[ChannelType2["Community"] = 4] = "Community";
340
+ ChannelType2[ChannelType2["CommunityTopic"] = 5] = "CommunityTopic";
341
+ ChannelType2[ChannelType2["Info"] = 6] = "Info";
342
+ ChannelType2[ChannelType2["Data"] = 7] = "Data";
343
+ ChannelType2[ChannelType2["Temp"] = 8] = "Temp";
344
+ ChannelType2[ChannelType2["Live"] = 9] = "Live";
345
+ ChannelType2[ChannelType2["Visitors"] = 10] = "Visitors";
346
+ })(ChannelType || (exports2.WKIMChannelType = exports2.ChannelType = ChannelType = {}));
347
+ var Event;
348
+ (function(Event2) {
349
+ Event2["Connect"] = "connect";
350
+ Event2["Disconnect"] = "disconnect";
351
+ Event2["Message"] = "message";
352
+ Event2["Error"] = "error";
353
+ Event2["SendAck"] = "sendack";
354
+ Event2["Reconnecting"] = "reconnecting";
355
+ Event2["CustomEvent"] = "customevent";
356
+ })(Event || (exports2.WKIMEvent = exports2.Event = Event = {}));
357
+ var ReasonCode;
358
+ (function(ReasonCode2) {
359
+ ReasonCode2[ReasonCode2["Unknown"] = 0] = "Unknown";
360
+ ReasonCode2[ReasonCode2["Success"] = 1] = "Success";
361
+ ReasonCode2[ReasonCode2["AuthFail"] = 2] = "AuthFail";
362
+ ReasonCode2[ReasonCode2["SubscriberNotExist"] = 3] = "SubscriberNotExist";
363
+ ReasonCode2[ReasonCode2["InBlacklist"] = 4] = "InBlacklist";
364
+ ReasonCode2[ReasonCode2["ChannelNotExist"] = 5] = "ChannelNotExist";
365
+ ReasonCode2[ReasonCode2["UserNotOnNode"] = 6] = "UserNotOnNode";
366
+ ReasonCode2[ReasonCode2["SenderOffline"] = 7] = "SenderOffline";
367
+ ReasonCode2[ReasonCode2["MsgKeyError"] = 8] = "MsgKeyError";
368
+ ReasonCode2[ReasonCode2["PayloadDecodeError"] = 9] = "PayloadDecodeError";
369
+ ReasonCode2[ReasonCode2["ForwardSendPacketError"] = 10] = "ForwardSendPacketError";
370
+ ReasonCode2[ReasonCode2["NotAllowSend"] = 11] = "NotAllowSend";
371
+ ReasonCode2[ReasonCode2["ConnectKick"] = 12] = "ConnectKick";
372
+ ReasonCode2[ReasonCode2["NotInWhitelist"] = 13] = "NotInWhitelist";
373
+ ReasonCode2[ReasonCode2["QueryTokenError"] = 14] = "QueryTokenError";
374
+ ReasonCode2[ReasonCode2["SystemError"] = 15] = "SystemError";
375
+ ReasonCode2[ReasonCode2["ChannelIDError"] = 16] = "ChannelIDError";
376
+ ReasonCode2[ReasonCode2["NodeMatchError"] = 17] = "NodeMatchError";
377
+ ReasonCode2[ReasonCode2["NodeNotMatch"] = 18] = "NodeNotMatch";
378
+ ReasonCode2[ReasonCode2["Ban"] = 19] = "Ban";
379
+ ReasonCode2[ReasonCode2["NotSupportHeader"] = 20] = "NotSupportHeader";
380
+ ReasonCode2[ReasonCode2["ClientKeyIsEmpty"] = 21] = "ClientKeyIsEmpty";
381
+ ReasonCode2[ReasonCode2["RateLimit"] = 22] = "RateLimit";
382
+ ReasonCode2[ReasonCode2["NotSupportChannelType"] = 23] = "NotSupportChannelType";
383
+ ReasonCode2[ReasonCode2["Disband"] = 24] = "Disband";
384
+ ReasonCode2[ReasonCode2["SendBan"] = 25] = "SendBan";
385
+ })(ReasonCode || (exports2.ReasonCode = ReasonCode = {}));
386
+ var DeviceFlag;
387
+ (function(DeviceFlag2) {
388
+ DeviceFlag2[DeviceFlag2["App"] = 0] = "App";
389
+ DeviceFlag2[DeviceFlag2["Web"] = 1] = "Web";
390
+ DeviceFlag2[DeviceFlag2["Desktop"] = 2] = "Desktop";
391
+ })(DeviceFlag || (exports2.WKIMDeviceFlag = exports2.DeviceFlag = DeviceFlag = {}));
392
+ var WKIM = class _WKIM {
393
+ constructor(url, auth) {
394
+ this.ws = null;
395
+ this.isConnected = false;
396
+ this.connectionPromise = null;
397
+ this.pingInterval = null;
398
+ this.pingTimeout = null;
399
+ this.PING_INTERVAL_MS = 25 * 1e3;
400
+ this.PONG_TIMEOUT_MS = 10 * 1e3;
401
+ this.pendingRequests = /* @__PURE__ */ new Map();
402
+ this.eventListeners = /* @__PURE__ */ new Map();
403
+ this.reconnectAttempts = 0;
404
+ this.maxReconnectAttempts = 5;
405
+ this.initialReconnectDelay = 1e3;
406
+ this.isReconnecting = false;
407
+ this.manualDisconnect = false;
408
+ this.beforeUnloadHandler = null;
409
+ this.url = url;
410
+ this.auth = auth || {};
411
+ this.sessionId = this.generateUUID();
412
+ if (!this.auth.deviceId || this.auth.deviceId === "") {
413
+ this.auth.deviceId = `web_${this.sessionId.slice(0, 8)}_${Date.now()}`;
414
+ }
415
+ Object.values(Event).forEach((event) => this.eventListeners.set(event, []));
416
+ this.setupBeforeUnloadHandler();
417
+ }
418
+ /**
419
+ * Initializes the WKIM instance.
420
+ * @param url WebSocket server URL (e.g., "ws://localhost:5100")
421
+ * @param auth Authentication options { uid, token, ... }
422
+ * @param options Configuration options { singleton: boolean }
423
+ * @returns A WKIM instance
424
+ */
425
+ static init(url, auth, options = {}) {
426
+ if (!url || !auth || !auth.uid || !auth.token) {
427
+ throw new Error("URL, uid, and token are required for initialization.");
428
+ }
429
+ if (options.singleton && _WKIM.globalInstance) {
430
+ console.log("Destroying previous global instance...");
431
+ _WKIM.globalInstance.destroy();
432
+ }
433
+ const instance = new _WKIM(url, auth);
434
+ if (options.singleton !== false) {
435
+ _WKIM.globalInstance = instance;
436
+ }
437
+ return instance;
438
+ }
439
+ /**
440
+ * Establishes connection and authenticates with the server.
441
+ * Returns a Promise that resolves on successful connection/authentication,
442
+ * or rejects on failure.
443
+ */
444
+ connect() {
445
+ return new Promise((resolve, reject) => {
446
+ var _a;
447
+ if (this.isConnected || ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WS_CONNECTING) {
448
+ console.warn("Connection already established or in progress.");
449
+ if (this.isConnected) {
450
+ resolve();
451
+ } else if (this.connectionPromise) {
452
+ this.connectionPromise.resolve = resolve;
453
+ this.connectionPromise.reject = reject;
454
+ } else {
455
+ reject(new Error("Already connecting, but no connection promise found."));
456
+ }
457
+ return;
458
+ }
459
+ this.manualDisconnect = false;
460
+ this.connectionPromise = { resolve, reject };
461
+ try {
462
+ console.log(`Connecting to ${this.url}... (Platform: ${currentPlatform})`);
463
+ this.ws = createWebSocket(this.url);
464
+ this.ws.onopen = () => {
465
+ console.log("WebSocket connection opened. Authenticating...");
466
+ this.sendConnectRequest();
467
+ };
468
+ this.ws.onmessage = (event) => {
469
+ this.handleMessage(event.data);
470
+ };
471
+ this.ws.onerror = (event) => {
472
+ const errorMessage = event.message || (event.error ? event.error.message : "WebSocket error");
473
+ console.error("WebSocket error:", errorMessage, event);
474
+ this.emit(Event.Error, event.error || new Error(errorMessage));
475
+ };
476
+ this.ws.onclose = (event) => {
477
+ const wasConnected = this.isConnected;
478
+ console.log(`WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason}`);
479
+ if (this.connectionPromise && !this.isConnected) {
480
+ this.connectionPromise.reject(new Error(`Connection closed before authentication (Code: ${event.code})`));
481
+ }
482
+ this.cleanupConnection();
483
+ this.emit(Event.Disconnect, { code: event.code, reason: event.reason });
484
+ if (wasConnected && !this.manualDisconnect) {
485
+ this.tryReconnect();
486
+ }
487
+ };
488
+ } catch (error) {
489
+ console.error("Failed to create WebSocket:", error);
490
+ this.emit(Event.Error, error);
491
+ if (this.connectionPromise) {
492
+ this.connectionPromise.reject(error);
493
+ this.connectionPromise = null;
494
+ }
495
+ this.cleanupConnection();
496
+ }
497
+ });
498
+ }
499
+ /**
500
+ * Disconnects from the server.
501
+ */
502
+ disconnect() {
503
+ console.log("Manual disconnect initiated.");
504
+ this.manualDisconnect = true;
505
+ this.isReconnecting = false;
506
+ this.cleanupBeforeUnloadHandler();
507
+ this.handleDisconnect(true, "Manual disconnection");
508
+ }
509
+ /**
510
+ * Completely destroys the SDK instance, cleaning up all resources.
511
+ * Call this when you no longer need the SDK instance.
512
+ */
513
+ destroy() {
514
+ console.log("Destroying SDK instance...");
515
+ this.disconnect();
516
+ this.eventListeners.clear();
517
+ this.pendingRequests.clear();
518
+ if (_WKIM.globalInstance === this) {
519
+ _WKIM.globalInstance = null;
520
+ }
521
+ }
522
+ /**
523
+ * Sends a message to a specific channel.
524
+ * @param channelId Target channel ID
525
+ * @param channelType Target channel type (e.g., WKIM.ChannelType.Person)
526
+ * @param payload Message payload (must be a JSON-serializable object)
527
+ * @param options Optional: { clientMsgNo, header, setting, msgKey, expire, topic }
528
+ * @returns Promise resolving with { messageId, messageSeq } on server ack, or rejecting on error.
529
+ */
530
+ send(channelId, channelType, payload, options = {}) {
531
+ if (!this.isConnected || !this.ws || this.ws.readyState !== WS_OPEN) {
532
+ return Promise.reject(new Error("Not connected. Call connect() first."));
533
+ }
534
+ if (typeof payload !== "object" || payload === null) {
535
+ return Promise.reject(new Error("Payload must be a non-null object."));
536
+ }
537
+ const header = options.header || {};
538
+ header.redDot = true;
539
+ const clientMsgNo = options.clientMsgNo || this.generateUUID();
540
+ const params = {
541
+ clientMsgNo,
542
+ channelId,
543
+ channelType,
544
+ payload: this._encodePayloadToBase64(payload),
545
+ header,
546
+ topic: options.topic,
547
+ setting: options.setting
548
+ };
549
+ return this.sendRequest("send", params);
550
+ }
551
+ /**
552
+ * Registers an event listener.
553
+ * @param eventName The event to listen for (e.g., WKIM.Event.Message)
554
+ * @param callback The function to call when the event occurs
555
+ */
556
+ on(eventName, callback) {
557
+ var _a;
558
+ if (this.eventListeners.has(eventName)) {
559
+ (_a = this.eventListeners.get(eventName)) === null || _a === void 0 ? void 0 : _a.push(callback);
560
+ } else {
561
+ console.warn(`Attempted to register listener for unknown event: ${eventName}`);
562
+ }
563
+ }
564
+ /**
565
+ * Removes an event listener.
566
+ * @param eventName The event to stop listening for
567
+ * @param callback The specific callback function to remove
568
+ */
569
+ off(eventName, callback) {
570
+ if (this.eventListeners.has(eventName)) {
571
+ const listeners = this.eventListeners.get(eventName);
572
+ if (listeners) {
573
+ const index = listeners.indexOf(callback);
574
+ if (index > -1) {
575
+ listeners.splice(index, 1);
576
+ }
577
+ }
578
+ }
579
+ }
580
+ // --- Private Methods ---
581
+ emit(eventName, ...args) {
582
+ const listeners = this.eventListeners.get(eventName);
583
+ if (listeners) {
584
+ listeners.forEach((callback) => {
585
+ try {
586
+ callback(...args);
587
+ } catch (error) {
588
+ console.error(`Error in event listener for ${eventName}:`, error);
589
+ }
590
+ });
591
+ }
592
+ }
593
+ generateUUID() {
594
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
595
+ const r = Math.random() * 16 | 0, v = c === "x" ? r : r & 3 | 8;
596
+ return v.toString(16);
597
+ });
598
+ }
599
+ sendConnectRequest() {
600
+ var _a;
601
+ const params = {
602
+ uid: this.auth.uid,
603
+ token: this.auth.token,
604
+ deviceId: this.auth.deviceId,
605
+ deviceFlag: (_a = this.auth.deviceFlag) !== null && _a !== void 0 ? _a : DeviceFlag.Web,
606
+ // Default to WEB
607
+ clientTimestamp: Date.now()
608
+ // Add version, clientKey if needed
609
+ };
610
+ this.sendRequest("connect", params, 5e3).then((result) => {
611
+ console.log("Authentication successful:", result);
612
+ this.isConnected = true;
613
+ this.reconnectAttempts = 0;
614
+ this.isReconnecting = false;
615
+ this.manualDisconnect = false;
616
+ this.startPing();
617
+ this.emit(Event.Connect, result);
618
+ if (this.connectionPromise) {
619
+ this.connectionPromise.resolve();
620
+ this.connectionPromise = null;
621
+ }
622
+ }).catch((error) => {
623
+ console.error("Authentication failed:", error);
624
+ this.emit(Event.Error, new Error(`Authentication failed: ${error.message || JSON.stringify(error)}`));
625
+ if (this.connectionPromise) {
626
+ this.connectionPromise.reject(error);
627
+ this.connectionPromise = null;
628
+ }
629
+ this.handleDisconnect(false, "Authentication failed");
630
+ this.cleanupConnection();
631
+ });
632
+ }
633
+ sendRequest(method, params, timeoutMs = 15e3) {
634
+ return new Promise((resolve, reject) => {
635
+ if (!this.ws || this.ws.readyState !== WS_OPEN) {
636
+ return reject(new Error("WebSocket is not open."));
637
+ }
638
+ const requestId = this.generateUUID();
639
+ const request = {
640
+ method,
641
+ params,
642
+ id: requestId
643
+ };
644
+ const timeoutTimer = setTimeout(() => {
645
+ this.pendingRequests.delete(requestId);
646
+ reject(new Error(`Request timeout for method ${method} (id: ${requestId})`));
647
+ }, timeoutMs);
648
+ this.pendingRequests.set(requestId, { resolve, reject, timeoutTimer });
649
+ try {
650
+ console.debug(`--> Sending request (id: ${requestId}):`, JSON.stringify(request));
651
+ this.ws.send(JSON.stringify(request));
652
+ } catch (error) {
653
+ clearTimeout(timeoutTimer);
654
+ this.pendingRequests.delete(requestId);
655
+ console.error(`Error sending request (id: ${requestId}):`, error);
656
+ reject(error);
657
+ }
658
+ });
659
+ }
660
+ sendNotification(method, params) {
661
+ if (!this.ws || this.ws.readyState !== WS_OPEN) {
662
+ console.error("Cannot send notification, WebSocket is not open.");
663
+ return;
664
+ }
665
+ const notification = {
666
+ method,
667
+ params
668
+ };
669
+ console.debug(`--> Sending notification:`, JSON.stringify(notification));
670
+ try {
671
+ this.ws.send(JSON.stringify(notification));
672
+ } catch (error) {
673
+ console.error(`Error sending notification (${method}):`, error);
674
+ this.emit(Event.Error, new Error(`Failed to send notification ${method}: ${error}`));
675
+ }
676
+ }
677
+ handleMessage(data) {
678
+ console.debug("<-- Received raw:", data);
679
+ let message;
680
+ try {
681
+ message = JSON.parse(data.toString());
682
+ } catch (error) {
683
+ console.error("Failed to parse incoming message:", error, data);
684
+ this.emit(Event.Error, new Error(`Failed to parse message: ${error}`));
685
+ return;
686
+ }
687
+ if ("id" in message) {
688
+ this.handleResponse(message);
689
+ } else if ("method" in message) {
690
+ this.handleNotification(message);
691
+ } else {
692
+ console.warn("Received unknown message format:", message);
693
+ }
694
+ }
695
+ handleResponse(response) {
696
+ console.debug(`<-- Handling response (id: ${response.id}):`, response);
697
+ const pending = this.pendingRequests.get(response.id);
698
+ if (pending) {
699
+ clearTimeout(pending.timeoutTimer);
700
+ this.pendingRequests.delete(response.id);
701
+ if (response.error) {
702
+ pending.reject(response.error);
703
+ } else {
704
+ pending.resolve(response.result);
705
+ }
706
+ } else {
707
+ console.warn(`Received response for unknown request ID: ${response.id}`);
708
+ }
709
+ }
710
+ handleNotification(notification) {
711
+ var _a, _b;
712
+ console.debug(`<-- Handling notification (${notification.method}):`, notification.params);
713
+ switch (notification.method) {
714
+ case "recv":
715
+ const messageData = notification.params;
716
+ if (typeof messageData.payload === "string") {
717
+ try {
718
+ messageData.payload = JSON.parse(this._decodeBase64ToStr(messageData.payload));
719
+ } catch (e) {
720
+ }
721
+ }
722
+ this.emit(Event.Message, messageData);
723
+ this.sendRecvAck(messageData.header, messageData.messageId, messageData.messageSeq);
724
+ break;
725
+ case "pong":
726
+ this.handlePong();
727
+ break;
728
+ case "disconnect":
729
+ console.warn("Server initiated disconnect:", notification.params);
730
+ this.emit(Event.Disconnect, notification.params);
731
+ this.handleDisconnect(false, `Server disconnected: ${((_a = notification.params) === null || _a === void 0 ? void 0 : _a.reason) || ((_b = notification.params) === null || _b === void 0 ? void 0 : _b.reasonCode)}`);
732
+ break;
733
+ case "event":
734
+ this.handleEventNotification(notification.params);
735
+ break;
736
+ // Handle other notifications if needed
737
+ default:
738
+ console.warn(`Received unhandled notification method: ${notification.method}`);
739
+ }
740
+ }
741
+ /**
742
+ * Encode payload object to base64 string.
743
+ * WuKongIM server expects payload as []byte (base64 in JSON).
744
+ */
745
+ _encodePayloadToBase64(payload) {
746
+ const json = JSON.stringify(payload);
747
+ if (typeof TextEncoder !== "undefined" && typeof btoa !== "undefined") {
748
+ const bytes = new TextEncoder().encode(json);
749
+ let binary = "";
750
+ for (let i = 0; i < bytes.length; i++) {
751
+ binary += String.fromCharCode(bytes[i]);
752
+ }
753
+ return btoa(binary);
754
+ }
755
+ if (typeof Buffer !== "undefined") {
756
+ return Buffer.from(json, "utf-8").toString("base64");
757
+ }
758
+ if (typeof wx !== "undefined" && (wx === null || wx === void 0 ? void 0 : wx.arrayBufferToBase64)) {
759
+ const encoder = new TextEncoder();
760
+ const bytes = encoder.encode(json);
761
+ return wx.arrayBufferToBase64(bytes.buffer);
762
+ }
763
+ throw new Error("No base64 encoding method available");
764
+ }
765
+ /**
766
+ * Decode base64 string to UTF-8 string.
767
+ */
768
+ _decodeBase64ToStr(base64Str) {
769
+ if (typeof atob !== "undefined" && typeof TextDecoder !== "undefined") {
770
+ const binary = atob(base64Str);
771
+ const bytes = new Uint8Array(binary.length);
772
+ for (let i = 0; i < binary.length; i++) {
773
+ bytes[i] = binary.charCodeAt(i);
774
+ }
775
+ return new TextDecoder().decode(bytes);
776
+ }
777
+ if (typeof Buffer !== "undefined") {
778
+ return Buffer.from(base64Str, "base64").toString("utf-8");
779
+ }
780
+ if (typeof wx !== "undefined" && (wx === null || wx === void 0 ? void 0 : wx.base64ToArrayBuffer)) {
781
+ const buf = wx.base64ToArrayBuffer(base64Str);
782
+ return new TextDecoder().decode(new Uint8Array(buf));
783
+ }
784
+ throw new Error("No base64 decoding method available");
785
+ }
786
+ sendRecvAck(header, messageId, messageSeq) {
787
+ const params = { header, messageId, messageSeq };
788
+ this.sendNotification("recvack", params);
789
+ }
790
+ /**
791
+ * Handles incoming event notifications from the server
792
+ * @param params Event notification parameters
793
+ */
794
+ handleEventNotification(params) {
795
+ try {
796
+ const eventData = {
797
+ header: params.header,
798
+ id: params.id,
799
+ type: params.type,
800
+ timestamp: params.timestamp,
801
+ data: params.data
802
+ };
803
+ if (!eventData.id || !eventData.type) {
804
+ console.error("Invalid event notification: missing required fields", params);
805
+ this.emit(Event.Error, new Error("Invalid event notification: missing required fields"));
806
+ return;
807
+ }
808
+ if (typeof eventData.data === "string") {
809
+ try {
810
+ eventData.data = JSON.parse(eventData.data);
811
+ } catch (e) {
812
+ console.debug("Event data is not JSON, keeping as string");
813
+ }
814
+ }
815
+ console.log(`Event notification received: type=${eventData.type}, id=${eventData.id}`);
816
+ this.emit(Event.CustomEvent, eventData);
817
+ } catch (error) {
818
+ console.error("Error handling event notification:", error);
819
+ this.emit(Event.Error, new Error(`Failed to handle event notification: ${error}`));
820
+ }
821
+ }
822
+ startPing() {
823
+ this.stopPing();
824
+ this.pingInterval = setInterval(() => {
825
+ if (this.ws && this.ws.readyState === WS_OPEN) {
826
+ this.sendRequest("ping", {}, this.PONG_TIMEOUT_MS).then(this.handlePong.bind(this)).catch((err) => {
827
+ console.error("Ping failed or timed out:", err);
828
+ this.emit(Event.Error, new Error(`Ping timeout: ${(err === null || err === void 0 ? void 0 : err.message) || err}`));
829
+ if (!this.manualDisconnect) {
830
+ this.handleDisconnect(false, "Ping timeout");
831
+ this.tryReconnect();
832
+ }
833
+ });
834
+ } else {
835
+ this.stopPing();
836
+ }
837
+ }, this.PING_INTERVAL_MS);
838
+ console.log(`Ping interval started (${this.PING_INTERVAL_MS}ms).`);
839
+ }
840
+ stopPing() {
841
+ if (this.pingInterval) {
842
+ clearInterval(this.pingInterval);
843
+ this.pingInterval = null;
844
+ console.log("Ping interval stopped.");
845
+ }
846
+ if (this.pingTimeout) {
847
+ clearTimeout(this.pingTimeout);
848
+ this.pingTimeout = null;
849
+ }
850
+ }
851
+ handlePong() {
852
+ }
853
+ handleDisconnect(graceful, reason) {
854
+ console.log(`Handling disconnect. Graceful: ${graceful}, Reason: ${reason}`);
855
+ if (this.ws) {
856
+ this.stopPing();
857
+ if (graceful && this.ws.readyState === WS_OPEN) {
858
+ this.ws.close(1e3, "Client disconnected");
859
+ } else if (this.ws.readyState === WS_CONNECTING || this.ws.readyState === WS_OPEN) {
860
+ this.ws.close(3001, reason.substring(0, 123));
861
+ }
862
+ }
863
+ this.cleanupConnection();
864
+ }
865
+ cleanupConnection() {
866
+ console.log("Cleaning up connection resources.");
867
+ this.isConnected = false;
868
+ this.stopPing();
869
+ this.pendingRequests.forEach((pending) => {
870
+ clearTimeout(pending.timeoutTimer);
871
+ pending.reject(new Error("Connection closed"));
872
+ });
873
+ this.pendingRequests.clear();
874
+ if (this.connectionPromise) {
875
+ if (!this.isReconnecting && !this.isConnected) {
876
+ this.connectionPromise.reject(new Error("Connection closed during operation"));
877
+ }
878
+ this.connectionPromise = null;
879
+ }
880
+ if (this.ws) {
881
+ this.ws.onopen = null;
882
+ this.ws.onmessage = null;
883
+ this.ws.onerror = null;
884
+ this.ws.onclose = null;
885
+ }
886
+ }
887
+ // --- Reconnection Methods ---
888
+ setupBeforeUnloadHandler() {
889
+ if (typeof window !== "undefined") {
890
+ this.beforeUnloadHandler = () => {
891
+ console.log("Page unloading, closing WebSocket connection...");
892
+ this.manualDisconnect = true;
893
+ this.isReconnecting = false;
894
+ if (this.ws && this.ws.readyState === WS_OPEN) {
895
+ this.ws.close(1e3, "Page unloaded");
896
+ }
897
+ };
898
+ window.addEventListener("beforeunload", this.beforeUnloadHandler);
899
+ window.addEventListener("pagehide", this.beforeUnloadHandler);
900
+ }
901
+ }
902
+ cleanupBeforeUnloadHandler() {
903
+ if (typeof window !== "undefined" && this.beforeUnloadHandler) {
904
+ window.removeEventListener("beforeunload", this.beforeUnloadHandler);
905
+ window.removeEventListener("pagehide", this.beforeUnloadHandler);
906
+ this.beforeUnloadHandler = null;
907
+ }
908
+ }
909
+ tryReconnect() {
910
+ if (this.isReconnecting || this.manualDisconnect) {
911
+ return;
912
+ }
913
+ this.isReconnecting = true;
914
+ this.scheduleReconnect();
915
+ }
916
+ scheduleReconnect() {
917
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
918
+ console.error("Max reconnect attempts reached. Giving up.");
919
+ this.isReconnecting = false;
920
+ this.reconnectAttempts = 0;
921
+ this.emit(Event.Error, new Error("Reconnection failed."));
922
+ return;
923
+ }
924
+ const delay = this.initialReconnectDelay * Math.pow(2, this.reconnectAttempts);
925
+ this.reconnectAttempts++;
926
+ console.log(`Will attempt to reconnect in ${delay / 1e3}s (Attempt ${this.reconnectAttempts}).`);
927
+ this.emit(Event.Reconnecting, { attempt: this.reconnectAttempts, delay });
928
+ setTimeout(() => {
929
+ if (!this.isReconnecting) {
930
+ console.log("Reconnection aborted.");
931
+ return;
932
+ }
933
+ this.connect().catch(() => {
934
+ if (this.isReconnecting) {
935
+ this.scheduleReconnect();
936
+ }
937
+ });
938
+ }, delay);
939
+ }
940
+ };
941
+ exports2.WKIM = WKIM;
942
+ WKIM.globalInstance = null;
943
+ }
944
+ });
945
+
946
+ // miniprogram_dist/core/chatStore.js
947
+ var IMService = require("../services/wukongim");
948
+ var visitorService = require("../services/visitor");
949
+ var historyService = require("../services/messageHistory");
950
+ var chatService = require("../services/chat");
951
+ var uploadService = require("../services/upload");
952
+ var systemInfoAdapter = require("../adapters/systemInfo");
953
+ var types = require("./types");
954
+ var platformStore = require("./platformStore");
955
+ var uidUtil = require("../utils/uid");
956
+ var jsonRenderUtils = require("../utils/jsonRender");
957
+ var offMsg = null;
958
+ var offStatus = null;
959
+ var offCustom = null;
960
+ var streamTimer = null;
961
+ var STREAM_TIMEOUT_MS = 6e4;
962
+ var activeParsers = {};
28
963
  function ChatStore() {
29
964
  this._state = {
30
965
  messages: [],
@@ -37,329 +972,314 @@ function ChatStore() {
37
972
  historyError: null,
38
973
  earliestSeq: null,
39
974
  // identity
40
- apiBase: '',
41
- platformApiKey: '',
42
- myUid: '',
43
- channelId: '',
975
+ apiBase: "",
976
+ platformApiKey: "",
977
+ myUid: "",
978
+ channelId: "",
44
979
  channelType: 251,
45
980
  // streaming
46
981
  isStreaming: false,
47
982
  streamCanceling: false,
48
- streamingClientMsgNo: ''
49
- }
50
- this._listeners = []
51
- this._throttleTimer = null
52
- this._pendingState = null
53
- }
54
-
55
- ChatStore.prototype.getState = function () {
56
- return this._state
57
- }
58
-
59
- ChatStore.prototype._setState = function (partial) {
60
- Object.assign(this._state, partial)
61
- var state = this._state
62
- this._listeners.forEach(function (fn) { try { fn(state) } catch (e) {} })
983
+ streamingClientMsgNo: ""
984
+ };
985
+ this._listeners = [];
986
+ this._throttleTimer = null;
987
+ this._pendingState = null;
63
988
  }
64
-
65
- /**
66
- * Throttled setState for streaming updates (50ms batch).
67
- * Mutates this._state immediately (so subsequent reads see latest data),
68
- * but defers listener notification to avoid excessive setData calls.
69
- */
70
- ChatStore.prototype._setStateThrottled = function (partial) {
71
- var self = this
72
- // Apply state mutation immediately so next read sees latest data
73
- Object.assign(this._state, partial)
74
- // Throttle listener notification
989
+ ChatStore.prototype.getState = function() {
990
+ return this._state;
991
+ };
992
+ ChatStore.prototype._setState = function(partial) {
993
+ Object.assign(this._state, partial);
994
+ var state = this._state;
995
+ this._listeners.forEach(function(fn) {
996
+ try {
997
+ fn(state);
998
+ } catch (e) {
999
+ }
1000
+ });
1001
+ };
1002
+ ChatStore.prototype._setStateThrottled = function(partial) {
1003
+ var self = this;
1004
+ Object.assign(this._state, partial);
75
1005
  if (!this._throttleTimer) {
76
- this._throttleTimer = setTimeout(function () {
77
- self._throttleTimer = null
78
- var state = self._state
79
- self._listeners.forEach(function (fn) { try { fn(state) } catch (e) {} })
80
- }, 50)
81
- }
82
- }
83
-
84
- ChatStore.prototype.subscribe = function (fn) {
85
- this._listeners.push(fn)
86
- var self = this
87
- return function () {
88
- var idx = self._listeners.indexOf(fn)
89
- if (idx >= 0) self._listeners.splice(idx, 1)
1006
+ this._throttleTimer = setTimeout(function() {
1007
+ self._throttleTimer = null;
1008
+ var state = self._state;
1009
+ self._listeners.forEach(function(fn) {
1010
+ try {
1011
+ fn(state);
1012
+ } catch (e) {
1013
+ }
1014
+ });
1015
+ }, 50);
90
1016
  }
91
- }
92
-
93
- // ========== Initialization ==========
94
-
95
- ChatStore.prototype.initIM = function (cfg) {
96
- if (!cfg || !cfg.apiBase || !cfg.platformApiKey) return Promise.resolve()
97
- var self = this
98
- var st = this._state
99
- if (st.initializing || IMService.isReady()) return Promise.resolve()
100
-
101
- this._setState({ initializing: true, error: null, apiBase: cfg.apiBase, platformApiKey: cfg.platformApiKey })
102
-
103
- var apiBase = cfg.apiBase
104
- var platformApiKey = cfg.platformApiKey
105
-
106
- // Load or register visitor
107
- var cached = visitorService.loadCachedVisitor(apiBase, platformApiKey)
108
- var visitorPromise
1017
+ };
1018
+ ChatStore.prototype.subscribe = function(fn) {
1019
+ this._listeners.push(fn);
1020
+ var self = this;
1021
+ return function() {
1022
+ var idx = self._listeners.indexOf(fn);
1023
+ if (idx >= 0) self._listeners.splice(idx, 1);
1024
+ };
1025
+ };
1026
+ ChatStore.prototype.initIM = function(cfg) {
1027
+ if (!cfg || !cfg.apiBase || !cfg.platformApiKey) return Promise.resolve();
1028
+ var self = this;
1029
+ var st = this._state;
1030
+ if (st.initializing || IMService.isReady()) return Promise.resolve();
1031
+ this._setState({ initializing: true, error: null, apiBase: cfg.apiBase, platformApiKey: cfg.platformApiKey });
1032
+ var apiBase = cfg.apiBase;
1033
+ var platformApiKey = cfg.platformApiKey;
1034
+ var cached = visitorService.loadCachedVisitor(apiBase, platformApiKey);
1035
+ var visitorPromise;
109
1036
  if (cached) {
110
- visitorPromise = Promise.resolve(cached)
1037
+ visitorPromise = Promise.resolve(cached);
111
1038
  } else {
112
- var sysInfo = systemInfoAdapter.collectSystemInfo()
1039
+ var sysInfo = systemInfoAdapter.collectSystemInfo();
113
1040
  visitorPromise = visitorService.registerVisitor({
114
- apiBase: apiBase,
115
- platformApiKey: platformApiKey,
1041
+ apiBase,
1042
+ platformApiKey,
116
1043
  extra: sysInfo ? { system_info: sysInfo } : {}
117
- }).then(function (res) {
118
- visitorService.saveCachedVisitor(apiBase, platformApiKey, res)
119
- return visitorService.loadCachedVisitor(apiBase, platformApiKey)
120
- })
1044
+ }).then(function(res) {
1045
+ visitorService.saveCachedVisitor(apiBase, platformApiKey, res);
1046
+ return visitorService.loadCachedVisitor(apiBase, platformApiKey);
1047
+ });
121
1048
  }
122
-
123
- return visitorPromise.then(function (visitor) {
124
- var uid = String(visitor.visitor_id || '')
125
- var uidForIM = uid.endsWith('-vtr') ? uid : uid + '-vtr'
126
- var target = visitor.channel_id
127
- var token = visitor.im_token
128
-
1049
+ return visitorPromise.then(function(visitor) {
1050
+ var uid = String(visitor.visitor_id || "");
1051
+ var uidForIM = uid.endsWith("-vtr") ? uid : uid + "-vtr";
1052
+ var target = visitor.channel_id;
1053
+ var token = visitor.im_token;
129
1054
  self._setState({
130
1055
  myUid: uidForIM,
131
1056
  channelId: target,
132
1057
  channelType: visitor.channel_type || 251
133
- })
134
-
1058
+ });
135
1059
  if (!token) {
136
- throw new Error('[Chat] Missing im_token from visitor registration')
1060
+ throw new Error("[Chat] Missing im_token from visitor registration");
137
1061
  }
138
-
139
1062
  return IMService.init({
140
- apiBase: apiBase,
1063
+ apiBase,
141
1064
  uid: uidForIM,
142
- token: token,
143
- target: target,
144
- channelType: 'group'
145
- })
146
- }).then(function () {
147
- // Subscribe to IM events
148
- self._bindIMEvents()
149
- return IMService.connect()
150
- }).then(function () {
151
- // Load initial history
152
- return self.loadInitialHistory(20)
153
- }).catch(function (e) {
154
- var errMsg = e && e.message ? e.message : String(e)
155
- console.error('[Chat] IM initialization failed:', errMsg)
156
- self._setState({ error: errMsg, online: false })
157
- }).then(function () {
158
- self._setState({ initializing: false })
159
- })
160
- }
161
-
162
- ChatStore.prototype._bindIMEvents = function () {
163
- var self = this
164
- var uidForIM = this._state.myUid
165
-
166
- // Status events
167
- if (offStatus) { try { offStatus() } catch (e) {} ; offStatus = null }
168
- offStatus = IMService.onStatus(function (s) {
169
- self._setState({ online: s === 'connected' })
170
- })
171
-
172
- // Message events
173
- if (offMsg) { try { offMsg() } catch (e) {} ; offMsg = null }
174
- offMsg = IMService.onMessage(function (m) {
175
- if (!m.fromUid || m.fromUid === uidForIM) return
176
-
1065
+ token,
1066
+ target,
1067
+ channelType: "group"
1068
+ });
1069
+ }).then(function() {
1070
+ self._bindIMEvents();
1071
+ return IMService.connect();
1072
+ }).then(function() {
1073
+ return self.loadInitialHistory(20);
1074
+ }).catch(function(e) {
1075
+ var errMsg = e && e.message ? e.message : String(e);
1076
+ console.error("[Chat] IM initialization failed:", errMsg);
1077
+ self._setState({ error: errMsg, online: false });
1078
+ }).then(function() {
1079
+ self._setState({ initializing: false });
1080
+ });
1081
+ };
1082
+ ChatStore.prototype._bindIMEvents = function() {
1083
+ var self = this;
1084
+ var uidForIM = this._state.myUid;
1085
+ if (offStatus) {
1086
+ try {
1087
+ offStatus();
1088
+ } catch (e) {
1089
+ }
1090
+ ;
1091
+ offStatus = null;
1092
+ }
1093
+ offStatus = IMService.onStatus(function(s) {
1094
+ self._setState({ online: s === "connected" });
1095
+ });
1096
+ if (offMsg) {
1097
+ try {
1098
+ offMsg();
1099
+ } catch (e) {
1100
+ }
1101
+ ;
1102
+ offMsg = null;
1103
+ }
1104
+ offMsg = IMService.onMessage(function(m) {
1105
+ if (!m.fromUid || m.fromUid === uidForIM) return;
177
1106
  var chat = {
178
1107
  id: String(m.messageId),
179
- role: 'agent',
1108
+ role: "agent",
180
1109
  payload: types.toPayloadFromAny(m && m.payload),
181
- time: new Date(m.timestamp * 1000),
182
- messageSeq: typeof m.messageSeq === 'number' ? m.messageSeq : undefined,
1110
+ time: new Date(m.timestamp * 1e3),
1111
+ messageSeq: typeof m.messageSeq === "number" ? m.messageSeq : void 0,
183
1112
  clientMsgNo: m.clientMsgNo,
184
1113
  fromUid: m.fromUid,
185
1114
  channelId: m.channelId,
186
1115
  channelType: m.channelType
187
- }
188
-
189
- var currentMessages = self._state.messages
1116
+ };
1117
+ var currentMessages = self._state.messages;
190
1118
  for (var i = 0; i < currentMessages.length; i++) {
191
- if (currentMessages[i].id === chat.id) return
1119
+ if (currentMessages[i].id === chat.id) return;
192
1120
  }
193
-
194
- // Merge into streaming placeholder if exists
195
1121
  if (chat.clientMsgNo) {
196
- var idx = -1
1122
+ var idx = -1;
197
1123
  for (var j = 0; j < currentMessages.length; j++) {
198
1124
  if (currentMessages[j].clientMsgNo && currentMessages[j].clientMsgNo === chat.clientMsgNo) {
199
- idx = j
200
- break
1125
+ idx = j;
1126
+ break;
201
1127
  }
202
1128
  }
203
1129
  if (idx >= 0) {
204
- var next = currentMessages.slice()
205
- next[idx] = Object.assign({}, currentMessages[idx], chat, { streamData: undefined })
206
- self._setState({ messages: next })
207
- return
1130
+ var next = currentMessages.slice();
1131
+ next[idx] = Object.assign({}, currentMessages[idx], chat, { streamData: void 0 });
1132
+ self._setState({ messages: next });
1133
+ return;
208
1134
  }
209
1135
  }
210
-
211
- self._setState({ messages: currentMessages.concat([chat]) })
212
- })
213
-
214
- // Custom stream events
215
- if (offCustom) { try { offCustom() } catch (e) {} ; offCustom = null }
216
- offCustom = IMService.onCustom(function (ev) {
1136
+ self._setState({ messages: currentMessages.concat([chat]) });
1137
+ });
1138
+ if (offCustom) {
217
1139
  try {
218
- if (!ev) return
219
- var customEvent = ev
220
-
221
- // Parse event data
222
- var eventData = null
223
- if (customEvent.dataJson && typeof customEvent.dataJson === 'object') {
224
- eventData = customEvent.dataJson
225
- } else if (typeof customEvent.data === 'string') {
226
- try { eventData = JSON.parse(customEvent.data) } catch (e) {}
227
- } else if (customEvent.data && typeof customEvent.data === 'object') {
228
- eventData = customEvent.data
1140
+ offCustom();
1141
+ } catch (e) {
1142
+ }
1143
+ ;
1144
+ offCustom = null;
1145
+ }
1146
+ offCustom = IMService.onCustom(function(ev) {
1147
+ try {
1148
+ if (!ev) return;
1149
+ var customEvent = ev;
1150
+ var eventData = null;
1151
+ if (customEvent.dataJson && typeof customEvent.dataJson === "object") {
1152
+ eventData = customEvent.dataJson;
1153
+ } else if (typeof customEvent.data === "string") {
1154
+ try {
1155
+ eventData = JSON.parse(customEvent.data);
1156
+ } catch (e) {
1157
+ }
1158
+ } else if (customEvent.data && typeof customEvent.data === "object") {
1159
+ eventData = customEvent.data;
229
1160
  }
230
-
231
- var newEventType = (eventData && eventData.event_type) || customEvent.type || ''
232
- var clientMsgNo = (eventData && eventData.client_msg_no) ? String(eventData.client_msg_no) : (customEvent.id ? String(customEvent.id) : '')
233
-
234
- // --- Stream API v2 ---
235
- if (newEventType === 'stream.delta') {
236
- if (!clientMsgNo) return
237
- var payload = eventData && eventData.payload
238
- var delta = payload && payload.delta
1161
+ var newEventType = eventData && eventData.event_type || customEvent.type || "";
1162
+ var clientMsgNo = eventData && eventData.client_msg_no ? String(eventData.client_msg_no) : customEvent.id ? String(customEvent.id) : "";
1163
+ if (newEventType === "stream.delta") {
1164
+ if (!clientMsgNo) return;
1165
+ var payload = eventData && eventData.payload;
1166
+ var delta = payload && payload.delta;
239
1167
  if (delta) {
240
- var parser = activeParsers[clientMsgNo]
1168
+ var parser = activeParsers[clientMsgNo];
241
1169
  if (!parser) {
242
1170
  parser = jsonRenderUtils.createMixedStreamParser({
243
- onText: function (t) { self.appendMixedPart(clientMsgNo, { type: 'text', text: t + '\n' }) },
244
- onPatch: function (p) { self.appendMixedPart(clientMsgNo, { type: 'data-spec', data: { type: 'patch', patch: p } }) }
245
- })
246
- activeParsers[clientMsgNo] = parser
1171
+ onText: function(t) {
1172
+ self.appendMixedPart(clientMsgNo, { type: "text", text: t + "\n" });
1173
+ },
1174
+ onPatch: function(p) {
1175
+ self.appendMixedPart(clientMsgNo, { type: "data-spec", data: { type: "patch", patch: p } });
1176
+ }
1177
+ });
1178
+ activeParsers[clientMsgNo] = parser;
247
1179
  }
248
- parser.push(String(delta).replace(/([^\n])```spec/g, '$1\n```spec'))
1180
+ parser.push(String(delta).replace(/([^\n])```spec/g, "$1\n```spec"));
249
1181
  }
250
- return
1182
+ return;
251
1183
  }
252
-
253
- if (newEventType === 'stream.close') {
254
- if (!clientMsgNo) return
255
- var closeParser = activeParsers[clientMsgNo]
256
- if (closeParser) { closeParser.flush(); delete activeParsers[clientMsgNo] }
257
- var errMsg = (eventData && eventData.payload && eventData.payload.end_reason > 0) ? '流异常结束' : undefined
258
- self.finalizeStreamMessage(clientMsgNo, errMsg)
259
- self.markStreamingEnd()
260
- return
1184
+ if (newEventType === "stream.close") {
1185
+ if (!clientMsgNo) return;
1186
+ var closeParser = activeParsers[clientMsgNo];
1187
+ if (closeParser) {
1188
+ closeParser.flush();
1189
+ delete activeParsers[clientMsgNo];
1190
+ }
1191
+ var errMsg = eventData && eventData.payload && eventData.payload.end_reason > 0 ? "\u6D41\u5F02\u5E38\u7ED3\u675F" : void 0;
1192
+ self.finalizeStreamMessage(clientMsgNo, errMsg);
1193
+ self.markStreamingEnd();
1194
+ return;
261
1195
  }
262
-
263
- if (newEventType === 'stream.error') {
264
- if (!clientMsgNo) return
265
- var errParser = activeParsers[clientMsgNo]
266
- if (errParser) { errParser.flush(); delete activeParsers[clientMsgNo] }
267
- var errMessage = (eventData && eventData.payload && eventData.payload.error) || '未知错误'
268
- self.finalizeStreamMessage(clientMsgNo, errMessage)
269
- self.markStreamingEnd()
270
- return
1196
+ if (newEventType === "stream.error") {
1197
+ if (!clientMsgNo) return;
1198
+ var errParser = activeParsers[clientMsgNo];
1199
+ if (errParser) {
1200
+ errParser.flush();
1201
+ delete activeParsers[clientMsgNo];
1202
+ }
1203
+ var errMessage = eventData && eventData.payload && eventData.payload.error || "\u672A\u77E5\u9519\u8BEF";
1204
+ self.finalizeStreamMessage(clientMsgNo, errMessage);
1205
+ self.markStreamingEnd();
1206
+ return;
271
1207
  }
272
-
273
- if (newEventType === 'stream.cancel') {
274
- if (!clientMsgNo) return
275
- var cancelParser = activeParsers[clientMsgNo]
276
- if (cancelParser) { cancelParser.flush(); delete activeParsers[clientMsgNo] }
277
- self.finalizeStreamMessage(clientMsgNo)
278
- self.markStreamingEnd()
279
- return
1208
+ if (newEventType === "stream.cancel") {
1209
+ if (!clientMsgNo) return;
1210
+ var cancelParser = activeParsers[clientMsgNo];
1211
+ if (cancelParser) {
1212
+ cancelParser.flush();
1213
+ delete activeParsers[clientMsgNo];
1214
+ }
1215
+ self.finalizeStreamMessage(clientMsgNo);
1216
+ self.markStreamingEnd();
1217
+ return;
280
1218
  }
281
-
282
- if (newEventType === 'stream.finish') {
283
- return
1219
+ if (newEventType === "stream.finish") {
1220
+ return;
284
1221
  }
285
-
286
- // --- Legacy event format ---
287
- if (customEvent.type === '___TextMessageStart') {
288
- var startId = customEvent.id ? String(customEvent.id) : ''
289
- if (startId) self.markStreamingStart(startId)
290
- return
1222
+ if (customEvent.type === "___TextMessageStart") {
1223
+ var startId = customEvent.id ? String(customEvent.id) : "";
1224
+ if (startId) self.markStreamingStart(startId);
1225
+ return;
291
1226
  }
292
-
293
- if (customEvent.type === '___TextMessageContent') {
294
- var contentId = customEvent.id ? String(customEvent.id) : ''
295
- if (!contentId) return
296
- var chunk = typeof customEvent.data === 'string' ? customEvent.data : (customEvent.data != null ? String(customEvent.data) : '')
297
- if (chunk) self.appendStreamData(contentId, chunk)
298
- return
1227
+ if (customEvent.type === "___TextMessageContent") {
1228
+ var contentId = customEvent.id ? String(customEvent.id) : "";
1229
+ if (!contentId) return;
1230
+ var chunk = typeof customEvent.data === "string" ? customEvent.data : customEvent.data != null ? String(customEvent.data) : "";
1231
+ if (chunk) self.appendStreamData(contentId, chunk);
1232
+ return;
299
1233
  }
300
-
301
- if (customEvent.type === '___TextMessageEnd') {
302
- var endId = customEvent.id ? String(customEvent.id) : ''
303
- if (!endId) return
304
- var endError = customEvent.data ? String(customEvent.data) : undefined
305
- self.finalizeStreamMessage(endId, endError)
306
- self.markStreamingEnd()
307
- return
1234
+ if (customEvent.type === "___TextMessageEnd") {
1235
+ var endId = customEvent.id ? String(customEvent.id) : "";
1236
+ if (!endId) return;
1237
+ var endError = customEvent.data ? String(customEvent.data) : void 0;
1238
+ self.finalizeStreamMessage(endId, endError);
1239
+ self.markStreamingEnd();
1240
+ return;
308
1241
  }
309
1242
  } catch (err) {
310
- console.error('[Chat] Custom event handler error:', err)
1243
+ console.error("[Chat] Custom event handler error:", err);
311
1244
  }
312
- })
313
- }
314
-
315
- // ========== Send Message ==========
316
-
317
- ChatStore.prototype.sendMessage = function (text) {
318
- var v = (text || '').trim()
319
- if (!v) return Promise.resolve()
320
-
321
- var self = this
322
- var clientMsgNo = uidUtil.generateClientMsgNo('cmn')
323
- var id = 'u-' + Date.now()
1245
+ });
1246
+ };
1247
+ ChatStore.prototype.sendMessage = function(text) {
1248
+ var v = (text || "").trim();
1249
+ if (!v) return Promise.resolve();
1250
+ var self = this;
1251
+ var clientMsgNo = uidUtil.generateClientMsgNo("cmn");
1252
+ var id = "u-" + Date.now();
324
1253
  var msg = {
325
- id: id,
326
- role: 'user',
1254
+ id,
1255
+ role: "user",
327
1256
  payload: { type: 1, content: v },
328
- time: new Date(),
329
- status: 'sending',
330
- clientMsgNo: clientMsgNo
331
- }
332
-
333
- // Add to messages immediately
334
- this._setState({ messages: this._state.messages.concat([msg]) })
335
-
336
- var st = this._state
1257
+ time: /* @__PURE__ */ new Date(),
1258
+ status: "sending",
1259
+ clientMsgNo
1260
+ };
1261
+ this._setState({ messages: this._state.messages.concat([msg]) });
1262
+ var st = this._state;
337
1263
  if (!st.apiBase || !st.platformApiKey || !st.myUid) {
338
- this._updateMessage(id, { status: undefined, errorMessage: 'Not initialized' })
339
- return Promise.resolve()
1264
+ this._updateMessage(id, { status: void 0, errorMessage: "Not initialized" });
1265
+ return Promise.resolve();
340
1266
  }
341
-
342
- // Auto-cancel previous streaming
343
- var cancelPromise = st.isStreaming ? this.cancelStreaming('auto_cancel_on_new_send') : Promise.resolve()
344
-
345
- return cancelPromise.then(function () {
346
- // Wait for IM ready
1267
+ var cancelPromise = st.isStreaming ? this.cancelStreaming("auto_cancel_on_new_send") : Promise.resolve();
1268
+ return cancelPromise.then(function() {
347
1269
  if (!IMService.isReady()) {
348
- return self._waitForIMReady(10000)
1270
+ return self._waitForIMReady(1e4);
349
1271
  }
350
- }).then(function () {
1272
+ }).then(function() {
351
1273
  if (!IMService.isReady()) {
352
- throw new Error('IM service is not ready')
1274
+ throw new Error("IM service is not ready");
353
1275
  }
354
- return IMService.sendText(v, { clientMsgNo: clientMsgNo })
355
- }).then(function (result) {
356
- var ReasonCode = require('easyjssdk').ReasonCode
1276
+ return IMService.sendText(v, { clientMsgNo });
1277
+ }).then(function(result) {
1278
+ var ReasonCode = require_cjs().ReasonCode;
357
1279
  if (result.reasonCode !== ReasonCode.Success) {
358
- self._updateMessage(id, { status: undefined, reasonCode: result.reasonCode })
359
- return
1280
+ self._updateMessage(id, { status: void 0, reasonCode: result.reasonCode });
1281
+ return;
360
1282
  }
361
-
362
- // Call chat completion API
363
1283
  return chatService.sendChatCompletion({
364
1284
  apiBase: self._state.apiBase,
365
1285
  platformApiKey: self._state.platformApiKey,
@@ -367,99 +1287,87 @@ ChatStore.prototype.sendMessage = function (text) {
367
1287
  fromUid: self._state.myUid,
368
1288
  channelId: self._state.channelId,
369
1289
  channelType: self._state.channelType
370
- }).then(function () {
371
- self._updateMessage(id, { status: undefined, reasonCode: result.reasonCode })
372
- })
373
- }).catch(function (e) {
374
- console.error('[Chat] Send failed:', e)
375
- self.markStreamingEnd()
376
- var ReasonCode = require('easyjssdk').ReasonCode
377
- self._updateMessage(id, { status: undefined, reasonCode: ReasonCode.Unknown })
378
- self._setState({ error: e && e.message ? e.message : String(e) })
379
- })
380
- }
381
-
382
- ChatStore.prototype._waitForIMReady = function (timeoutMs) {
383
- var start = Date.now()
384
- return new Promise(function (resolve) {
385
- var check = function () {
386
- if (IMService.isReady() || (Date.now() - start) >= timeoutMs) {
387
- resolve()
1290
+ }).then(function() {
1291
+ self._updateMessage(id, { status: void 0, reasonCode: result.reasonCode });
1292
+ });
1293
+ }).catch(function(e) {
1294
+ console.error("[Chat] Send failed:", e);
1295
+ self.markStreamingEnd();
1296
+ var ReasonCode = require_cjs().ReasonCode;
1297
+ self._updateMessage(id, { status: void 0, reasonCode: ReasonCode.Unknown });
1298
+ self._setState({ error: e && e.message ? e.message : String(e) });
1299
+ });
1300
+ };
1301
+ ChatStore.prototype._waitForIMReady = function(timeoutMs) {
1302
+ var start = Date.now();
1303
+ return new Promise(function(resolve) {
1304
+ var check = function() {
1305
+ if (IMService.isReady() || Date.now() - start >= timeoutMs) {
1306
+ resolve();
388
1307
  } else {
389
- setTimeout(check, 120)
1308
+ setTimeout(check, 120);
390
1309
  }
391
- }
392
- check()
393
- })
394
- }
395
-
396
- ChatStore.prototype._updateMessage = function (id, partial) {
397
- var messages = this._state.messages.map(function (m) {
398
- if (m.id === id) return Object.assign({}, m, partial)
399
- return m
400
- })
401
- this._setState({ messages: messages })
402
- }
403
-
404
- // ========== Upload ==========
405
-
406
- ChatStore.prototype.uploadImage = function (tempFilePath) {
407
- var self = this
408
- var st = this._state
1310
+ };
1311
+ check();
1312
+ });
1313
+ };
1314
+ ChatStore.prototype._updateMessage = function(id, partial) {
1315
+ var messages = this._state.messages.map(function(m) {
1316
+ if (m.id === id) return Object.assign({}, m, partial);
1317
+ return m;
1318
+ });
1319
+ this._setState({ messages });
1320
+ };
1321
+ ChatStore.prototype.uploadImage = function(tempFilePath) {
1322
+ var self = this;
1323
+ var st = this._state;
409
1324
  if (!st.apiBase || !st.channelId) {
410
- this._setState({ error: '[Upload] Not initialized' })
411
- return Promise.resolve()
1325
+ this._setState({ error: "[Upload] Not initialized" });
1326
+ return Promise.resolve();
412
1327
  }
413
-
414
- var clientMsgNo = uidUtil.generateClientMsgNo('um')
415
- var id = 'u-up-' + Date.now() + '-' + Math.random().toString(36).slice(2, 6)
1328
+ var clientMsgNo = uidUtil.generateClientMsgNo("um");
1329
+ var id = "u-up-" + Date.now() + "-" + Math.random().toString(36).slice(2, 6);
416
1330
  var placeholder = {
417
- id: id,
418
- role: 'user',
419
- payload: { type: 1, content: '图片上传中…' },
420
- time: new Date(),
421
- status: 'uploading',
1331
+ id,
1332
+ role: "user",
1333
+ payload: { type: 1, content: "\u56FE\u7247\u4E0A\u4F20\u4E2D\u2026" },
1334
+ time: /* @__PURE__ */ new Date(),
1335
+ status: "uploading",
422
1336
  uploadProgress: 0,
423
- clientMsgNo: clientMsgNo
424
- }
425
- this._setState({ messages: this._state.messages.concat([placeholder]) })
426
-
427
- return uploadService.getImageInfo(tempFilePath).then(function (dims) {
1337
+ clientMsgNo
1338
+ };
1339
+ this._setState({ messages: this._state.messages.concat([placeholder]) });
1340
+ return uploadService.getImageInfo(tempFilePath).then(function(dims) {
428
1341
  return uploadService.uploadChatFile({
429
1342
  apiBase: st.apiBase,
430
1343
  apiKey: st.platformApiKey,
431
1344
  channelId: st.channelId,
432
1345
  channelType: st.channelType,
433
1346
  filePath: tempFilePath,
434
- onProgress: function (p) {
435
- self._updateMessage(id, { uploadProgress: p })
436
- }
437
- }).then(function (res) {
438
- var w = dims ? Math.max(1, dims.width) : 1
439
- var h = dims ? Math.max(1, dims.height) : 1
440
- var payload = { type: 2, url: res.file_url, width: w, height: h }
441
- self._updateMessage(id, { payload: payload, status: 'sending', uploadProgress: undefined })
442
- return IMService.sendPayload(payload, { clientMsgNo: clientMsgNo })
443
- }).then(function (result) {
444
- self._updateMessage(id, { status: undefined, reasonCode: result && result.reasonCode })
445
- })
446
- }).catch(function (err) {
447
- console.error('[Chat] Upload failed:', err)
448
- self._updateMessage(id, { status: undefined, uploadError: err && err.message ? err.message : '上传失败' })
449
- })
450
- }
451
-
452
- // ========== History ==========
453
-
454
- ChatStore.prototype.loadInitialHistory = function (limit) {
455
- limit = limit || 20
456
- var self = this
457
- var st = this._state
458
- if (!st.channelId || !st.channelType) return Promise.resolve()
459
- if (st.historyLoading) return Promise.resolve()
460
-
461
- this._setState({ historyLoading: true, historyError: null })
462
-
1347
+ onProgress: function(p) {
1348
+ self._updateMessage(id, { uploadProgress: p });
1349
+ }
1350
+ }).then(function(res) {
1351
+ var w = dims ? Math.max(1, dims.width) : 1;
1352
+ var h = dims ? Math.max(1, dims.height) : 1;
1353
+ var payload = { type: 2, url: res.file_url, width: w, height: h };
1354
+ self._updateMessage(id, { payload, status: "sending", uploadProgress: void 0 });
1355
+ return IMService.sendPayload(payload, { clientMsgNo });
1356
+ }).then(function(result) {
1357
+ self._updateMessage(id, { status: void 0, reasonCode: result && result.reasonCode });
1358
+ });
1359
+ }).catch(function(err) {
1360
+ console.error("[Chat] Upload failed:", err);
1361
+ self._updateMessage(id, { status: void 0, uploadError: err && err.message ? err.message : "\u4E0A\u4F20\u5931\u8D25" });
1362
+ });
1363
+ };
1364
+ ChatStore.prototype.loadInitialHistory = function(limit) {
1365
+ limit = limit || 20;
1366
+ var self = this;
1367
+ var st = this._state;
1368
+ if (!st.channelId || !st.channelType) return Promise.resolve();
1369
+ if (st.historyLoading) return Promise.resolve();
1370
+ this._setState({ historyLoading: true, historyError: null });
463
1371
  return historyService.syncVisitorMessages({
464
1372
  apiBase: st.apiBase,
465
1373
  platformApiKey: st.platformApiKey,
@@ -467,58 +1375,50 @@ ChatStore.prototype.loadInitialHistory = function (limit) {
467
1375
  channelType: st.channelType,
468
1376
  startSeq: 0,
469
1377
  endSeq: 0,
470
- limit: limit,
1378
+ limit,
471
1379
  pullMode: 1
472
- }).then(function (res) {
473
- var myUid = self._state.myUid
474
- var list = res.messages.slice().sort(function (a, b) {
475
- return (a.message_seq || 0) - (b.message_seq || 0)
476
- }).map(function (m) {
477
- return types.mapHistoryToChatMessage(m, myUid)
478
- })
479
-
480
- // Dedup and prepend
481
- var existingSeqs = {}
482
- var existingIds = {}
483
- self._state.messages.forEach(function (m) {
484
- if (typeof m.messageSeq === 'number') existingSeqs[m.messageSeq] = true
485
- existingIds[m.id] = true
486
- })
487
-
488
- var mergedHead = list.filter(function (m) {
489
- if (m.messageSeq != null) return !existingSeqs[m.messageSeq]
490
- return !existingIds[m.id]
491
- })
492
-
493
- var earliest = self._state.earliestSeq
494
- mergedHead.forEach(function (m) {
1380
+ }).then(function(res) {
1381
+ var myUid = self._state.myUid;
1382
+ var list = res.messages.slice().sort(function(a, b) {
1383
+ return (a.message_seq || 0) - (b.message_seq || 0);
1384
+ }).map(function(m) {
1385
+ return types.mapHistoryToChatMessage(m, myUid);
1386
+ });
1387
+ var existingSeqs = {};
1388
+ var existingIds = {};
1389
+ self._state.messages.forEach(function(m) {
1390
+ if (typeof m.messageSeq === "number") existingSeqs[m.messageSeq] = true;
1391
+ existingIds[m.id] = true;
1392
+ });
1393
+ var mergedHead = list.filter(function(m) {
1394
+ if (m.messageSeq != null) return !existingSeqs[m.messageSeq];
1395
+ return !existingIds[m.id];
1396
+ });
1397
+ var earliest = self._state.earliestSeq;
1398
+ mergedHead.forEach(function(m) {
495
1399
  if (m.messageSeq != null) {
496
- if (earliest === null || m.messageSeq < earliest) earliest = m.messageSeq
1400
+ if (earliest === null || m.messageSeq < earliest) earliest = m.messageSeq;
497
1401
  }
498
- })
499
-
1402
+ });
500
1403
  self._setState({
501
1404
  messages: mergedHead.concat(self._state.messages),
502
1405
  earliestSeq: earliest,
503
1406
  historyHasMore: res.more === 1
504
- })
505
- }).catch(function (e) {
506
- self._setState({ historyError: e && e.message ? e.message : String(e) })
507
- }).then(function () {
508
- self._setState({ historyLoading: false })
509
- })
510
- }
511
-
512
- ChatStore.prototype.loadMoreHistory = function (limit) {
513
- limit = limit || 20
514
- var self = this
515
- var st = this._state
516
- if (!st.channelId || !st.channelType) return Promise.resolve()
517
- if (st.historyLoading) return Promise.resolve()
518
-
519
- var start = st.earliestSeq || 0
520
- this._setState({ historyLoading: true, historyError: null })
521
-
1407
+ });
1408
+ }).catch(function(e) {
1409
+ self._setState({ historyError: e && e.message ? e.message : String(e) });
1410
+ }).then(function() {
1411
+ self._setState({ historyLoading: false });
1412
+ });
1413
+ };
1414
+ ChatStore.prototype.loadMoreHistory = function(limit) {
1415
+ limit = limit || 20;
1416
+ var self = this;
1417
+ var st = this._state;
1418
+ if (!st.channelId || !st.channelType) return Promise.resolve();
1419
+ if (st.historyLoading) return Promise.resolve();
1420
+ var start = st.earliestSeq || 0;
1421
+ this._setState({ historyLoading: true, historyError: null });
522
1422
  return historyService.syncVisitorMessages({
523
1423
  apiBase: st.apiBase,
524
1424
  platformApiKey: st.platformApiKey,
@@ -526,233 +1426,236 @@ ChatStore.prototype.loadMoreHistory = function (limit) {
526
1426
  channelType: st.channelType,
527
1427
  startSeq: start,
528
1428
  endSeq: 0,
529
- limit: limit,
1429
+ limit,
530
1430
  pullMode: 0
531
- }).then(function (res) {
532
- var myUid = self._state.myUid
533
- var listAsc = res.messages.slice().sort(function (a, b) {
534
- return (a.message_seq || 0) - (b.message_seq || 0)
535
- }).map(function (m) {
536
- return types.mapHistoryToChatMessage(m, myUid)
537
- })
538
-
539
- var existingSeqs = {}
540
- var existingIds = {}
541
- self._state.messages.forEach(function (m) {
542
- if (typeof m.messageSeq === 'number') existingSeqs[m.messageSeq] = true
543
- existingIds[m.id] = true
544
- })
545
-
546
- var prepend = listAsc.filter(function (m) {
547
- if (m.messageSeq != null) return !existingSeqs[m.messageSeq]
548
- return !existingIds[m.id]
549
- })
550
-
551
- var earliest = self._state.earliestSeq
552
- prepend.forEach(function (m) {
1431
+ }).then(function(res) {
1432
+ var myUid = self._state.myUid;
1433
+ var listAsc = res.messages.slice().sort(function(a, b) {
1434
+ return (a.message_seq || 0) - (b.message_seq || 0);
1435
+ }).map(function(m) {
1436
+ return types.mapHistoryToChatMessage(m, myUid);
1437
+ });
1438
+ var existingSeqs = {};
1439
+ var existingIds = {};
1440
+ self._state.messages.forEach(function(m) {
1441
+ if (typeof m.messageSeq === "number") existingSeqs[m.messageSeq] = true;
1442
+ existingIds[m.id] = true;
1443
+ });
1444
+ var prepend = listAsc.filter(function(m) {
1445
+ if (m.messageSeq != null) return !existingSeqs[m.messageSeq];
1446
+ return !existingIds[m.id];
1447
+ });
1448
+ var earliest = self._state.earliestSeq;
1449
+ prepend.forEach(function(m) {
553
1450
  if (m.messageSeq != null) {
554
- if (earliest === null || m.messageSeq < earliest) earliest = m.messageSeq
1451
+ if (earliest === null || m.messageSeq < earliest) earliest = m.messageSeq;
555
1452
  }
556
- })
557
-
1453
+ });
558
1454
  self._setState({
559
1455
  messages: prepend.concat(self._state.messages),
560
1456
  earliestSeq: earliest,
561
1457
  historyHasMore: res.more === 1
562
- })
563
- }).catch(function (e) {
564
- self._setState({ historyError: e && e.message ? e.message : String(e) })
565
- }).then(function () {
566
- self._setState({ historyLoading: false })
567
- })
568
- }
569
-
570
- // ========== Streaming ==========
571
-
572
- ChatStore.prototype.markStreamingStart = function (clientMsgNo) {
573
- if (!clientMsgNo) return
574
- if (streamTimer) { try { clearTimeout(streamTimer) } catch (e) {} ; streamTimer = null }
575
- var self = this
576
- this._setState({ isStreaming: true, streamCanceling: false, streamingClientMsgNo: clientMsgNo })
577
- streamTimer = setTimeout(function () {
578
- var s = self._state
1458
+ });
1459
+ }).catch(function(e) {
1460
+ self._setState({ historyError: e && e.message ? e.message : String(e) });
1461
+ }).then(function() {
1462
+ self._setState({ historyLoading: false });
1463
+ });
1464
+ };
1465
+ ChatStore.prototype.markStreamingStart = function(clientMsgNo) {
1466
+ if (!clientMsgNo) return;
1467
+ if (streamTimer) {
1468
+ try {
1469
+ clearTimeout(streamTimer);
1470
+ } catch (e) {
1471
+ }
1472
+ ;
1473
+ streamTimer = null;
1474
+ }
1475
+ var self = this;
1476
+ this._setState({ isStreaming: true, streamCanceling: false, streamingClientMsgNo: clientMsgNo });
1477
+ streamTimer = setTimeout(function() {
1478
+ var s = self._state;
579
1479
  if (s.isStreaming && s.streamingClientMsgNo === clientMsgNo) {
580
- self._setState({ isStreaming: false, streamingClientMsgNo: '', streamCanceling: false })
1480
+ self._setState({ isStreaming: false, streamingClientMsgNo: "", streamCanceling: false });
581
1481
  }
582
- }, STREAM_TIMEOUT_MS)
583
- }
584
-
585
- ChatStore.prototype.markStreamingEnd = function () {
586
- if (streamTimer) { try { clearTimeout(streamTimer) } catch (e) {} ; streamTimer = null }
587
- this._setState({ isStreaming: false, streamCanceling: false, streamingClientMsgNo: '' })
588
- }
589
-
590
- ChatStore.prototype.cancelStreaming = function (reason) {
591
- var self = this
592
- var st = this._state
593
- if (st.streamCanceling) return Promise.resolve()
594
-
595
- this._setState({ streamCanceling: true })
596
-
1482
+ }, STREAM_TIMEOUT_MS);
1483
+ };
1484
+ ChatStore.prototype.markStreamingEnd = function() {
1485
+ if (streamTimer) {
1486
+ try {
1487
+ clearTimeout(streamTimer);
1488
+ } catch (e) {
1489
+ }
1490
+ ;
1491
+ streamTimer = null;
1492
+ }
1493
+ this._setState({ isStreaming: false, streamCanceling: false, streamingClientMsgNo: "" });
1494
+ };
1495
+ ChatStore.prototype.cancelStreaming = function(reason) {
1496
+ var self = this;
1497
+ var st = this._state;
1498
+ if (st.streamCanceling) return Promise.resolve();
1499
+ this._setState({ streamCanceling: true });
597
1500
  if (!st.apiBase || !st.streamingClientMsgNo || !st.platformApiKey) {
598
- this.markStreamingEnd()
599
- return Promise.resolve()
1501
+ this.markStreamingEnd();
1502
+ return Promise.resolve();
600
1503
  }
601
-
602
1504
  return chatService.cancelStreaming({
603
1505
  apiBase: st.apiBase,
604
1506
  platformApiKey: st.platformApiKey,
605
1507
  clientMsgNo: st.streamingClientMsgNo,
606
- reason: reason || 'user_cancel'
607
- }).catch(function (e) {
608
- console.warn('[Chat] Cancel streaming error:', e)
609
- }).then(function () {
610
- self.markStreamingEnd()
611
- })
612
- }
613
-
614
- ChatStore.prototype.appendStreamData = function (clientMsgNo, data) {
615
- if (!clientMsgNo || !data) return
616
-
617
- var messages = this._state.messages
618
- var found = false
619
- var updated = messages.map(function (m) {
1508
+ reason: reason || "user_cancel"
1509
+ }).catch(function(e) {
1510
+ console.warn("[Chat] Cancel streaming error:", e);
1511
+ }).then(function() {
1512
+ self.markStreamingEnd();
1513
+ });
1514
+ };
1515
+ ChatStore.prototype.appendStreamData = function(clientMsgNo, data) {
1516
+ if (!clientMsgNo || !data) return;
1517
+ var messages = this._state.messages;
1518
+ var found = false;
1519
+ var updated = messages.map(function(m) {
620
1520
  if (m.clientMsgNo && m.clientMsgNo === clientMsgNo) {
621
- found = true
622
- return Object.assign({}, m, { streamData: (m.streamData || '') + data })
1521
+ found = true;
1522
+ return Object.assign({}, m, { streamData: (m.streamData || "") + data });
623
1523
  }
624
- return m
625
- })
626
-
1524
+ return m;
1525
+ });
627
1526
  if (!found) {
628
1527
  var placeholder = {
629
- id: 'stream-' + clientMsgNo,
630
- role: 'agent',
631
- payload: { type: 1, content: '' },
632
- time: new Date(),
633
- clientMsgNo: clientMsgNo,
1528
+ id: "stream-" + clientMsgNo,
1529
+ role: "agent",
1530
+ payload: { type: 1, content: "" },
1531
+ time: /* @__PURE__ */ new Date(),
1532
+ clientMsgNo,
634
1533
  streamData: data
635
- }
636
- updated = messages.concat([placeholder])
1534
+ };
1535
+ updated = messages.concat([placeholder]);
637
1536
  }
638
-
639
- this._setStateThrottled({ messages: updated })
640
-
1537
+ this._setStateThrottled({ messages: updated });
641
1538
  if (!this._state.isStreaming) {
642
- this.markStreamingStart(clientMsgNo)
1539
+ this.markStreamingStart(clientMsgNo);
643
1540
  }
644
- }
645
-
646
- ChatStore.prototype.appendMixedPart = function (clientMsgNo, part) {
647
- if (!clientMsgNo) return
648
-
649
- var messages = this._state.messages
650
- var found = false
651
- var updated = messages.map(function (m) {
1541
+ };
1542
+ ChatStore.prototype.appendMixedPart = function(clientMsgNo, part) {
1543
+ if (!clientMsgNo) return;
1544
+ var messages = this._state.messages;
1545
+ var found = false;
1546
+ var updated = messages.map(function(m) {
652
1547
  if (m.clientMsgNo && m.clientMsgNo === clientMsgNo) {
653
- found = true
654
- var parts = (m.uiParts || []).slice()
655
- // Merge consecutive text parts
656
- if (part.type === 'text' && parts.length > 0) {
657
- var last = parts[parts.length - 1]
658
- if (last.type === 'text') {
659
- parts[parts.length - 1] = { type: 'text', text: (last.text || '') + (part.text || '') }
660
- var textContent = ''
1548
+ found = true;
1549
+ var parts = (m.uiParts || []).slice();
1550
+ if (part.type === "text" && parts.length > 0) {
1551
+ var last = parts[parts.length - 1];
1552
+ if (last.type === "text") {
1553
+ parts[parts.length - 1] = { type: "text", text: (last.text || "") + (part.text || "") };
1554
+ var textContent = "";
661
1555
  for (var i = 0; i < parts.length; i++) {
662
- if (parts[i].type === 'text') textContent += parts[i].text || ''
1556
+ if (parts[i].type === "text") textContent += parts[i].text || "";
663
1557
  }
664
- return Object.assign({}, m, { uiParts: parts, streamData: textContent })
1558
+ return Object.assign({}, m, { uiParts: parts, streamData: textContent });
665
1559
  }
666
1560
  }
667
- parts.push(part)
668
- var tc = ''
1561
+ parts.push(part);
1562
+ var tc = "";
669
1563
  for (var j = 0; j < parts.length; j++) {
670
- if (parts[j].type === 'text') tc += parts[j].text || ''
1564
+ if (parts[j].type === "text") tc += parts[j].text || "";
671
1565
  }
672
- return Object.assign({}, m, { uiParts: parts, streamData: tc })
1566
+ return Object.assign({}, m, { uiParts: parts, streamData: tc });
673
1567
  }
674
- return m
675
- })
676
-
1568
+ return m;
1569
+ });
677
1570
  if (!found) {
678
- var initParts = [part]
1571
+ var initParts = [part];
679
1572
  var placeholder = {
680
- id: 'stream-' + clientMsgNo,
681
- role: 'agent',
682
- payload: { type: 1, content: '' },
683
- time: new Date(),
684
- clientMsgNo: clientMsgNo,
1573
+ id: "stream-" + clientMsgNo,
1574
+ role: "agent",
1575
+ payload: { type: 1, content: "" },
1576
+ time: /* @__PURE__ */ new Date(),
1577
+ clientMsgNo,
685
1578
  uiParts: initParts,
686
- streamData: part.type === 'text' ? (part.text || '') : ''
687
- }
688
- updated = messages.concat([placeholder])
1579
+ streamData: part.type === "text" ? part.text || "" : ""
1580
+ };
1581
+ updated = messages.concat([placeholder]);
689
1582
  }
690
-
691
- this._setStateThrottled({ messages: updated })
692
-
1583
+ this._setStateThrottled({ messages: updated });
693
1584
  if (!this._state.isStreaming) {
694
- this.markStreamingStart(clientMsgNo)
1585
+ this.markStreamingStart(clientMsgNo);
695
1586
  }
696
- }
697
-
698
- ChatStore.prototype.finalizeStreamMessage = function (clientMsgNo, errorMessage) {
699
- if (!clientMsgNo) return
700
-
701
- var messages = this._state.messages.map(function (m) {
1587
+ };
1588
+ ChatStore.prototype.finalizeStreamMessage = function(clientMsgNo, errorMessage) {
1589
+ if (!clientMsgNo) return;
1590
+ var messages = this._state.messages.map(function(m) {
702
1591
  if (m.clientMsgNo && m.clientMsgNo === clientMsgNo) {
703
- var finalPayload = m.streamData
704
- ? { type: 1, content: m.streamData }
705
- : m.payload
1592
+ var finalPayload = m.streamData ? { type: 1, content: m.streamData } : m.payload;
706
1593
  var result = Object.assign({}, m, {
707
1594
  payload: finalPayload,
708
- streamData: undefined,
709
- errorMessage: errorMessage || undefined
710
- })
711
- // Preserve uiParts for json-render
712
- if (m.uiParts) result.uiParts = m.uiParts
713
- return result
1595
+ streamData: void 0,
1596
+ errorMessage: errorMessage || void 0
1597
+ });
1598
+ if (m.uiParts) result.uiParts = m.uiParts;
1599
+ return result;
714
1600
  }
715
- return m
716
- })
717
-
718
- this._setState({ messages: messages })
719
-
1601
+ return m;
1602
+ });
1603
+ this._setState({ messages });
720
1604
  if (this._state.streamingClientMsgNo === clientMsgNo) {
721
- this.markStreamingEnd()
1605
+ this.markStreamingEnd();
722
1606
  }
723
- }
724
-
725
- ChatStore.prototype.ensureWelcomeMessage = function (text) {
726
- var t = (text || '').trim()
727
- if (!t) return
728
-
729
- var messages = this._state.messages
730
- var idx = -1
1607
+ };
1608
+ ChatStore.prototype.ensureWelcomeMessage = function(text) {
1609
+ var t = (text || "").trim();
1610
+ if (!t) return;
1611
+ var messages = this._state.messages;
1612
+ var idx = -1;
731
1613
  for (var i = 0; i < messages.length; i++) {
732
- if (messages[i].id === 'welcome') { idx = i; break }
1614
+ if (messages[i].id === "welcome") {
1615
+ idx = i;
1616
+ break;
1617
+ }
733
1618
  }
734
-
735
1619
  if (idx >= 0) {
736
- var next = messages.slice()
737
- next[idx] = Object.assign({}, messages[idx], { payload: { type: 1, content: t } })
738
- this._setState({ messages: next })
1620
+ var next = messages.slice();
1621
+ next[idx] = Object.assign({}, messages[idx], { payload: { type: 1, content: t } });
1622
+ this._setState({ messages: next });
739
1623
  } else {
740
1624
  var welcome = {
741
- id: 'welcome',
742
- role: 'agent',
1625
+ id: "welcome",
1626
+ role: "agent",
743
1627
  payload: { type: 1, content: t },
744
- time: new Date()
1628
+ time: /* @__PURE__ */ new Date()
1629
+ };
1630
+ this._setState({ messages: [welcome].concat(messages) });
1631
+ }
1632
+ };
1633
+ ChatStore.prototype.disconnect = function() {
1634
+ if (offMsg) {
1635
+ try {
1636
+ offMsg();
1637
+ } catch (e) {
745
1638
  }
746
- this._setState({ messages: [welcome].concat(messages) })
1639
+ ;
1640
+ offMsg = null;
747
1641
  }
748
- }
749
-
750
- ChatStore.prototype.disconnect = function () {
751
- if (offMsg) { try { offMsg() } catch (e) {} ; offMsg = null }
752
- if (offStatus) { try { offStatus() } catch (e) {} ; offStatus = null }
753
- if (offCustom) { try { offCustom() } catch (e) {} ; offCustom = null }
754
- this.markStreamingEnd()
755
- IMService.disconnect()
756
- }
757
-
758
- module.exports = new ChatStore()
1642
+ if (offStatus) {
1643
+ try {
1644
+ offStatus();
1645
+ } catch (e) {
1646
+ }
1647
+ ;
1648
+ offStatus = null;
1649
+ }
1650
+ if (offCustom) {
1651
+ try {
1652
+ offCustom();
1653
+ } catch (e) {
1654
+ }
1655
+ ;
1656
+ offCustom = null;
1657
+ }
1658
+ this.markStreamingEnd();
1659
+ IMService.disconnect();
1660
+ };
1661
+ module.exports = new ChatStore();