@fluxyte/sdk 0.2.0 → 0.2.2
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 +75 -24
- package/dist/core/client.d.ts +1 -1
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +2 -2
- package/dist/core/client.js.map +1 -1
- package/dist/core/sse.d.ts +1 -1
- package/dist/core/sse.d.ts.map +1 -1
- package/dist/core/sse.js +64 -15
- package/dist/core/sse.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
# Fluxyte SDK (TypeScript)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Includes:
|
|
6
|
-
- HTTP client (fetch-based) with strong typing generated from OpenAPI
|
|
7
|
-
- Streaming (SSE) and non-streaming chat
|
|
8
|
-
- React provider + hooks
|
|
9
|
-
- Node and browser entrypoints
|
|
10
|
-
- Onboarding events and answer feedback
|
|
3
|
+
The official TypeScript SDK for the Fluxyte Onboarding AI API: a context-aware,
|
|
4
|
+
documentation-grounded assistant designed for onboarding and setup flows (not generic chat).
|
|
11
5
|
|
|
12
6
|
## Install
|
|
13
7
|
|
|
@@ -18,17 +12,34 @@ npm install @fluxyte/sdk
|
|
|
18
12
|
## Requirements
|
|
19
13
|
|
|
20
14
|
- Browser or Node.js 18+ (global `fetch` available)
|
|
21
|
-
- A
|
|
15
|
+
- A Fluxyte API key (sent as `X-API-Key`)
|
|
16
|
+
|
|
17
|
+
## Authentication (API Key)
|
|
18
|
+
|
|
19
|
+
Treat your API key like a password. Do not commit it to source control.
|
|
20
|
+
|
|
21
|
+
- Vite: `VITE_FLUXYTE_API_KEY=...`
|
|
22
|
+
- Next.js: `NEXT_PUBLIC_FLUXYTE_API_KEY=...` (only for client-safe keys)
|
|
23
|
+
- Server: `FLUXYTE_API_KEY=...`
|
|
22
24
|
|
|
23
|
-
##
|
|
25
|
+
## Choose An Entrypoint
|
|
26
|
+
|
|
27
|
+
The SDK ships multiple entrypoints, all with the same API surface:
|
|
28
|
+
|
|
29
|
+
- `@fluxyte/sdk/react` (React hooks + provider)
|
|
30
|
+
- `@fluxyte/sdk/node` (server-side; validates `fetch` availability)
|
|
31
|
+
- `@fluxyte/sdk/vanilla` (browser usage without React)
|
|
32
|
+
- `@fluxyte/sdk` (base exports)
|
|
33
|
+
|
|
34
|
+
## Create A Client (Node / Vanilla)
|
|
24
35
|
|
|
25
36
|
```ts
|
|
26
|
-
import { OnboardingAIClient } from "@fluxyte/sdk";
|
|
37
|
+
import { OnboardingAIClient } from "@fluxyte/sdk/node";
|
|
27
38
|
|
|
28
|
-
const client = new OnboardingAIClient(
|
|
39
|
+
const client = new OnboardingAIClient(process.env.FLUXYTE_API_KEY!);
|
|
29
40
|
```
|
|
30
41
|
|
|
31
|
-
##
|
|
42
|
+
## Chat Completions (Non-Streaming)
|
|
32
43
|
|
|
33
44
|
```ts
|
|
34
45
|
const res = await client.chat({
|
|
@@ -43,9 +54,23 @@ const res = await client.chat({
|
|
|
43
54
|
|
|
44
55
|
console.log(res.answerId);
|
|
45
56
|
console.log(res.reply);
|
|
57
|
+
console.log(res.confidence);
|
|
58
|
+
console.log(res.sources);
|
|
46
59
|
```
|
|
47
60
|
|
|
48
|
-
## Streaming
|
|
61
|
+
## Chat Completions (Streaming via SSE)
|
|
62
|
+
|
|
63
|
+
Streaming is useful when you want:
|
|
64
|
+
|
|
65
|
+
- live typing UX
|
|
66
|
+
- progressive rendering
|
|
67
|
+
- early access to `answerId` (for feedback)
|
|
68
|
+
|
|
69
|
+
Streaming lifecycle:
|
|
70
|
+
|
|
71
|
+
1. `meta` (contains `answerId`)
|
|
72
|
+
2. `delta` (partial text; one or more)
|
|
73
|
+
3. `done` (confidence, sources)
|
|
49
74
|
|
|
50
75
|
```ts
|
|
51
76
|
const stop = client.streamChat(
|
|
@@ -57,13 +82,35 @@ const stop = client.streamChat(
|
|
|
57
82
|
(event) => {
|
|
58
83
|
if (event.type === "meta") console.log("Answer ID:", event.answerId);
|
|
59
84
|
if (event.type === "delta") process.stdout.write(event.replyDelta);
|
|
60
|
-
if (event.type === "done")
|
|
85
|
+
if (event.type === "done") {
|
|
86
|
+
console.log("\nConfidence:", event.confidence);
|
|
87
|
+
console.log("Sources:", event.sources);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
(err) => {
|
|
91
|
+
// Optional: handle auth/network/server errors.
|
|
92
|
+
console.error("Streaming error:", err);
|
|
61
93
|
},
|
|
62
94
|
);
|
|
63
95
|
|
|
64
96
|
// stop() cancels streaming
|
|
65
97
|
```
|
|
66
98
|
|
|
99
|
+
## Context
|
|
100
|
+
|
|
101
|
+
Context is required for chat requests. Minimum shape:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
context: { product: string; userTarget: string }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Best practices:
|
|
108
|
+
|
|
109
|
+
- Use stable `product` identifiers
|
|
110
|
+
- Always pass `userTarget`
|
|
111
|
+
- Include `flowSlug` / `stepSlug` when available
|
|
112
|
+
- Treat context like application state (update it as the user moves)
|
|
113
|
+
|
|
67
114
|
## Onboarding Events
|
|
68
115
|
|
|
69
116
|
```ts
|
|
@@ -83,10 +130,11 @@ await client.sendEvent({
|
|
|
83
130
|
await client.submitFeedback({
|
|
84
131
|
answerId: "ans_7xk9p2m",
|
|
85
132
|
rating: "GOOD",
|
|
133
|
+
comment: "Clear explanation and actionable advice",
|
|
86
134
|
});
|
|
87
135
|
```
|
|
88
136
|
|
|
89
|
-
## React Usage
|
|
137
|
+
## React Usage (Recommended)
|
|
90
138
|
|
|
91
139
|
```tsx
|
|
92
140
|
import { OnboardingAIClient } from "@fluxyte/sdk";
|
|
@@ -103,7 +151,7 @@ export function App() {
|
|
|
103
151
|
}
|
|
104
152
|
```
|
|
105
153
|
|
|
106
|
-
### React
|
|
154
|
+
### React Hooks
|
|
107
155
|
|
|
108
156
|
```tsx
|
|
109
157
|
import { useChat } from "@fluxyte/sdk/react";
|
|
@@ -117,17 +165,20 @@ await send({
|
|
|
117
165
|
});
|
|
118
166
|
```
|
|
119
167
|
|
|
120
|
-
|
|
168
|
+
```tsx
|
|
169
|
+
import { useStreamingChat } from "@fluxyte/sdk/react";
|
|
170
|
+
|
|
171
|
+
const { text, answerId, confidence, streaming, start, stop } = useStreamingChat();
|
|
121
172
|
|
|
122
|
-
|
|
123
|
-
|
|
173
|
+
start({
|
|
174
|
+
message: "What's the next step?",
|
|
175
|
+
context: { product: "analytics", userTarget: "admin" },
|
|
176
|
+
});
|
|
124
177
|
```
|
|
125
178
|
|
|
126
|
-
##
|
|
179
|
+
## Multi-Product
|
|
127
180
|
|
|
128
|
-
|
|
129
|
-
import { OnboardingAIClient } from "@fluxyte/sdk/vanilla";
|
|
130
|
-
```
|
|
181
|
+
Use `context.product` to isolate multiple apps/products under one account (analytics, billing, alerts, etc).
|
|
131
182
|
|
|
132
183
|
## Error Handling
|
|
133
184
|
|
package/dist/core/client.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class OnboardingAIClient {
|
|
|
9
9
|
private readonly baseUrl;
|
|
10
10
|
constructor(apiKey: string);
|
|
11
11
|
chat(payload: ChatCompletionRequest): Promise<ChatCompletionResponse>;
|
|
12
|
-
streamChat(payload: Omit<ChatCompletionRequest, "stream">, onEvent: (event: ChatSSEEvent) => void): () => void;
|
|
12
|
+
streamChat(payload: Omit<ChatCompletionRequest, "stream">, onEvent: (event: ChatSSEEvent) => void, onError?: (err: Error) => void): () => void;
|
|
13
13
|
sendEvent(payload: OnboardingEventRequest): Promise<void>;
|
|
14
14
|
submitFeedback(payload: FeedbackRequest): Promise<void>;
|
|
15
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,KAAK,qBAAqB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC,CAAC;AAC5E,KAAK,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,wBAAwB,CAAC,CAAC;AAC9E,KAAK,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAChE,KAAK,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,wBAAwB,CAAC,CAAC;AAI9E,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;gBAEf,MAAM,EAAE,MAAM;IAErC,IAAI,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAc3E,UAAU,CACR,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,KAAK,qBAAqB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC,CAAC;AAC5E,KAAK,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,wBAAwB,CAAC,CAAC;AAC9E,KAAK,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAChE,KAAK,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,wBAAwB,CAAC,CAAC;AAI9E,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;gBAEf,MAAM,EAAE,MAAM;IAErC,IAAI,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAc3E,UAAU,CACR,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,EACtC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAC7B,MAAM,IAAI;IAUP,SAAS,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAY9D"}
|
package/dist/core/client.js
CHANGED
|
@@ -18,8 +18,8 @@ export class OnboardingAIClient {
|
|
|
18
18
|
await handleResponse(res);
|
|
19
19
|
return res.json();
|
|
20
20
|
}
|
|
21
|
-
streamChat(payload, onEvent) {
|
|
22
|
-
return streamSSE(`${this.baseUrl}/chat/completions`, this.apiKey, { ...payload, stream: true }, onEvent);
|
|
21
|
+
streamChat(payload, onEvent, onError) {
|
|
22
|
+
return streamSSE(`${this.baseUrl}/chat/completions`, this.apiKey, { ...payload, stream: true }, onEvent, onError);
|
|
23
23
|
}
|
|
24
24
|
async sendEvent(payload) {
|
|
25
25
|
const res = await fetch(`${this.baseUrl}/events`, {
|
package/dist/core/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAQrC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAEtD,MAAM,OAAO,kBAAkB;IAG7B,YAA6B,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QAF1B,YAAO,GAAG,gBAAgB,CAAC;IAEE,CAAC;IAE/C,KAAK,CAAC,IAAI,CAAC,OAA8B;QACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,mBAAmB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;SACpD,CAAC,CAAC;QAEH,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,UAAU,CACR,OAA8C,EAC9C,OAAsC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAQrC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAEtD,MAAM,OAAO,kBAAkB;IAG7B,YAA6B,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QAF1B,YAAO,GAAG,gBAAgB,CAAC;IAEE,CAAC;IAE/C,KAAK,CAAC,IAAI,CAAC,OAA8B;QACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,mBAAmB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;SACpD,CAAC,CAAC;QAEH,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,UAAU,CACR,OAA8C,EAC9C,OAAsC,EACtC,OAA8B;QAE9B,OAAO,SAAS,CACd,GAAG,IAAI,CAAC,OAAO,mBAAmB,EAClC,IAAI,CAAC,MAAM,EACX,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAC5B,OAAO,EACP,OAAO,CACR,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAA+B;QAC7C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,SAAS,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAwB;QAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;YAClD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;CACF"}
|
package/dist/core/sse.d.ts
CHANGED
|
@@ -13,6 +13,6 @@ export type ChatSSEEvent = {
|
|
|
13
13
|
kind?: AdminAIIntent;
|
|
14
14
|
sources?: EvidenceItem[];
|
|
15
15
|
};
|
|
16
|
-
export declare function streamSSE(url: string, apiKey: string, body: unknown, onEvent: (event: ChatSSEEvent) => void): () => void;
|
|
16
|
+
export declare function streamSSE(url: string, apiKey: string, body: unknown, onEvent: (event: ChatSSEEvent) => void, onError?: (err: Error) => void): () => void;
|
|
17
17
|
export {};
|
|
18
18
|
//# sourceMappingURL=sse.d.ts.map
|
package/dist/core/sse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/core/sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,KAAK,aAAa,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AAC5D,KAAK,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC;AAE1D,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACrC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B,CAAC;AAEN,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/core/sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,KAAK,aAAa,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AAC5D,KAAK,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC;AAE1D,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACrC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B,CAAC;AAEN,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,EACtC,OAAO,GAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAe,GACvC,MAAM,IAAI,CAuGZ"}
|
package/dist/core/sse.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export function streamSSE(url, apiKey, body, onEvent) {
|
|
1
|
+
export function streamSSE(url, apiKey, body, onEvent, onError = () => { }) {
|
|
2
2
|
const controller = new AbortController();
|
|
3
3
|
fetch(url, {
|
|
4
4
|
method: "POST",
|
|
5
5
|
headers: {
|
|
6
|
+
Accept: "text/event-stream",
|
|
6
7
|
"Content-Type": "application/json",
|
|
7
8
|
"X-API-Key": apiKey,
|
|
8
9
|
},
|
|
9
10
|
body: JSON.stringify(body),
|
|
10
11
|
signal: controller.signal,
|
|
11
|
-
})
|
|
12
|
+
})
|
|
13
|
+
.then(async (res) => {
|
|
12
14
|
if (!res.ok || !res.body) {
|
|
13
15
|
throw new Error(`SSE connection failed (${res.status})`);
|
|
14
16
|
}
|
|
@@ -17,30 +19,77 @@ export function streamSSE(url, apiKey, body, onEvent) {
|
|
|
17
19
|
let buffer = "";
|
|
18
20
|
while (true) {
|
|
19
21
|
const { done, value } = await reader.read();
|
|
20
|
-
if (done)
|
|
22
|
+
if (done || controller.signal.aborted)
|
|
21
23
|
break;
|
|
22
24
|
buffer += decoder.decode(value, { stream: true });
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
while (true) {
|
|
26
|
+
const lf = buffer.indexOf("\n\n");
|
|
27
|
+
const crlf = buffer.indexOf("\r\n\r\n");
|
|
28
|
+
let idx = -1;
|
|
29
|
+
let sepLen = 0;
|
|
30
|
+
if (lf !== -1 && (crlf === -1 || lf < crlf)) {
|
|
31
|
+
idx = lf;
|
|
32
|
+
sepLen = 2;
|
|
33
|
+
}
|
|
34
|
+
else if (crlf !== -1) {
|
|
35
|
+
idx = crlf;
|
|
36
|
+
sepLen = 4;
|
|
37
|
+
}
|
|
38
|
+
if (idx === -1)
|
|
39
|
+
break;
|
|
25
40
|
const frame = buffer.slice(0, idx);
|
|
26
|
-
buffer = buffer.slice(idx +
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
buffer = buffer.slice(idx + sepLen);
|
|
42
|
+
let eventName;
|
|
43
|
+
const dataLines = [];
|
|
44
|
+
for (const line of frame.split(/\r?\n/)) {
|
|
45
|
+
if (line.startsWith("event:")) {
|
|
46
|
+
eventName = line.slice("event:".length).trim();
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (line.startsWith("data:")) {
|
|
50
|
+
dataLines.push(line.slice("data:".length).replace(/^\s*/, ""));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
33
53
|
if (!dataLines.length)
|
|
34
54
|
continue;
|
|
55
|
+
if (eventName === "ping")
|
|
56
|
+
continue;
|
|
35
57
|
const data = dataLines.join("\n");
|
|
36
|
-
if (data === "[DONE]")
|
|
58
|
+
if (data === "[DONE]") {
|
|
37
59
|
return;
|
|
60
|
+
}
|
|
38
61
|
try {
|
|
39
|
-
|
|
62
|
+
const parsed = JSON.parse(data);
|
|
63
|
+
// Expected payloads already include `type`, per OpenAPI schema.
|
|
64
|
+
if (parsed && typeof parsed === "object" && "type" in parsed) {
|
|
65
|
+
onEvent(parsed);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// If the server uses SSE `event:` names instead of embedding `type`,
|
|
69
|
+
// normalize into our typed event union.
|
|
70
|
+
if (eventName === "meta" && parsed && typeof parsed === "object") {
|
|
71
|
+
onEvent({ type: "meta", ...parsed });
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (eventName === "delta" && parsed && typeof parsed === "object") {
|
|
75
|
+
onEvent({ type: "delta", ...parsed });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (eventName === "done" && parsed && typeof parsed === "object") {
|
|
79
|
+
onEvent({ type: "done", ...parsed });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// If parsing fails, ignore the frame (SSE can also include comments, etc).
|
|
40
85
|
}
|
|
41
|
-
catch { }
|
|
42
86
|
}
|
|
43
87
|
}
|
|
88
|
+
})
|
|
89
|
+
.catch((err) => {
|
|
90
|
+
if (controller.signal.aborted)
|
|
91
|
+
return;
|
|
92
|
+
onError(err instanceof Error ? err : new Error(String(err)));
|
|
44
93
|
});
|
|
45
94
|
return () => controller.abort();
|
|
46
95
|
}
|
package/dist/core/sse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/core/sse.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,SAAS,CACvB,GAAW,EACX,MAAc,EACd,IAAa,EACb,OAAsC;
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/core/sse.ts"],"names":[],"mappings":"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"}
|