@deltakit/react 0.2.0 → 0.2.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @deltakit/react
2
2
 
3
- React hook for building streaming chat UIs over Server-Sent Events (SSE). Manages the entire lifecycle -- state, network requests, SSE parsing, cancellation, and event handling -- in a single `useStreamChat` hook.
3
+ React hook for building streaming chat UIs with pluggable transport strategies. `useStreamChat` manages message state, event handling, loading state, and transport lifecycle for direct SSE, resumable/background SSE, and WebSocket chat backends.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ React hook for building streaming chat UIs over Server-Sent Events (SSE). Manage
8
8
  npm install @deltakit/react
9
9
  ```
10
10
 
11
- Requires React 18+ and a backend endpoint that streams SSE.
11
+ Requires React 18+.
12
12
 
13
13
  ## Quick Start
14
14
 
@@ -59,14 +59,17 @@ const {
59
59
  messages, // Message[] -- live-updating conversation
60
60
  isLoading, // boolean -- true while streaming
61
61
  error, // Error | null -- latest error
62
+ runId, // string | null -- resumable transport run id
62
63
  sendMessage, // (text: string) => void -- send and start streaming
63
- stop, // () => void -- abort current stream
64
+ stop, // () => void -- request cancellation if supported
64
65
  setMessages, // React setState -- direct state control
65
66
  } = useStreamChat({
66
- api: "/api/chat", // Required. SSE endpoint URL
67
+ api: "/api/chat", // Backward-compatible direct SSE shorthand
67
68
  initialMessages: [], // Pre-populate conversation (e.g. from DB)
68
69
  headers: {}, // Extra fetch headers (e.g. Authorization)
69
70
  body: {}, // Extra POST body fields
71
+ transport: "sse", // "sse" | "background-sse" | "websocket" | custom adapter
72
+ transportOptions: {}, // Grouped config for built-in transports
70
73
  onEvent: (event, helpers) => {}, // Custom event handler (replaces default)
71
74
  onFinish: (messages) => {}, // Stream ended
72
75
  onMessage: (message) => {}, // New message added
@@ -74,6 +77,115 @@ const {
74
77
  });
75
78
  ```
76
79
 
80
+ ### Transport Strategies
81
+
82
+ ### Direct SSE
83
+
84
+ Existing callers continue to work:
85
+
86
+ ```tsx
87
+ const chat = useStreamChat({
88
+ api: "/api/chat",
89
+ });
90
+ ```
91
+
92
+ Or use the grouped transport config:
93
+
94
+ ```tsx
95
+ const chat = useStreamChat({
96
+ transport: "sse",
97
+ transportOptions: {
98
+ sse: {
99
+ api: "/api/chat",
100
+ headers: { Authorization: "Bearer token" },
101
+ body: { conversationId: "demo" },
102
+ },
103
+ },
104
+ });
105
+ ```
106
+
107
+ ### Background / Resumable SSE
108
+
109
+ Use this when the backend starts a job first, then exposes a reconnectable SSE stream by `runId`.
110
+
111
+ ```tsx
112
+ const [activeRunId, setActiveRunId] = useState<string | null>(null);
113
+
114
+ const chat = useStreamChat({
115
+ transport: "background-sse",
116
+ transportOptions: {
117
+ backgroundSSE: {
118
+ startApi: "/api/chat/jobs",
119
+ eventsApi: (runId) => `/api/chat/jobs/${runId}/events`,
120
+ statusApi: (runId) => `/api/chat/jobs/${runId}`,
121
+ runId: activeRunId,
122
+ onRunIdChange: setActiveRunId,
123
+ },
124
+ },
125
+ });
126
+ ```
127
+
128
+ If the component unmounts, the local stream disconnects. When the user returns, provide the stored `runId` again and the hook can reconnect with `resume`.
129
+
130
+ ### WebSocket
131
+
132
+ Use this when the backend streams events over a socket instead of HTTP SSE.
133
+
134
+ ```tsx
135
+ type ChatEvent =
136
+ | { type: "text_delta"; delta: string }
137
+ | { type: "tool_call"; tool_name: string; argument: string; call_id?: string };
138
+
139
+ const chat = useStreamChat<ContentPart, ChatEvent>({
140
+ transport: "websocket",
141
+ transportOptions: {
142
+ websocket: {
143
+ url: "ws://localhost:8000/ws/chat",
144
+ body: { room: "demo" },
145
+ parseMessage: (data) => {
146
+ if (typeof data !== "string") return null;
147
+ return JSON.parse(data) as ChatEvent;
148
+ },
149
+ },
150
+ },
151
+ });
152
+ ```
153
+
154
+ ### Custom Transport Adapters
155
+
156
+ If your backend needs a different lifecycle, pass a custom `transport` object. The adapter only handles connection mechanics; the hook still owns message state, event helpers, loading state, and callbacks.
157
+
158
+ ```tsx
159
+ const chat = useStreamChat({
160
+ transport: {
161
+ start: ({ context, message }) => {
162
+ const socket = new WebSocket("ws://localhost:8000/ws/chat");
163
+
164
+ socket.onopen = () => {
165
+ context.ensureAssistantMessage();
166
+ socket.send(JSON.stringify({ message }));
167
+ };
168
+
169
+ socket.onmessage = (event) => {
170
+ context.emit(JSON.parse(event.data));
171
+ };
172
+
173
+ socket.onerror = () => {
174
+ context.fail(new Error("Socket error"));
175
+ };
176
+
177
+ socket.onclose = () => {
178
+ context.finish();
179
+ };
180
+
181
+ return {
182
+ close: () => socket.close(),
183
+ };
184
+ },
185
+ },
186
+ });
187
+ ```
188
+
77
189
  ### Event Helpers
78
190
 
79
191
  When using `onEvent`, you receive helpers for mutating message state during streaming: