@surf-kit/agent 0.2.2 → 0.3.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/dist/chat/index.cjs +625 -204
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +11 -6
- package/dist/chat/index.d.ts +11 -6
- package/dist/chat/index.js +606 -185
- package/dist/chat/index.js.map +1 -1
- package/dist/{chat--OifhIRe.d.ts → chat-BIIDOGrD.d.ts} +10 -1
- package/dist/{chat-ChYl2XjV.d.cts → chat-CGamM7Mz.d.cts} +10 -1
- package/dist/{hooks-DLfF18IU.d.cts → hooks-B1NYoLLs.d.cts} +21 -5
- package/dist/{hooks-BGs8-4GK.d.ts → hooks-CTeEqnBQ.d.ts} +21 -5
- package/dist/hooks.cjs +126 -81
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +3 -3
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +126 -81
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +686 -265
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +645 -224
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.cjs +646 -225
- package/dist/layouts/index.cjs.map +1 -1
- package/dist/layouts/index.d.cts +1 -1
- package/dist/layouts/index.d.ts +1 -1
- package/dist/layouts/index.js +622 -201
- package/dist/layouts/index.js.map +1 -1
- package/dist/mcp/index.cjs +1 -1
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/response/index.cjs +66 -12
- package/dist/response/index.cjs.map +1 -1
- package/dist/response/index.d.cts +2 -2
- package/dist/response/index.d.ts +2 -2
- package/dist/response/index.js +64 -10
- package/dist/response/index.js.map +1 -1
- package/dist/sources/index.cjs +30 -1
- package/dist/sources/index.cjs.map +1 -1
- package/dist/sources/index.js +30 -1
- package/dist/sources/index.js.map +1 -1
- package/dist/streaming/index.cjs +202 -93
- package/dist/streaming/index.cjs.map +1 -1
- package/dist/streaming/index.d.cts +4 -3
- package/dist/streaming/index.d.ts +4 -3
- package/dist/streaming/index.js +172 -73
- package/dist/streaming/index.js.map +1 -1
- package/dist/{streaming-DbQxScpi.d.ts → streaming-Bx-ff2tt.d.ts} +1 -1
- package/dist/{streaming-DfT22A0z.d.cts → streaming-x7umFHoP.d.cts} +1 -1
- package/package.json +15 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ChatMessage, C as ChatError, b as ConversationSummary } from './chat
|
|
2
|
-
import { a as StreamState, S as StreamEvent } from './streaming-
|
|
1
|
+
import { A as Attachment, a as ChatMessage, C as ChatError, b as ConversationSummary } from './chat-BIIDOGrD.js';
|
|
2
|
+
import { a as StreamState, S as StreamEvent } from './streaming-Bx-ff2tt.js';
|
|
3
3
|
import { A as AgentInfo } from './agent-BNSmiexZ.js';
|
|
4
4
|
|
|
5
5
|
interface AgentChatConfig {
|
|
@@ -11,14 +11,29 @@ interface AgentChatConfig {
|
|
|
11
11
|
feedbackPath?: string;
|
|
12
12
|
/** Conversations endpoint path (appended to apiUrl) */
|
|
13
13
|
conversationsPath?: string;
|
|
14
|
-
/** Request headers (e.g. Authorization) */
|
|
15
|
-
headers?: Record<string, string
|
|
14
|
+
/** Request headers (e.g. Authorization). Can be a static object or an async function that returns headers (useful for refreshing auth tokens). */
|
|
15
|
+
headers?: Record<string, string> | (() => Promise<Record<string, string>>);
|
|
16
16
|
/** Request timeout in milliseconds */
|
|
17
17
|
timeout?: number;
|
|
18
18
|
/** Enable localStorage persistence for conversations */
|
|
19
19
|
persistConversations?: boolean;
|
|
20
20
|
/** Map of agent IDs to their display config */
|
|
21
21
|
agentThemes?: Record<string, AgentInfo>;
|
|
22
|
+
/** Extra fields merged into every request body (e.g. `{ agent: "research" }`).
|
|
23
|
+
* Keys here are shallow-merged after the default fields (message, conversation_id, attachments). */
|
|
24
|
+
bodyExtra?: Record<string, unknown>;
|
|
25
|
+
/** Custom stream reader for environments without ReadableStream (e.g. React Native).
|
|
26
|
+
* When provided, this function handles sending the request and parsing SSE events
|
|
27
|
+
* instead of the default fetch + getReader() approach. */
|
|
28
|
+
streamAdapter?: (url: string, options: {
|
|
29
|
+
method: string;
|
|
30
|
+
headers: Record<string, string>;
|
|
31
|
+
body: string;
|
|
32
|
+
signal: AbortSignal;
|
|
33
|
+
}, onEvent: (event: {
|
|
34
|
+
type: string;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}) => void) => Promise<void>;
|
|
22
37
|
}
|
|
23
38
|
|
|
24
39
|
interface AgentChatState {
|
|
@@ -29,9 +44,10 @@ interface AgentChatState {
|
|
|
29
44
|
inputValue: string;
|
|
30
45
|
streamPhase: StreamState['phase'];
|
|
31
46
|
streamingContent: string;
|
|
47
|
+
streamingAgent: string | null;
|
|
32
48
|
}
|
|
33
49
|
interface AgentChatActions {
|
|
34
|
-
sendMessage: (content: string) => Promise<void>;
|
|
50
|
+
sendMessage: (content: string, attachments?: Attachment[]) => Promise<void>;
|
|
35
51
|
setInputValue: (value: string) => void;
|
|
36
52
|
loadConversation: (conversationId: string, messages: ChatMessage[]) => void;
|
|
37
53
|
submitFeedback: (messageId: string, rating: 'positive' | 'negative', comment?: string) => Promise<void>;
|
package/dist/hooks.cjs
CHANGED
|
@@ -39,7 +39,8 @@ var initialState = {
|
|
|
39
39
|
error: null,
|
|
40
40
|
inputValue: "",
|
|
41
41
|
streamPhase: "idle",
|
|
42
|
-
streamingContent: ""
|
|
42
|
+
streamingContent: "",
|
|
43
|
+
streamingAgent: null
|
|
43
44
|
};
|
|
44
45
|
function reducer(state, action) {
|
|
45
46
|
switch (action.type) {
|
|
@@ -53,12 +54,15 @@ function reducer(state, action) {
|
|
|
53
54
|
error: null,
|
|
54
55
|
inputValue: "",
|
|
55
56
|
streamPhase: "thinking",
|
|
56
|
-
streamingContent: ""
|
|
57
|
+
streamingContent: "",
|
|
58
|
+
streamingAgent: null
|
|
57
59
|
};
|
|
58
60
|
case "STREAM_PHASE":
|
|
59
61
|
return { ...state, streamPhase: action.phase };
|
|
60
62
|
case "STREAM_CONTENT":
|
|
61
63
|
return { ...state, streamingContent: state.streamingContent + action.content };
|
|
64
|
+
case "STREAM_AGENT":
|
|
65
|
+
return { ...state, streamingAgent: action.agent };
|
|
62
66
|
case "SEND_SUCCESS":
|
|
63
67
|
return {
|
|
64
68
|
...state,
|
|
@@ -74,7 +78,8 @@ function reducer(state, action) {
|
|
|
74
78
|
isLoading: false,
|
|
75
79
|
error: action.error,
|
|
76
80
|
streamPhase: "idle",
|
|
77
|
-
streamingContent: ""
|
|
81
|
+
streamingContent: "",
|
|
82
|
+
streamingAgent: null
|
|
78
83
|
};
|
|
79
84
|
case "LOAD_CONVERSATION":
|
|
80
85
|
return {
|
|
@@ -100,107 +105,142 @@ function useAgentChat(config) {
|
|
|
100
105
|
const configRef = (0, import_react.useRef)(config);
|
|
101
106
|
configRef.current = config;
|
|
102
107
|
const lastUserMessageRef = (0, import_react.useRef)(null);
|
|
108
|
+
const lastUserAttachmentsRef = (0, import_react.useRef)(void 0);
|
|
103
109
|
const sendMessage = (0, import_react.useCallback)(
|
|
104
|
-
async (content) => {
|
|
105
|
-
const { apiUrl, streamPath = "/chat/stream", headers
|
|
110
|
+
async (content, attachments) => {
|
|
111
|
+
const { apiUrl, streamPath = "/chat/stream", headers: headersOrFn, timeout = 3e4, bodyExtra } = configRef.current;
|
|
112
|
+
const headers = typeof headersOrFn === "function" ? await headersOrFn() : headersOrFn ?? {};
|
|
106
113
|
lastUserMessageRef.current = content;
|
|
114
|
+
lastUserAttachmentsRef.current = attachments;
|
|
107
115
|
const userMessage = {
|
|
108
116
|
id: generateMessageId(),
|
|
109
117
|
role: "user",
|
|
110
118
|
content,
|
|
119
|
+
attachments,
|
|
111
120
|
timestamp: /* @__PURE__ */ new Date()
|
|
112
121
|
};
|
|
113
122
|
dispatch({ type: "SEND_START", message: userMessage });
|
|
114
123
|
const controller = new AbortController();
|
|
115
124
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
116
125
|
try {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
error: {
|
|
135
|
-
code: "API_ERROR",
|
|
136
|
-
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
137
|
-
retryable: response.status >= 500
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
126
|
+
const url = `${apiUrl}${streamPath}`;
|
|
127
|
+
const mergedHeaders = {
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
Accept: "text/event-stream",
|
|
130
|
+
...headers
|
|
131
|
+
};
|
|
132
|
+
const requestBody = {
|
|
133
|
+
message: content,
|
|
134
|
+
conversation_id: state.conversationId,
|
|
135
|
+
...bodyExtra
|
|
136
|
+
};
|
|
137
|
+
if (attachments && attachments.length > 0) {
|
|
138
|
+
requestBody.attachments = attachments.map((a) => ({
|
|
139
|
+
filename: a.filename,
|
|
140
|
+
content_type: a.content_type,
|
|
141
|
+
data: a.data
|
|
142
|
+
}));
|
|
141
143
|
}
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
const body = JSON.stringify(requestBody);
|
|
145
|
+
const ctx = {
|
|
146
|
+
accumulatedContent: "",
|
|
147
|
+
agentResponse: null,
|
|
148
|
+
capturedAgent: null,
|
|
149
|
+
capturedConversationId: null,
|
|
150
|
+
hadStreamError: false
|
|
151
|
+
};
|
|
152
|
+
const handleEvent = (event) => {
|
|
153
|
+
switch (event.type) {
|
|
154
|
+
case "agent":
|
|
155
|
+
ctx.capturedAgent = event.agent;
|
|
156
|
+
dispatch({ type: "STREAM_AGENT", agent: ctx.capturedAgent });
|
|
157
|
+
break;
|
|
158
|
+
case "phase":
|
|
159
|
+
dispatch({ type: "STREAM_PHASE", phase: event.phase });
|
|
160
|
+
break;
|
|
161
|
+
case "delta":
|
|
162
|
+
ctx.accumulatedContent += event.content;
|
|
163
|
+
dispatch({ type: "STREAM_CONTENT", content: event.content });
|
|
164
|
+
break;
|
|
165
|
+
case "done":
|
|
166
|
+
ctx.agentResponse = event.response;
|
|
167
|
+
ctx.capturedConversationId = event.conversation_id ?? null;
|
|
168
|
+
break;
|
|
169
|
+
case "error":
|
|
170
|
+
ctx.hadStreamError = true;
|
|
171
|
+
dispatch({ type: "SEND_ERROR", error: event.error });
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const { streamAdapter } = configRef.current;
|
|
176
|
+
if (streamAdapter) {
|
|
177
|
+
await streamAdapter(
|
|
178
|
+
url,
|
|
179
|
+
{ method: "POST", headers: mergedHeaders, body, signal: controller.signal },
|
|
180
|
+
handleEvent
|
|
181
|
+
);
|
|
182
|
+
clearTimeout(timeoutId);
|
|
183
|
+
} else {
|
|
184
|
+
const response = await fetch(url, {
|
|
185
|
+
method: "POST",
|
|
186
|
+
headers: mergedHeaders,
|
|
187
|
+
body,
|
|
188
|
+
signal: controller.signal
|
|
147
189
|
});
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
dispatch({ type: "SEND_ERROR", error: event.error });
|
|
185
|
-
return;
|
|
190
|
+
clearTimeout(timeoutId);
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
dispatch({
|
|
193
|
+
type: "SEND_ERROR",
|
|
194
|
+
error: {
|
|
195
|
+
code: "API_ERROR",
|
|
196
|
+
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
197
|
+
retryable: response.status >= 500
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const reader = response.body?.getReader();
|
|
203
|
+
if (!reader) {
|
|
204
|
+
dispatch({
|
|
205
|
+
type: "SEND_ERROR",
|
|
206
|
+
error: { code: "STREAM_ERROR", message: "No response body", retryable: true }
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const decoder = new TextDecoder();
|
|
211
|
+
let buffer = "";
|
|
212
|
+
while (true) {
|
|
213
|
+
const { done, value } = await reader.read();
|
|
214
|
+
if (done) break;
|
|
215
|
+
buffer += decoder.decode(value, { stream: true });
|
|
216
|
+
const lines = buffer.split("\n");
|
|
217
|
+
buffer = lines.pop() ?? "";
|
|
218
|
+
for (const line of lines) {
|
|
219
|
+
if (!line.startsWith("data: ")) continue;
|
|
220
|
+
const data = line.slice(6).trim();
|
|
221
|
+
if (data === "[DONE]") continue;
|
|
222
|
+
try {
|
|
223
|
+
const event = JSON.parse(data);
|
|
224
|
+
handleEvent(event);
|
|
225
|
+
} catch {
|
|
186
226
|
}
|
|
187
|
-
} catch {
|
|
188
227
|
}
|
|
189
228
|
}
|
|
190
229
|
}
|
|
230
|
+
if (ctx.hadStreamError) return;
|
|
191
231
|
const assistantMessage = {
|
|
192
232
|
id: generateMessageId(),
|
|
193
233
|
role: "assistant",
|
|
194
|
-
content: agentResponse?.message ?? accumulatedContent,
|
|
195
|
-
response: agentResponse ?? void 0,
|
|
196
|
-
agent: capturedAgent ?? void 0,
|
|
234
|
+
content: ctx.agentResponse?.message ?? ctx.accumulatedContent,
|
|
235
|
+
response: ctx.agentResponse ?? void 0,
|
|
236
|
+
agent: ctx.capturedAgent ?? void 0,
|
|
197
237
|
timestamp: /* @__PURE__ */ new Date()
|
|
198
238
|
};
|
|
199
239
|
dispatch({
|
|
200
240
|
type: "SEND_SUCCESS",
|
|
201
241
|
message: assistantMessage,
|
|
202
|
-
streamingContent: accumulatedContent,
|
|
203
|
-
conversationId: capturedConversationId
|
|
242
|
+
streamingContent: ctx.accumulatedContent,
|
|
243
|
+
conversationId: ctx.capturedConversationId
|
|
204
244
|
});
|
|
205
245
|
} catch (err) {
|
|
206
246
|
clearTimeout(timeoutId);
|
|
@@ -231,7 +271,8 @@ function useAgentChat(config) {
|
|
|
231
271
|
}, []);
|
|
232
272
|
const submitFeedback = (0, import_react.useCallback)(
|
|
233
273
|
async (messageId, rating, comment) => {
|
|
234
|
-
const { apiUrl, feedbackPath = "/feedback", headers
|
|
274
|
+
const { apiUrl, feedbackPath = "/feedback", headers: headersOrFn } = configRef.current;
|
|
275
|
+
const headers = typeof headersOrFn === "function" ? await headersOrFn() : headersOrFn ?? {};
|
|
235
276
|
await fetch(`${apiUrl}${feedbackPath}`, {
|
|
236
277
|
method: "POST",
|
|
237
278
|
headers: { "Content-Type": "application/json", ...headers },
|
|
@@ -242,12 +283,13 @@ function useAgentChat(config) {
|
|
|
242
283
|
);
|
|
243
284
|
const retry = (0, import_react.useCallback)(async () => {
|
|
244
285
|
if (lastUserMessageRef.current) {
|
|
245
|
-
await sendMessage(lastUserMessageRef.current);
|
|
286
|
+
await sendMessage(lastUserMessageRef.current, lastUserAttachmentsRef.current);
|
|
246
287
|
}
|
|
247
288
|
}, [sendMessage]);
|
|
248
289
|
const reset = (0, import_react.useCallback)(() => {
|
|
249
290
|
dispatch({ type: "RESET" });
|
|
250
291
|
lastUserMessageRef.current = null;
|
|
292
|
+
lastUserAttachmentsRef.current = void 0;
|
|
251
293
|
}, []);
|
|
252
294
|
const actions = {
|
|
253
295
|
sendMessage,
|
|
@@ -607,7 +649,10 @@ function useCharacterDrain(target, msPerChar = 15) {
|
|
|
607
649
|
const elapsed = now - lastTimeRef.current;
|
|
608
650
|
const charsToAdvance = Math.floor(elapsed / msPerCharRef.current);
|
|
609
651
|
if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {
|
|
610
|
-
|
|
652
|
+
let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
|
|
653
|
+
while (nextIndex < currentTarget.length && currentTarget[nextIndex - 1].trim() === "") {
|
|
654
|
+
nextIndex++;
|
|
655
|
+
}
|
|
611
656
|
indexRef.current = nextIndex;
|
|
612
657
|
lastTimeRef.current = now;
|
|
613
658
|
setDisplayed(currentTarget.slice(0, nextIndex));
|
package/dist/hooks.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks.ts","../src/hooks/useAgentChat.ts","../src/hooks/useStreaming.ts","../src/hooks/useConversation.ts","../src/hooks/useFeedback.ts","../src/hooks/useAgentTheme.ts","../src/hooks/useCharacterDrain.ts"],"sourcesContent":["export { useAgentChat } from './hooks/useAgentChat'\nexport type { AgentChatState, AgentChatActions } from './hooks/useAgentChat'\n\nexport { useStreaming } from './hooks/useStreaming'\nexport type { UseStreamingOptions } from './hooks/useStreaming'\n\nexport { useConversation } from './hooks/useConversation'\nexport type { Conversation, UseConversationOptions } from './hooks/useConversation'\n\nexport { useFeedback } from './hooks/useFeedback'\nexport type { FeedbackState, UseFeedbackOptions, FeedbackPayload } from './hooks/useFeedback'\n\nexport { useAgentTheme } from './hooks/useAgentTheme'\nexport type { AgentThemeResult } from './hooks/useAgentTheme'\n\nexport { useCharacterDrain } from './hooks/useCharacterDrain'\nexport type { CharacterDrainResult } from './hooks/useCharacterDrain'\n","'use client'\n\nimport { useReducer, useCallback, useRef } from 'react'\nimport type { ChatMessage, ChatError } from '../types/chat'\nimport type { AgentResponse } from '../types/agent'\nimport type { StreamState } from '../types/streaming'\nimport type { AgentChatConfig } from '../types/config'\n\n// ── State ──────────────────────────────────────────────────────────────\n\nexport interface AgentChatState {\n messages: ChatMessage[]\n conversationId: string | null\n isLoading: boolean\n error: ChatError | null\n inputValue: string\n streamPhase: StreamState['phase']\n streamingContent: string\n}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\n}\n\n// ── Actions ────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_INPUT'; value: string }\n | { type: 'SEND_START'; message: ChatMessage }\n | { type: 'STREAM_PHASE'; phase: StreamState['phase'] }\n | { type: 'STREAM_CONTENT'; content: string }\n | { type: 'SEND_SUCCESS'; message: ChatMessage; streamingContent: string; conversationId: string | null }\n | { type: 'SEND_ERROR'; error: ChatError }\n | { type: 'LOAD_CONVERSATION'; conversationId: string; messages: ChatMessage[] }\n | { type: 'RESET' }\n | { type: 'CLEAR_ERROR' }\n\nfunction reducer(state: AgentChatState, action: Action): AgentChatState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, inputValue: action.value }\n\n case 'SEND_START':\n return {\n ...state,\n messages: [...state.messages, action.message],\n isLoading: true,\n error: null,\n inputValue: '',\n streamPhase: 'thinking',\n streamingContent: '',\n }\n\n case 'STREAM_PHASE':\n return { ...state, streamPhase: action.phase }\n\n case 'STREAM_CONTENT':\n return { ...state, streamingContent: state.streamingContent + action.content }\n\n case 'SEND_SUCCESS':\n return {\n ...state,\n messages: [...state.messages, action.message],\n conversationId: action.conversationId ?? state.conversationId,\n isLoading: false,\n streamPhase: 'idle',\n streamingContent: '',\n }\n\n case 'SEND_ERROR':\n return {\n ...state,\n isLoading: false,\n error: action.error,\n streamPhase: 'idle',\n streamingContent: '',\n }\n\n case 'LOAD_CONVERSATION':\n return {\n ...state,\n conversationId: action.conversationId,\n messages: action.messages,\n error: null,\n }\n\n case 'RESET':\n return { ...initialState }\n\n case 'CLEAR_ERROR':\n return { ...state, error: null }\n\n default:\n return state\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────\n\nlet msgIdCounter = 0\nfunction generateMessageId(): string {\n return `msg-${Date.now()}-${++msgIdCounter}`\n}\n\nexport interface AgentChatActions {\n sendMessage: (content: string) => Promise<void>\n setInputValue: (value: string) => void\n loadConversation: (conversationId: string, messages: ChatMessage[]) => void\n submitFeedback: (messageId: string, rating: 'positive' | 'negative', comment?: string) => Promise<void>\n retry: () => Promise<void>\n reset: () => void\n}\n\nexport function useAgentChat(config: AgentChatConfig) {\n const [state, dispatch] = useReducer(reducer, initialState)\n const configRef = useRef(config)\n configRef.current = config\n const lastUserMessageRef = useRef<string | null>(null)\n\n const sendMessage = useCallback(\n async (content: string) => {\n const { apiUrl, streamPath = '/chat/stream', headers = {}, timeout = 30000 } = configRef.current\n\n lastUserMessageRef.current = content\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\n timestamp: new Date(),\n }\n\n dispatch({ type: 'SEND_START', message: userMessage })\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n try {\n const response = await fetch(`${apiUrl}${streamPath}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n },\n body: JSON.stringify({\n message: content,\n conversation_id: state.conversationId,\n }),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n })\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'STREAM_ERROR', message: 'No response body', retryable: true },\n })\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n let accumulatedContent = ''\n let agentResponse: AgentResponse | null = null\n let capturedAgent: string | null = null\n let capturedConversationId: string | null = null\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data)\n switch (event.type) {\n case 'agent':\n capturedAgent = event.agent as string\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase })\n break\n case 'delta':\n accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'done':\n agentResponse = event.response\n capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n dispatch({ type: 'SEND_ERROR', error: event.error })\n return\n }\n } catch {\n // Skip malformed events\n }\n }\n }\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: agentResponse?.message ?? accumulatedContent,\n response: agentResponse ?? undefined,\n agent: capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: accumulatedContent,\n conversationId: capturedConversationId,\n })\n } catch (err: unknown) {\n clearTimeout(timeoutId)\n if ((err as Error).name === 'AbortError') {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'TIMEOUT', message: 'Request timed out', retryable: true },\n })\n } else {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n })\n }\n }\n },\n [state.conversationId],\n )\n\n const setInputValue = useCallback((value: string) => {\n dispatch({ type: 'SET_INPUT', value })\n }, [])\n\n const loadConversation = useCallback((conversationId: string, messages: ChatMessage[]) => {\n dispatch({ type: 'LOAD_CONVERSATION', conversationId, messages })\n }, [])\n\n const submitFeedback = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n const { apiUrl, feedbackPath = '/feedback', headers = {} } = configRef.current\n await fetch(`${apiUrl}${feedbackPath}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({ messageId, rating, comment }),\n })\n },\n [],\n )\n\n const retry = useCallback(async () => {\n if (lastUserMessageRef.current) {\n await sendMessage(lastUserMessageRef.current)\n }\n }, [sendMessage])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\n }, [])\n\n const actions: AgentChatActions = {\n sendMessage,\n setInputValue,\n loadConversation,\n submitFeedback,\n retry,\n reset,\n }\n\n return { state, actions }\n}\n","'use client'\n\nimport { useState, useCallback, useRef, useEffect } from 'react'\nimport type { StreamEvent, StreamState } from '../types/streaming'\nimport type { Source } from '../types/agent'\n\nexport interface UseStreamingOptions {\n /** SSE endpoint URL */\n url: string\n /** Additional headers for fetch-based SSE (not used with native EventSource) */\n headers?: Record<string, string>\n /** Called when a complete response is received */\n onDone?: (event: Extract<StreamEvent, { type: 'done' }>) => void\n /** Called on error */\n onError?: (event: Extract<StreamEvent, { type: 'error' }>) => void\n}\n\nconst initialState: StreamState = {\n active: false,\n phase: 'idle',\n content: '',\n sources: [],\n agent: null,\n agentLabel: null,\n}\n\nexport function useStreaming(options: UseStreamingOptions) {\n const { url, headers, onDone, onError } = options\n const [state, setState] = useState<StreamState>(initialState)\n const abortRef = useRef<AbortController | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n const stop = useCallback(() => {\n if (abortRef.current) {\n abortRef.current.abort()\n abortRef.current = null\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n }, [])\n\n const start = useCallback(\n async (body: Record<string, unknown>) => {\n // Reset state\n setState({ ...initialState, active: true, phase: 'thinking' })\n\n const controller = new AbortController()\n abortRef.current = controller\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorEvent: StreamEvent = {\n type: 'error',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(errorEvent as Extract<StreamEvent, { type: 'error' }>)\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data) as StreamEvent\n processEvent(event, setState, optionsRef)\n } catch {\n // Skip malformed events\n }\n }\n }\n } catch (err: unknown) {\n if ((err as Error).name === 'AbortError') return\n const errorEvent: StreamEvent = {\n type: 'error',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(errorEvent as Extract<StreamEvent, { type: 'error' }>)\n }\n },\n [url, headers],\n )\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (abortRef.current) {\n abortRef.current.abort()\n }\n }\n }, [])\n\n return { state, start, stop }\n}\n\nfunction processEvent(\n event: StreamEvent,\n setState: React.Dispatch<React.SetStateAction<StreamState>>,\n optionsRef: React.MutableRefObject<UseStreamingOptions>,\n) {\n switch (event.type) {\n case 'phase':\n setState((prev) => ({ ...prev, phase: event.phase }))\n break\n case 'delta':\n setState((prev) => ({ ...prev, content: prev.content + event.content }))\n break\n case 'source':\n setState((prev) => ({ ...prev, sources: [...prev.sources, event.source] }))\n break\n case 'agent':\n setState((prev) => ({ ...prev, agent: event.agent }))\n break\n case 'done':\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onDone?.(event)\n break\n case 'error':\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(event)\n break\n }\n}\n","'use client'\n\nimport { useState, useCallback } from 'react'\nimport type { ChatMessage } from '../types/chat'\nimport type { ConversationSummary } from '../types/chat'\n\nexport interface Conversation {\n id: string\n title: string\n messages: ChatMessage[]\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface UseConversationOptions {\n /** Enable localStorage persistence */\n persist?: boolean\n /** localStorage key prefix */\n storageKey?: string\n}\n\nconst STORAGE_PREFIX = 'surf-kit-conversations'\n\nfunction getStorageKey(prefix: string) {\n return `${prefix}:list`\n}\n\nfunction loadFromStorage(storageKey: string): Conversation[] {\n if (typeof window === 'undefined') return []\n try {\n const raw = window.localStorage.getItem(getStorageKey(storageKey))\n if (!raw) return []\n const parsed = JSON.parse(raw) as Array<Conversation & { createdAt: string; updatedAt: string }>\n return parsed.map((c) => ({\n ...c,\n createdAt: new Date(c.createdAt),\n updatedAt: new Date(c.updatedAt),\n messages: c.messages.map((m) => ({ ...m, timestamp: new Date(m.timestamp as unknown as string) })),\n }))\n } catch {\n return []\n }\n}\n\nfunction saveToStorage(storageKey: string, conversations: Conversation[]) {\n if (typeof window === 'undefined') return\n try {\n window.localStorage.setItem(getStorageKey(storageKey), JSON.stringify(conversations))\n } catch {\n // Storage full or unavailable\n }\n}\n\nlet idCounter = 0\nfunction generateId(): string {\n return `conv-${Date.now()}-${++idCounter}`\n}\n\nexport function useConversation(options: UseConversationOptions = {}) {\n const { persist = false, storageKey = STORAGE_PREFIX } = options\n\n const [conversations, setConversations] = useState<Conversation[]>(() =>\n persist ? loadFromStorage(storageKey) : [],\n )\n const [current, setCurrent] = useState<Conversation | null>(null)\n\n const persistIfNeeded = useCallback(\n (convs: Conversation[]) => {\n if (persist) saveToStorage(storageKey, convs)\n },\n [persist, storageKey],\n )\n\n const create = useCallback(\n (title?: string): Conversation => {\n const now = new Date()\n const conv: Conversation = {\n id: generateId(),\n title: title ?? 'New Conversation',\n messages: [],\n createdAt: now,\n updatedAt: now,\n }\n setConversations((prev) => {\n const next = [conv, ...prev]\n persistIfNeeded(next)\n return next\n })\n setCurrent(conv)\n return conv\n },\n [persistIfNeeded],\n )\n\n const list = useCallback((): ConversationSummary[] => {\n return conversations.map((c) => ({\n id: c.id,\n title: c.title,\n lastMessage: c.messages.length > 0 ? c.messages[c.messages.length - 1].content : '',\n updatedAt: c.updatedAt,\n messageCount: c.messages.length,\n }))\n }, [conversations])\n\n const load = useCallback(\n (id: string): Conversation | null => {\n const conv = conversations.find((c) => c.id === id) ?? null\n setCurrent(conv)\n return conv\n },\n [conversations],\n )\n\n const remove = useCallback(\n (id: string) => {\n setConversations((prev) => {\n const next = prev.filter((c) => c.id !== id)\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) => (prev?.id === id ? null : prev))\n },\n [persistIfNeeded],\n )\n\n const rename = useCallback(\n (id: string, title: string) => {\n setConversations((prev) => {\n const next = prev.map((c) => (c.id === id ? { ...c, title, updatedAt: new Date() } : c))\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) => (prev?.id === id ? { ...prev, title, updatedAt: new Date() } : prev))\n },\n [persistIfNeeded],\n )\n\n const addMessage = useCallback(\n (conversationId: string, message: ChatMessage) => {\n setConversations((prev) => {\n const next = prev.map((c) =>\n c.id === conversationId\n ? { ...c, messages: [...c.messages, message], updatedAt: new Date() }\n : c,\n )\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) =>\n prev?.id === conversationId\n ? { ...prev, messages: [...prev.messages, message], updatedAt: new Date() }\n : prev,\n )\n },\n [persistIfNeeded],\n )\n\n return {\n conversations,\n current,\n create,\n list,\n load,\n delete: remove,\n rename,\n addMessage,\n }\n}\n","'use client'\n\nimport { useState, useCallback, useRef } from 'react'\n\nexport type FeedbackState = 'idle' | 'submitting' | 'submitted' | 'error'\n\nexport interface UseFeedbackOptions {\n /** API endpoint URL for feedback submission */\n url: string\n /** Additional request headers */\n headers?: Record<string, string>\n}\n\nexport interface FeedbackPayload {\n messageId: string\n rating: 'positive' | 'negative'\n comment?: string\n}\n\nexport function useFeedback(options: UseFeedbackOptions) {\n const { url, headers } = options\n const [state, setState] = useState<FeedbackState>('idle')\n const [error, setError] = useState<string | null>(null)\n const abortRef = useRef<AbortController | null>(null)\n\n const submit = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n setState('submitting')\n setError(null)\n\n const controller = new AbortController()\n abortRef.current = controller\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ messageId, rating, comment }),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n setState('submitted')\n } catch (err: unknown) {\n if ((err as Error).name === 'AbortError') return\n setError((err as Error).message ?? 'Failed to submit feedback')\n setState('error')\n }\n },\n [url, headers],\n )\n\n const reset = useCallback(() => {\n setState('idle')\n setError(null)\n }, [])\n\n return { state, error, submit, reset }\n}\n","'use client'\n\nimport { useMemo } from 'react'\nimport type { AgentInfo } from '../types/agent'\n\nexport interface AgentThemeResult {\n accent: string\n icon: AgentInfo['icon'] | null\n label: string\n}\n\nconst DEFAULT_ACCENT = '#6366f1'\nconst DEFAULT_LABEL = 'Agent'\n\nexport function useAgentTheme(\n agentId: string | null | undefined,\n agentThemes?: Record<string, AgentInfo>,\n): AgentThemeResult {\n return useMemo(() => {\n if (!agentId) {\n return { accent: DEFAULT_ACCENT, icon: null, label: DEFAULT_LABEL }\n }\n\n const theme = agentThemes?.[agentId]\n if (!theme) {\n return { accent: DEFAULT_ACCENT, icon: null, label: agentId }\n }\n\n return {\n accent: theme.accent ?? DEFAULT_ACCENT,\n icon: theme.icon ?? null,\n label: theme.label,\n }\n }, [agentId, agentThemes])\n}\n","'use client'\n\nimport { useState, useRef, useEffect } from 'react'\n\nexport interface CharacterDrainResult {\n displayed: string\n isDraining: boolean\n}\n\n/**\n * Smoothly drains a growing `target` string character-by-character using\n * `requestAnimationFrame`, decoupling visual rendering from network packet\n * timing so text appears to type out instead of arriving in chunks.\n *\n * When `target` resets to empty (e.g. stream finished), the hook continues\n * draining the previous content to completion before resetting, so the\n * typing animation isn't cut short.\n *\n * Design: the RAF loop is long-lived — it does NOT restart on every delta.\n * The tick function is stored in a ref (updated each render) so the loop\n * always reads the latest drainTarget without being cancelled/restarted.\n * A separate kick-start effect re-fires the loop when it was idle and new\n * content arrives.\n */\nexport function useCharacterDrain(target: string, msPerChar = 15): CharacterDrainResult {\n const [displayed, setDisplayed] = useState('')\n const indexRef = useRef(0)\n const lastTimeRef = useRef(0)\n const rafRef = useRef<number | null>(null)\n // Holds the last non-empty target so we can finish draining after source resets\n const drainTargetRef = useRef('')\n const msPerCharRef = useRef(msPerChar)\n\n msPerCharRef.current = msPerChar\n\n // Update drain target when new content arrives; preserve old value on reset\n if (target !== '') {\n drainTargetRef.current = target\n }\n\n const drainTarget = drainTargetRef.current\n const isDraining = displayed.length < drainTarget.length\n\n // Tick function stored in ref so the long-lived RAF loop always reads the\n // latest drainTarget and msPerChar without being cancelled/recreated.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const tickRef = useRef<(now: number) => void>(() => {})\n tickRef.current = (now: number) => {\n const currentTarget = drainTargetRef.current\n if (currentTarget === '') {\n rafRef.current = null\n return\n }\n\n if (lastTimeRef.current === 0) lastTimeRef.current = now\n const elapsed = now - lastTimeRef.current\n const charsToAdvance = Math.floor(elapsed / msPerCharRef.current)\n\n if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {\n const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\n indexRef.current = nextIndex\n lastTimeRef.current = now\n setDisplayed(currentTarget.slice(0, nextIndex))\n }\n\n if (indexRef.current < currentTarget.length) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n } else {\n rafRef.current = null\n }\n }\n\n // Kick-start the RAF loop when new content arrives and the loop is idle.\n // No cleanup here — we intentionally do NOT cancel the running loop when\n // drainTarget grows; the long-lived tick will pick up new chars automatically.\n useEffect(() => {\n if (\n drainTargetRef.current !== '' &&\n indexRef.current < drainTargetRef.current.length &&\n rafRef.current === null\n ) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n }\n }, [drainTarget]) // drainTarget change = new content; check if loop needs kicking\n\n // Once drain completes and source stream is already done, reset all state\n useEffect(() => {\n if (target === '' && !isDraining && displayed !== '') {\n indexRef.current = 0\n lastTimeRef.current = 0\n drainTargetRef.current = ''\n setDisplayed('')\n }\n }, [target, isDraining, displayed])\n\n // Cancel any pending RAF on unmount\n useEffect(() => {\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n }\n }, [])\n\n return { displayed, isDraining }\n}\n"],"mappings":"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","names":["import_react","initialState","import_react","import_react","import_react","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks.ts","../src/hooks/useAgentChat.ts","../src/hooks/useStreaming.ts","../src/hooks/useConversation.ts","../src/hooks/useFeedback.ts","../src/hooks/useAgentTheme.ts","../src/hooks/useCharacterDrain.ts"],"sourcesContent":["export { useAgentChat } from './hooks/useAgentChat'\nexport type { AgentChatState, AgentChatActions } from './hooks/useAgentChat'\n\nexport { useStreaming } from './hooks/useStreaming'\nexport type { UseStreamingOptions } from './hooks/useStreaming'\n\nexport { useConversation } from './hooks/useConversation'\nexport type { Conversation, UseConversationOptions } from './hooks/useConversation'\n\nexport { useFeedback } from './hooks/useFeedback'\nexport type { FeedbackState, UseFeedbackOptions, FeedbackPayload } from './hooks/useFeedback'\n\nexport { useAgentTheme } from './hooks/useAgentTheme'\nexport type { AgentThemeResult } from './hooks/useAgentTheme'\n\nexport { useCharacterDrain } from './hooks/useCharacterDrain'\nexport type { CharacterDrainResult } from './hooks/useCharacterDrain'\n","'use client'\n\nimport { useReducer, useCallback, useRef } from 'react'\nimport type { ChatMessage, ChatError, Attachment } from '../types/chat'\nimport type { AgentResponse } from '../types/agent'\nimport type { StreamState } from '../types/streaming'\nimport type { AgentChatConfig } from '../types/config'\n\n// ── State ──────────────────────────────────────────────────────────────\n\nexport interface AgentChatState {\n messages: ChatMessage[]\n conversationId: string | null\n isLoading: boolean\n error: ChatError | null\n inputValue: string\n streamPhase: StreamState['phase']\n streamingContent: string\n streamingAgent: string | null\n}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n}\n\n// ── Actions ────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_INPUT'; value: string }\n | { type: 'SEND_START'; message: ChatMessage }\n | { type: 'STREAM_PHASE'; phase: StreamState['phase'] }\n | { type: 'STREAM_CONTENT'; content: string }\n | { type: 'STREAM_AGENT'; agent: string }\n | { type: 'SEND_SUCCESS'; message: ChatMessage; streamingContent: string; conversationId: string | null }\n | { type: 'SEND_ERROR'; error: ChatError }\n | { type: 'LOAD_CONVERSATION'; conversationId: string; messages: ChatMessage[] }\n | { type: 'RESET' }\n | { type: 'CLEAR_ERROR' }\n\nfunction reducer(state: AgentChatState, action: Action): AgentChatState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, inputValue: action.value }\n\n case 'SEND_START':\n return {\n ...state,\n messages: [...state.messages, action.message],\n isLoading: true,\n error: null,\n inputValue: '',\n streamPhase: 'thinking',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'STREAM_PHASE':\n return { ...state, streamPhase: action.phase }\n\n case 'STREAM_CONTENT':\n return { ...state, streamingContent: state.streamingContent + action.content }\n\n case 'STREAM_AGENT':\n return { ...state, streamingAgent: action.agent }\n\n case 'SEND_SUCCESS':\n return {\n ...state,\n messages: [...state.messages, action.message],\n conversationId: action.conversationId ?? state.conversationId,\n isLoading: false,\n streamPhase: 'idle',\n streamingContent: '',\n }\n\n case 'SEND_ERROR':\n return {\n ...state,\n isLoading: false,\n error: action.error,\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'LOAD_CONVERSATION':\n return {\n ...state,\n conversationId: action.conversationId,\n messages: action.messages,\n error: null,\n }\n\n case 'RESET':\n return { ...initialState }\n\n case 'CLEAR_ERROR':\n return { ...state, error: null }\n\n default:\n return state\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────\n\nlet msgIdCounter = 0\nfunction generateMessageId(): string {\n return `msg-${Date.now()}-${++msgIdCounter}`\n}\n\nexport interface AgentChatActions {\n sendMessage: (content: string, attachments?: Attachment[]) => Promise<void>\n setInputValue: (value: string) => void\n loadConversation: (conversationId: string, messages: ChatMessage[]) => void\n submitFeedback: (messageId: string, rating: 'positive' | 'negative', comment?: string) => Promise<void>\n retry: () => Promise<void>\n reset: () => void\n}\n\nexport function useAgentChat(config: AgentChatConfig) {\n const [state, dispatch] = useReducer(reducer, initialState)\n const configRef = useRef(config)\n configRef.current = config\n const lastUserMessageRef = useRef<string | null>(null)\n const lastUserAttachmentsRef = useRef<Attachment[] | undefined>(undefined)\n\n const sendMessage = useCallback(\n async (content: string, attachments?: Attachment[]) => {\n const { apiUrl, streamPath = '/chat/stream', headers: headersOrFn, timeout = 30000, bodyExtra } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n\n lastUserMessageRef.current = content\n lastUserAttachmentsRef.current = attachments\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\n attachments,\n timestamp: new Date(),\n }\n\n dispatch({ type: 'SEND_START', message: userMessage })\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n try {\n const url = `${apiUrl}${streamPath}`\n const mergedHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n }\n\n // Build request body — include attachments if present\n const requestBody: Record<string, unknown> = {\n message: content,\n conversation_id: state.conversationId,\n ...bodyExtra,\n }\n if (attachments && attachments.length > 0) {\n requestBody.attachments = attachments.map(a => ({\n filename: a.filename,\n content_type: a.content_type,\n data: a.data,\n }))\n }\n const body = JSON.stringify(requestBody)\n\n // These variables are mutated inside handleEvent (called from async stream processing).\n // TypeScript can't track mutations through closures, so we use a mutable context object.\n const ctx = {\n accumulatedContent: '',\n agentResponse: null as AgentResponse | null,\n capturedAgent: null as string | null,\n capturedConversationId: null as string | null,\n hadStreamError: false,\n }\n\n // Shared handler for parsed SSE events (used by both adapter and default paths)\n const handleEvent = (event: { type: string; [key: string]: unknown }) => {\n switch (event.type) {\n case 'agent':\n ctx.capturedAgent = event.agent as string\n dispatch({ type: 'STREAM_AGENT', agent: ctx.capturedAgent })\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase as StreamState['phase'] })\n break\n case 'delta':\n ctx.accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'done':\n ctx.agentResponse = event.response as AgentResponse\n ctx.capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n ctx.hadStreamError = true\n dispatch({ type: 'SEND_ERROR', error: event.error as ChatError })\n break\n }\n }\n\n const { streamAdapter } = configRef.current\n\n if (streamAdapter) {\n // Use the custom stream adapter (e.g. React Native XHR-based SSE)\n await streamAdapter(\n url,\n { method: 'POST', headers: mergedHeaders, body, signal: controller.signal },\n handleEvent,\n )\n clearTimeout(timeoutId)\n } else {\n // Default path: fetch + ReadableStream getReader()\n const response = await fetch(url, {\n method: 'POST',\n headers: mergedHeaders,\n body,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n })\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'STREAM_ERROR', message: 'No response body', retryable: true },\n })\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data)\n handleEvent(event)\n } catch {\n // Skip malformed events\n }\n }\n }\n }\n\n // If an error event was dispatched during streaming, don't dispatch success\n if (ctx.hadStreamError) return\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: ctx.agentResponse?.message ?? ctx.accumulatedContent,\n response: ctx.agentResponse ?? undefined,\n agent: ctx.capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: ctx.accumulatedContent,\n conversationId: ctx.capturedConversationId,\n })\n } catch (err: unknown) {\n clearTimeout(timeoutId)\n if ((err as Error).name === 'AbortError') {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'TIMEOUT', message: 'Request timed out', retryable: true },\n })\n } else {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n })\n }\n }\n },\n [state.conversationId],\n )\n\n const setInputValue = useCallback((value: string) => {\n dispatch({ type: 'SET_INPUT', value })\n }, [])\n\n const loadConversation = useCallback((conversationId: string, messages: ChatMessage[]) => {\n dispatch({ type: 'LOAD_CONVERSATION', conversationId, messages })\n }, [])\n\n const submitFeedback = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n const { apiUrl, feedbackPath = '/feedback', headers: headersOrFn } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n await fetch(`${apiUrl}${feedbackPath}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({ messageId, rating, comment }),\n })\n },\n [],\n )\n\n const retry = useCallback(async () => {\n if (lastUserMessageRef.current) {\n await sendMessage(lastUserMessageRef.current, lastUserAttachmentsRef.current)\n }\n }, [sendMessage])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\n lastUserAttachmentsRef.current = undefined\n }, [])\n\n const actions: AgentChatActions = {\n sendMessage,\n setInputValue,\n loadConversation,\n submitFeedback,\n retry,\n reset,\n }\n\n return { state, actions }\n}\n","'use client'\n\nimport { useState, useCallback, useRef, useEffect } from 'react'\nimport type { StreamEvent, StreamState } from '../types/streaming'\nimport type { Source } from '../types/agent'\n\nexport interface UseStreamingOptions {\n /** SSE endpoint URL */\n url: string\n /** Additional headers for fetch-based SSE (not used with native EventSource) */\n headers?: Record<string, string>\n /** Called when a complete response is received */\n onDone?: (event: Extract<StreamEvent, { type: 'done' }>) => void\n /** Called on error */\n onError?: (event: Extract<StreamEvent, { type: 'error' }>) => void\n}\n\nconst initialState: StreamState = {\n active: false,\n phase: 'idle',\n content: '',\n sources: [],\n agent: null,\n agentLabel: null,\n}\n\nexport function useStreaming(options: UseStreamingOptions) {\n const { url, headers, onDone, onError } = options\n const [state, setState] = useState<StreamState>(initialState)\n const abortRef = useRef<AbortController | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n const stop = useCallback(() => {\n if (abortRef.current) {\n abortRef.current.abort()\n abortRef.current = null\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n }, [])\n\n const start = useCallback(\n async (body: Record<string, unknown>) => {\n // Reset state\n setState({ ...initialState, active: true, phase: 'thinking' })\n\n const controller = new AbortController()\n abortRef.current = controller\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorEvent: StreamEvent = {\n type: 'error',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(errorEvent as Extract<StreamEvent, { type: 'error' }>)\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data) as StreamEvent\n processEvent(event, setState, optionsRef)\n } catch {\n // Skip malformed events\n }\n }\n }\n } catch (err: unknown) {\n if ((err as Error).name === 'AbortError') return\n const errorEvent: StreamEvent = {\n type: 'error',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n }\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(errorEvent as Extract<StreamEvent, { type: 'error' }>)\n }\n },\n [url, headers],\n )\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (abortRef.current) {\n abortRef.current.abort()\n }\n }\n }, [])\n\n return { state, start, stop }\n}\n\nfunction processEvent(\n event: StreamEvent,\n setState: React.Dispatch<React.SetStateAction<StreamState>>,\n optionsRef: React.MutableRefObject<UseStreamingOptions>,\n) {\n switch (event.type) {\n case 'phase':\n setState((prev) => ({ ...prev, phase: event.phase }))\n break\n case 'delta':\n setState((prev) => ({ ...prev, content: prev.content + event.content }))\n break\n case 'source':\n setState((prev) => ({ ...prev, sources: [...prev.sources, event.source] }))\n break\n case 'agent':\n setState((prev) => ({ ...prev, agent: event.agent }))\n break\n case 'done':\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onDone?.(event)\n break\n case 'error':\n setState((prev) => ({ ...prev, active: false, phase: 'idle' }))\n optionsRef.current.onError?.(event)\n break\n }\n}\n","'use client'\n\nimport { useState, useCallback } from 'react'\nimport type { ChatMessage } from '../types/chat'\nimport type { ConversationSummary } from '../types/chat'\n\nexport interface Conversation {\n id: string\n title: string\n messages: ChatMessage[]\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface UseConversationOptions {\n /** Enable localStorage persistence */\n persist?: boolean\n /** localStorage key prefix */\n storageKey?: string\n}\n\nconst STORAGE_PREFIX = 'surf-kit-conversations'\n\nfunction getStorageKey(prefix: string) {\n return `${prefix}:list`\n}\n\nfunction loadFromStorage(storageKey: string): Conversation[] {\n if (typeof window === 'undefined') return []\n try {\n const raw = window.localStorage.getItem(getStorageKey(storageKey))\n if (!raw) return []\n const parsed = JSON.parse(raw) as Array<Conversation & { createdAt: string; updatedAt: string }>\n return parsed.map((c) => ({\n ...c,\n createdAt: new Date(c.createdAt),\n updatedAt: new Date(c.updatedAt),\n messages: c.messages.map((m) => ({ ...m, timestamp: new Date(m.timestamp as unknown as string) })),\n }))\n } catch {\n return []\n }\n}\n\nfunction saveToStorage(storageKey: string, conversations: Conversation[]) {\n if (typeof window === 'undefined') return\n try {\n window.localStorage.setItem(getStorageKey(storageKey), JSON.stringify(conversations))\n } catch {\n // Storage full or unavailable\n }\n}\n\nlet idCounter = 0\nfunction generateId(): string {\n return `conv-${Date.now()}-${++idCounter}`\n}\n\nexport function useConversation(options: UseConversationOptions = {}) {\n const { persist = false, storageKey = STORAGE_PREFIX } = options\n\n const [conversations, setConversations] = useState<Conversation[]>(() =>\n persist ? loadFromStorage(storageKey) : [],\n )\n const [current, setCurrent] = useState<Conversation | null>(null)\n\n const persistIfNeeded = useCallback(\n (convs: Conversation[]) => {\n if (persist) saveToStorage(storageKey, convs)\n },\n [persist, storageKey],\n )\n\n const create = useCallback(\n (title?: string): Conversation => {\n const now = new Date()\n const conv: Conversation = {\n id: generateId(),\n title: title ?? 'New Conversation',\n messages: [],\n createdAt: now,\n updatedAt: now,\n }\n setConversations((prev) => {\n const next = [conv, ...prev]\n persistIfNeeded(next)\n return next\n })\n setCurrent(conv)\n return conv\n },\n [persistIfNeeded],\n )\n\n const list = useCallback((): ConversationSummary[] => {\n return conversations.map((c) => ({\n id: c.id,\n title: c.title,\n lastMessage: c.messages.length > 0 ? c.messages[c.messages.length - 1].content : '',\n updatedAt: c.updatedAt,\n messageCount: c.messages.length,\n }))\n }, [conversations])\n\n const load = useCallback(\n (id: string): Conversation | null => {\n const conv = conversations.find((c) => c.id === id) ?? null\n setCurrent(conv)\n return conv\n },\n [conversations],\n )\n\n const remove = useCallback(\n (id: string) => {\n setConversations((prev) => {\n const next = prev.filter((c) => c.id !== id)\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) => (prev?.id === id ? null : prev))\n },\n [persistIfNeeded],\n )\n\n const rename = useCallback(\n (id: string, title: string) => {\n setConversations((prev) => {\n const next = prev.map((c) => (c.id === id ? { ...c, title, updatedAt: new Date() } : c))\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) => (prev?.id === id ? { ...prev, title, updatedAt: new Date() } : prev))\n },\n [persistIfNeeded],\n )\n\n const addMessage = useCallback(\n (conversationId: string, message: ChatMessage) => {\n setConversations((prev) => {\n const next = prev.map((c) =>\n c.id === conversationId\n ? { ...c, messages: [...c.messages, message], updatedAt: new Date() }\n : c,\n )\n persistIfNeeded(next)\n return next\n })\n setCurrent((prev) =>\n prev?.id === conversationId\n ? { ...prev, messages: [...prev.messages, message], updatedAt: new Date() }\n : prev,\n )\n },\n [persistIfNeeded],\n )\n\n return {\n conversations,\n current,\n create,\n list,\n load,\n delete: remove,\n rename,\n addMessage,\n }\n}\n","'use client'\n\nimport { useState, useCallback, useRef } from 'react'\n\nexport type FeedbackState = 'idle' | 'submitting' | 'submitted' | 'error'\n\nexport interface UseFeedbackOptions {\n /** API endpoint URL for feedback submission */\n url: string\n /** Additional request headers */\n headers?: Record<string, string>\n}\n\nexport interface FeedbackPayload {\n messageId: string\n rating: 'positive' | 'negative'\n comment?: string\n}\n\nexport function useFeedback(options: UseFeedbackOptions) {\n const { url, headers } = options\n const [state, setState] = useState<FeedbackState>('idle')\n const [error, setError] = useState<string | null>(null)\n const abortRef = useRef<AbortController | null>(null)\n\n const submit = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n setState('submitting')\n setError(null)\n\n const controller = new AbortController()\n abortRef.current = controller\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ messageId, rating, comment }),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n setState('submitted')\n } catch (err: unknown) {\n if ((err as Error).name === 'AbortError') return\n setError((err as Error).message ?? 'Failed to submit feedback')\n setState('error')\n }\n },\n [url, headers],\n )\n\n const reset = useCallback(() => {\n setState('idle')\n setError(null)\n }, [])\n\n return { state, error, submit, reset }\n}\n","'use client'\n\nimport { useMemo } from 'react'\nimport type { AgentInfo } from '../types/agent'\n\nexport interface AgentThemeResult {\n accent: string\n icon: AgentInfo['icon'] | null\n label: string\n}\n\nconst DEFAULT_ACCENT = '#6366f1'\nconst DEFAULT_LABEL = 'Agent'\n\nexport function useAgentTheme(\n agentId: string | null | undefined,\n agentThemes?: Record<string, AgentInfo>,\n): AgentThemeResult {\n return useMemo(() => {\n if (!agentId) {\n return { accent: DEFAULT_ACCENT, icon: null, label: DEFAULT_LABEL }\n }\n\n const theme = agentThemes?.[agentId]\n if (!theme) {\n return { accent: DEFAULT_ACCENT, icon: null, label: agentId }\n }\n\n return {\n accent: theme.accent ?? DEFAULT_ACCENT,\n icon: theme.icon ?? null,\n label: theme.label,\n }\n }, [agentId, agentThemes])\n}\n","'use client'\n\nimport { useState, useRef, useEffect } from 'react'\n\nexport interface CharacterDrainResult {\n displayed: string\n isDraining: boolean\n}\n\n/**\n * Smoothly drains a growing `target` string character-by-character using\n * `requestAnimationFrame`, decoupling visual rendering from network packet\n * timing so text appears to type out instead of arriving in chunks.\n *\n * When `target` resets to empty (e.g. stream finished), the hook continues\n * draining the previous content to completion before resetting, so the\n * typing animation isn't cut short.\n *\n * Design: the RAF loop is long-lived — it does NOT restart on every delta.\n * The tick function is stored in a ref (updated each render) so the loop\n * always reads the latest drainTarget without being cancelled/restarted.\n * A separate kick-start effect re-fires the loop when it was idle and new\n * content arrives.\n */\nexport function useCharacterDrain(target: string, msPerChar = 15): CharacterDrainResult {\n const [displayed, setDisplayed] = useState('')\n const indexRef = useRef(0)\n const lastTimeRef = useRef(0)\n const rafRef = useRef<number | null>(null)\n // Holds the last non-empty target so we can finish draining after source resets\n const drainTargetRef = useRef('')\n const msPerCharRef = useRef(msPerChar)\n\n msPerCharRef.current = msPerChar\n\n // Update drain target when new content arrives; preserve old value on reset\n if (target !== '') {\n drainTargetRef.current = target\n }\n\n const drainTarget = drainTargetRef.current\n const isDraining = displayed.length < drainTarget.length\n\n // Tick function stored in ref so the long-lived RAF loop always reads the\n // latest drainTarget and msPerChar without being cancelled/recreated.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const tickRef = useRef<(now: number) => void>(() => {})\n tickRef.current = (now: number) => {\n const currentTarget = drainTargetRef.current\n if (currentTarget === '') {\n rafRef.current = null\n return\n }\n\n if (lastTimeRef.current === 0) lastTimeRef.current = now\n const elapsed = now - lastTimeRef.current\n const charsToAdvance = Math.floor(elapsed / msPerCharRef.current)\n\n if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {\n let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\n // When the slice would end with whitespace, advance past it to include\n // the next visible character. This prevents trimEnd() in the streaming\n // UI from stripping trailing newlines and causing ReactMarkdown to\n // \"jump\" between block structures in a single frame (e.g. a heading\n // suddenly gaining a following paragraph with no transition).\n while (\n nextIndex < currentTarget.length &&\n currentTarget[nextIndex - 1].trim() === ''\n ) {\n nextIndex++\n }\n indexRef.current = nextIndex\n lastTimeRef.current = now\n setDisplayed(currentTarget.slice(0, nextIndex))\n }\n\n if (indexRef.current < currentTarget.length) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n } else {\n rafRef.current = null\n }\n }\n\n // Kick-start the RAF loop when new content arrives and the loop is idle.\n // No cleanup here — we intentionally do NOT cancel the running loop when\n // drainTarget grows; the long-lived tick will pick up new chars automatically.\n useEffect(() => {\n if (\n drainTargetRef.current !== '' &&\n indexRef.current < drainTargetRef.current.length &&\n rafRef.current === null\n ) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n }\n }, [drainTarget]) // drainTarget change = new content; check if loop needs kicking\n\n // Once drain completes and source stream is already done, reset all state\n useEffect(() => {\n if (target === '' && !isDraining && displayed !== '') {\n indexRef.current = 0\n lastTimeRef.current = 0\n drainTargetRef.current = ''\n setDisplayed('')\n }\n }, [target, isDraining, displayed])\n\n // Cancel any pending RAF on unmount\n useEffect(() => {\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n }\n }, [])\n\n return { displayed, isDraining }\n}\n"],"mappings":"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","names":["import_react","initialState","import_react","import_react","import_react","import_react"]}
|
package/dist/hooks.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { A as AgentChatActions, b as AgentChatState, c as AgentThemeResult, C as CharacterDrainResult, d as Conversation, F as FeedbackPayload, e as FeedbackState, U as UseConversationOptions, f as UseFeedbackOptions, g as UseStreamingOptions, u as useAgentChat, h as useAgentTheme, i as useCharacterDrain, j as useConversation, k as useFeedback, l as useStreaming } from './hooks-
|
|
2
|
-
import './chat-
|
|
1
|
+
export { A as AgentChatActions, b as AgentChatState, c as AgentThemeResult, C as CharacterDrainResult, d as Conversation, F as FeedbackPayload, e as FeedbackState, U as UseConversationOptions, f as UseFeedbackOptions, g as UseStreamingOptions, u as useAgentChat, h as useAgentTheme, i as useCharacterDrain, j as useConversation, k as useFeedback, l as useStreaming } from './hooks-B1NYoLLs.cjs';
|
|
2
|
+
import './chat-CGamM7Mz.cjs';
|
|
3
3
|
import './agent-BNSmiexZ.cjs';
|
|
4
4
|
import 'react';
|
|
5
|
-
import './streaming-
|
|
5
|
+
import './streaming-x7umFHoP.cjs';
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { A as AgentChatActions, b as AgentChatState, c as AgentThemeResult, C as CharacterDrainResult, d as Conversation, F as FeedbackPayload, e as FeedbackState, U as UseConversationOptions, f as UseFeedbackOptions, g as UseStreamingOptions, u as useAgentChat, h as useAgentTheme, i as useCharacterDrain, j as useConversation, k as useFeedback, l as useStreaming } from './hooks-
|
|
2
|
-
import './chat
|
|
1
|
+
export { A as AgentChatActions, b as AgentChatState, c as AgentThemeResult, C as CharacterDrainResult, d as Conversation, F as FeedbackPayload, e as FeedbackState, U as UseConversationOptions, f as UseFeedbackOptions, g as UseStreamingOptions, u as useAgentChat, h as useAgentTheme, i as useCharacterDrain, j as useConversation, k as useFeedback, l as useStreaming } from './hooks-CTeEqnBQ.js';
|
|
2
|
+
import './chat-BIIDOGrD.js';
|
|
3
3
|
import './agent-BNSmiexZ.js';
|
|
4
4
|
import 'react';
|
|
5
|
-
import './streaming-
|
|
5
|
+
import './streaming-Bx-ff2tt.js';
|