chat-nest-sdk 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/index.js +55 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
# chat-nest-sdk
|
|
2
2
|
|
|
3
|
-
> Frontend SDK for Chat Nest providing a simple React hook to consume streaming AI APIs safely.
|
|
3
|
+
> Frontend SDK for Chat Nest providing a simple React hook to consume streaming AI APIs safely using Server-Side Events (SSE).
|
|
4
4
|
|
|
5
5
|
This package handles:
|
|
6
|
-
-
|
|
6
|
+
- Server-Side Events (SSE) streaming response handling
|
|
7
|
+
- Real-time token streaming via SSE protocol
|
|
7
8
|
- Cancellation propagation
|
|
8
9
|
- Intelligent retry behavior
|
|
9
10
|
- Error normalization
|
|
10
11
|
- Message state management
|
|
11
12
|
|
|
12
|
-
Designed for production usage in React applications.
|
|
13
|
+
Designed for production usage in React applications. Uses SSE for efficient, bidirectional communication with the backend.
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
16
17
|
## ✨ Features
|
|
17
18
|
|
|
18
|
-
-
|
|
19
|
+
- Server-Side Events (SSE) streaming protocol
|
|
20
|
+
- Real-time token streaming via SSE events
|
|
19
21
|
- Abort-safe cancellation
|
|
20
22
|
- Retry only on network / server failures
|
|
21
23
|
- No retries on client or policy errors
|
|
22
24
|
- Message state management
|
|
23
25
|
- Lightweight and framework-friendly
|
|
26
|
+
- Efficient SSE event parsing (`token`, `done`, `error`, `ping`, `start` events)
|
|
24
27
|
|
|
25
28
|
---
|
|
26
29
|
|
|
@@ -96,6 +99,8 @@ Cancel immediately stops streaming and billing.
|
|
|
96
99
|
|
|
97
100
|
Network failures retry automatically.
|
|
98
101
|
|
|
102
|
+
**Server-Side Events (SSE)**: The SDK communicates with the backend using the SSE protocol. The backend must send events in SSE format (`event: <type>\ndata: <data>\n\n`). Supported event types: `start`, `token`, `done`, `error`, `ping`.
|
|
103
|
+
|
|
99
104
|
---
|
|
100
105
|
|
|
101
106
|
## 📄 License
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,7 @@ var FetchAiClient = class {
|
|
|
54
54
|
() => this.abortController?.abort(),
|
|
55
55
|
this.config.timeoutMs
|
|
56
56
|
);
|
|
57
|
+
let completed = false;
|
|
57
58
|
try {
|
|
58
59
|
const response = await fetch(this.config.endpoint, {
|
|
59
60
|
method: "POST",
|
|
@@ -75,13 +76,64 @@ var FetchAiClient = class {
|
|
|
75
76
|
}
|
|
76
77
|
const reader = response.body.getReader();
|
|
77
78
|
const decoder = new TextDecoder();
|
|
79
|
+
let buffer = "";
|
|
78
80
|
while (true) {
|
|
81
|
+
if (this.abortController.signal.aborted) {
|
|
82
|
+
throw new DOMException("Aborted", "AbortError");
|
|
83
|
+
}
|
|
79
84
|
const { value, done } = await reader.read();
|
|
85
|
+
if (value) {
|
|
86
|
+
buffer += decoder.decode(value, { stream: true });
|
|
87
|
+
}
|
|
88
|
+
const events = buffer.split("\n\n");
|
|
89
|
+
buffer = events.pop() || "";
|
|
90
|
+
for (const eventText of events) {
|
|
91
|
+
if (!eventText.trim()) continue;
|
|
92
|
+
let eventType = "";
|
|
93
|
+
let eventDataParts = [];
|
|
94
|
+
for (const line of eventText.split("\n")) {
|
|
95
|
+
if (line.startsWith("event:")) {
|
|
96
|
+
eventType = line.substring(6).trim();
|
|
97
|
+
} else if (line.startsWith("data:")) {
|
|
98
|
+
eventDataParts.push(line.substring(5).trim());
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const eventData = eventDataParts.join("\n");
|
|
102
|
+
switch (eventType) {
|
|
103
|
+
case "token": {
|
|
104
|
+
try {
|
|
105
|
+
const token = JSON.parse(eventData);
|
|
106
|
+
callbacks.onToken(token);
|
|
107
|
+
} catch {
|
|
108
|
+
callbacks.onToken(eventData);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "done":
|
|
113
|
+
completed = true;
|
|
114
|
+
callbacks.onComplete();
|
|
115
|
+
return;
|
|
116
|
+
case "error":
|
|
117
|
+
completed = true;
|
|
118
|
+
try {
|
|
119
|
+
const errorObj = JSON.parse(eventData);
|
|
120
|
+
callbacks.onError(
|
|
121
|
+
new Error(errorObj.message || "Stream error")
|
|
122
|
+
);
|
|
123
|
+
} catch {
|
|
124
|
+
callbacks.onError(new Error(eventData || "Stream error"));
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
case "ping":
|
|
128
|
+
case "start":
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
80
132
|
if (done) break;
|
|
81
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
82
|
-
callbacks.onToken(chunk);
|
|
83
133
|
}
|
|
84
|
-
|
|
134
|
+
if (!completed) {
|
|
135
|
+
callbacks.onComplete();
|
|
136
|
+
}
|
|
85
137
|
} finally {
|
|
86
138
|
clearTimeout(timeoutId);
|
|
87
139
|
}
|
package/package.json
CHANGED