@prur/dsh-chat-service 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/events.d.ts +2 -0
- package/lib/events.js +12 -2
- package/lib/index.js +5 -2
- package/package.json +2 -2
package/lib/events.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type ChatDownlinkEvent = 'chat/message' | 'chat/chunk' | 'chat/status';
|
|
|
14
14
|
/** Cross-plugin cordis event emitted when a chat turn completes (B4 E2E push hook). */
|
|
15
15
|
export interface ChatTurnEndEvent {
|
|
16
16
|
conversationId: string;
|
|
17
|
+
/** Optional conversation title so consumers (push-bridge) can name the wake-up push. */
|
|
18
|
+
title?: string;
|
|
17
19
|
}
|
|
18
20
|
declare module '@deepseek-ai/cordis' {
|
|
19
21
|
interface Events {
|
package/lib/events.js
CHANGED
|
@@ -15,6 +15,8 @@ import WebSocket, { WebSocketServer } from 'ws';
|
|
|
15
15
|
export const CHAT_EVENTS_PATH = '/chat/events';
|
|
16
16
|
/** Heartbeat interval; keeps proxies from dropping an idle downlink. */
|
|
17
17
|
const HEARTBEAT_INTERVAL_MS = 15_000;
|
|
18
|
+
/** /chat/events 下行背压水位:客户端 ws `bufferedAmount` 超过该值视为慢性慢消费者,断开让其重连 + 历史基线回填自愈。 */
|
|
19
|
+
const CHAT_DOWNLINK_BACKPRESSURE_BYTES = 16 * 1024 * 1024;
|
|
18
20
|
/**
|
|
19
21
|
* In-process event bus. The service publishes; the gateway subscribes and
|
|
20
22
|
* broadcasts to every connected client. Synchronous, listener failures are
|
|
@@ -82,8 +84,16 @@ export class ChatEventsGateway {
|
|
|
82
84
|
broadcast(frame) {
|
|
83
85
|
const payload = JSON.stringify(frame);
|
|
84
86
|
for (const client of this.clients) {
|
|
85
|
-
if (client.readyState
|
|
86
|
-
|
|
87
|
+
if (client.readyState !== WebSocket.OPEN)
|
|
88
|
+
continue;
|
|
89
|
+
// 慢消费者背压:ws send 缓冲区(bufferedAmount)无界增长会令宿主进程内存滞留到 OOM
|
|
90
|
+
// (手机经中继弱网消费慢)。超过水位即断开该客户端——其重连后经 chat/history 尾页基线
|
|
91
|
+
// + chat/status 快照回填自愈,不因积压把宿主进程拖垮。
|
|
92
|
+
if (client.bufferedAmount > CHAT_DOWNLINK_BACKPRESSURE_BYTES) {
|
|
93
|
+
client.terminate();
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
client.send(payload);
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
99
|
handleUpgrade(req, socket, head) {
|
package/lib/index.js
CHANGED
|
@@ -569,9 +569,12 @@ let ChatService = (() => {
|
|
|
569
569
|
this.bus.publish('chat/status', [conversationId, status]);
|
|
570
570
|
// B4 E2E: on a real turn completion (running→false, not user-aborted), broadcast a
|
|
571
571
|
// cross-plugin cordis event so the push-bridge can emit a wake-up push carrying the
|
|
572
|
-
// conversationId (client routes to the Chat surface).
|
|
572
|
+
// conversationId (client routes to the Chat surface). Carry the conversation title
|
|
573
|
+
// (best-effort; a missing record falls back to no title) so the push names it.
|
|
573
574
|
if (status.running === false && status.reason !== 'aborted') {
|
|
574
|
-
this.
|
|
575
|
+
void this.store.require(conversationId)
|
|
576
|
+
.then(record => this._ctx.emit('chat/turn-end', { conversationId, title: record.title ?? undefined }))
|
|
577
|
+
.catch(() => this._ctx.emit('chat/turn-end', { conversationId }));
|
|
575
578
|
}
|
|
576
579
|
}
|
|
577
580
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prur/dsh-chat-service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Typert Remote namespace exposing a plain streaming model chat (no agent loop) to DSH Mobile clients",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
36
|
"ws": "^8.21.0",
|
|
37
37
|
"zod": "^4.4.3",
|
|
38
|
-
"@prur/dsh-client-connection-mobile": "^0.
|
|
38
|
+
"@prur/dsh-client-connection-mobile": "^0.4.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@deepseek-ai/cordis": "^4.0.1",
|