@surf-kit/agent 0.2.1 → 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.
Files changed (65) hide show
  1. package/LICENSE +184 -12
  2. package/README.md +1 -1
  3. package/dist/agent-identity/index.cjs +1 -0
  4. package/dist/agent-identity/index.cjs.map +1 -1
  5. package/dist/agent-identity/index.js +2 -0
  6. package/dist/agent-identity/index.js.map +1 -1
  7. package/dist/chat/index.cjs +626 -204
  8. package/dist/chat/index.cjs.map +1 -1
  9. package/dist/chat/index.d.cts +11 -6
  10. package/dist/chat/index.d.ts +11 -6
  11. package/dist/chat/index.js +608 -185
  12. package/dist/chat/index.js.map +1 -1
  13. package/dist/{chat--OifhIRe.d.ts → chat-BIIDOGrD.d.ts} +10 -1
  14. package/dist/{chat-ChYl2XjV.d.cts → chat-CGamM7Mz.d.cts} +10 -1
  15. package/dist/confidence/index.cjs +1 -0
  16. package/dist/confidence/index.cjs.map +1 -1
  17. package/dist/confidence/index.js +2 -0
  18. package/dist/confidence/index.js.map +1 -1
  19. package/dist/feedback/index.cjs +1 -0
  20. package/dist/feedback/index.cjs.map +1 -1
  21. package/dist/feedback/index.js +2 -0
  22. package/dist/feedback/index.js.map +1 -1
  23. package/dist/{hooks-DLfF18IU.d.cts → hooks-B1NYoLLs.d.cts} +21 -5
  24. package/dist/{hooks-BGs8-4GK.d.ts → hooks-CTeEqnBQ.d.ts} +21 -5
  25. package/dist/hooks.cjs +127 -81
  26. package/dist/hooks.cjs.map +1 -1
  27. package/dist/hooks.d.cts +3 -3
  28. package/dist/hooks.d.ts +3 -3
  29. package/dist/hooks.js +128 -81
  30. package/dist/hooks.js.map +1 -1
  31. package/dist/index.cjs +687 -265
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +3 -3
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.js +647 -224
  36. package/dist/index.js.map +1 -1
  37. package/dist/layouts/index.cjs +647 -225
  38. package/dist/layouts/index.cjs.map +1 -1
  39. package/dist/layouts/index.d.cts +1 -1
  40. package/dist/layouts/index.d.ts +1 -1
  41. package/dist/layouts/index.js +624 -201
  42. package/dist/layouts/index.js.map +1 -1
  43. package/dist/mcp/index.cjs +2 -1
  44. package/dist/mcp/index.cjs.map +1 -1
  45. package/dist/mcp/index.js +4 -2
  46. package/dist/mcp/index.js.map +1 -1
  47. package/dist/response/index.cjs +67 -12
  48. package/dist/response/index.cjs.map +1 -1
  49. package/dist/response/index.d.cts +2 -2
  50. package/dist/response/index.d.ts +2 -2
  51. package/dist/response/index.js +66 -10
  52. package/dist/response/index.js.map +1 -1
  53. package/dist/sources/index.cjs +31 -1
  54. package/dist/sources/index.cjs.map +1 -1
  55. package/dist/sources/index.js +32 -1
  56. package/dist/sources/index.js.map +1 -1
  57. package/dist/streaming/index.cjs +203 -93
  58. package/dist/streaming/index.cjs.map +1 -1
  59. package/dist/streaming/index.d.cts +4 -3
  60. package/dist/streaming/index.d.ts +4 -3
  61. package/dist/streaming/index.js +174 -73
  62. package/dist/streaming/index.js.map +1 -1
  63. package/dist/{streaming-DbQxScpi.d.ts → streaming-Bx-ff2tt.d.ts} +1 -1
  64. package/dist/{streaming-DfT22A0z.d.cts → streaming-x7umFHoP.d.cts} +1 -1
  65. package/package.json +17 -6
package/dist/hooks.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/hooks/useAgentChat.ts
2
4
  import { useReducer, useCallback, useRef } from "react";
3
5
  var initialState = {
@@ -7,7 +9,8 @@ var initialState = {
7
9
  error: null,
8
10
  inputValue: "",
9
11
  streamPhase: "idle",
10
- streamingContent: ""
12
+ streamingContent: "",
13
+ streamingAgent: null
11
14
  };
12
15
  function reducer(state, action) {
13
16
  switch (action.type) {
@@ -21,12 +24,15 @@ function reducer(state, action) {
21
24
  error: null,
22
25
  inputValue: "",
23
26
  streamPhase: "thinking",
24
- streamingContent: ""
27
+ streamingContent: "",
28
+ streamingAgent: null
25
29
  };
26
30
  case "STREAM_PHASE":
27
31
  return { ...state, streamPhase: action.phase };
28
32
  case "STREAM_CONTENT":
29
33
  return { ...state, streamingContent: state.streamingContent + action.content };
34
+ case "STREAM_AGENT":
35
+ return { ...state, streamingAgent: action.agent };
30
36
  case "SEND_SUCCESS":
31
37
  return {
32
38
  ...state,
@@ -42,7 +48,8 @@ function reducer(state, action) {
42
48
  isLoading: false,
43
49
  error: action.error,
44
50
  streamPhase: "idle",
45
- streamingContent: ""
51
+ streamingContent: "",
52
+ streamingAgent: null
46
53
  };
47
54
  case "LOAD_CONVERSATION":
48
55
  return {
@@ -68,107 +75,142 @@ function useAgentChat(config) {
68
75
  const configRef = useRef(config);
69
76
  configRef.current = config;
70
77
  const lastUserMessageRef = useRef(null);
78
+ const lastUserAttachmentsRef = useRef(void 0);
71
79
  const sendMessage = useCallback(
72
- async (content) => {
73
- const { apiUrl, streamPath = "/chat/stream", headers = {}, timeout = 3e4 } = configRef.current;
80
+ async (content, attachments) => {
81
+ const { apiUrl, streamPath = "/chat/stream", headers: headersOrFn, timeout = 3e4, bodyExtra } = configRef.current;
82
+ const headers = typeof headersOrFn === "function" ? await headersOrFn() : headersOrFn ?? {};
74
83
  lastUserMessageRef.current = content;
84
+ lastUserAttachmentsRef.current = attachments;
75
85
  const userMessage = {
76
86
  id: generateMessageId(),
77
87
  role: "user",
78
88
  content,
89
+ attachments,
79
90
  timestamp: /* @__PURE__ */ new Date()
80
91
  };
81
92
  dispatch({ type: "SEND_START", message: userMessage });
82
93
  const controller = new AbortController();
83
94
  const timeoutId = setTimeout(() => controller.abort(), timeout);
84
95
  try {
85
- const response = await fetch(`${apiUrl}${streamPath}`, {
86
- method: "POST",
87
- headers: {
88
- "Content-Type": "application/json",
89
- Accept: "text/event-stream",
90
- ...headers
91
- },
92
- body: JSON.stringify({
93
- message: content,
94
- conversation_id: state.conversationId
95
- }),
96
- signal: controller.signal
97
- });
98
- clearTimeout(timeoutId);
99
- if (!response.ok) {
100
- dispatch({
101
- type: "SEND_ERROR",
102
- error: {
103
- code: "API_ERROR",
104
- message: `HTTP ${response.status}: ${response.statusText}`,
105
- retryable: response.status >= 500
106
- }
107
- });
108
- return;
96
+ const url = `${apiUrl}${streamPath}`;
97
+ const mergedHeaders = {
98
+ "Content-Type": "application/json",
99
+ Accept: "text/event-stream",
100
+ ...headers
101
+ };
102
+ const requestBody = {
103
+ message: content,
104
+ conversation_id: state.conversationId,
105
+ ...bodyExtra
106
+ };
107
+ if (attachments && attachments.length > 0) {
108
+ requestBody.attachments = attachments.map((a) => ({
109
+ filename: a.filename,
110
+ content_type: a.content_type,
111
+ data: a.data
112
+ }));
109
113
  }
110
- const reader = response.body?.getReader();
111
- if (!reader) {
112
- dispatch({
113
- type: "SEND_ERROR",
114
- error: { code: "STREAM_ERROR", message: "No response body", retryable: true }
114
+ const body = JSON.stringify(requestBody);
115
+ const ctx = {
116
+ accumulatedContent: "",
117
+ agentResponse: null,
118
+ capturedAgent: null,
119
+ capturedConversationId: null,
120
+ hadStreamError: false
121
+ };
122
+ const handleEvent = (event) => {
123
+ switch (event.type) {
124
+ case "agent":
125
+ ctx.capturedAgent = event.agent;
126
+ dispatch({ type: "STREAM_AGENT", agent: ctx.capturedAgent });
127
+ break;
128
+ case "phase":
129
+ dispatch({ type: "STREAM_PHASE", phase: event.phase });
130
+ break;
131
+ case "delta":
132
+ ctx.accumulatedContent += event.content;
133
+ dispatch({ type: "STREAM_CONTENT", content: event.content });
134
+ break;
135
+ case "done":
136
+ ctx.agentResponse = event.response;
137
+ ctx.capturedConversationId = event.conversation_id ?? null;
138
+ break;
139
+ case "error":
140
+ ctx.hadStreamError = true;
141
+ dispatch({ type: "SEND_ERROR", error: event.error });
142
+ break;
143
+ }
144
+ };
145
+ const { streamAdapter } = configRef.current;
146
+ if (streamAdapter) {
147
+ await streamAdapter(
148
+ url,
149
+ { method: "POST", headers: mergedHeaders, body, signal: controller.signal },
150
+ handleEvent
151
+ );
152
+ clearTimeout(timeoutId);
153
+ } else {
154
+ const response = await fetch(url, {
155
+ method: "POST",
156
+ headers: mergedHeaders,
157
+ body,
158
+ signal: controller.signal
115
159
  });
116
- return;
117
- }
118
- const decoder = new TextDecoder();
119
- let buffer = "";
120
- let accumulatedContent = "";
121
- let agentResponse = null;
122
- let capturedAgent = null;
123
- let capturedConversationId = null;
124
- while (true) {
125
- const { done, value } = await reader.read();
126
- if (done) break;
127
- buffer += decoder.decode(value, { stream: true });
128
- const lines = buffer.split("\n");
129
- buffer = lines.pop() ?? "";
130
- for (const line of lines) {
131
- if (!line.startsWith("data: ")) continue;
132
- const data = line.slice(6).trim();
133
- if (data === "[DONE]") continue;
134
- try {
135
- const event = JSON.parse(data);
136
- switch (event.type) {
137
- case "agent":
138
- capturedAgent = event.agent;
139
- break;
140
- case "phase":
141
- dispatch({ type: "STREAM_PHASE", phase: event.phase });
142
- break;
143
- case "delta":
144
- accumulatedContent += event.content;
145
- dispatch({ type: "STREAM_CONTENT", content: event.content });
146
- break;
147
- case "done":
148
- agentResponse = event.response;
149
- capturedConversationId = event.conversation_id ?? null;
150
- break;
151
- case "error":
152
- dispatch({ type: "SEND_ERROR", error: event.error });
153
- return;
160
+ clearTimeout(timeoutId);
161
+ if (!response.ok) {
162
+ dispatch({
163
+ type: "SEND_ERROR",
164
+ error: {
165
+ code: "API_ERROR",
166
+ message: `HTTP ${response.status}: ${response.statusText}`,
167
+ retryable: response.status >= 500
168
+ }
169
+ });
170
+ return;
171
+ }
172
+ const reader = response.body?.getReader();
173
+ if (!reader) {
174
+ dispatch({
175
+ type: "SEND_ERROR",
176
+ error: { code: "STREAM_ERROR", message: "No response body", retryable: true }
177
+ });
178
+ return;
179
+ }
180
+ const decoder = new TextDecoder();
181
+ let buffer = "";
182
+ while (true) {
183
+ const { done, value } = await reader.read();
184
+ if (done) break;
185
+ buffer += decoder.decode(value, { stream: true });
186
+ const lines = buffer.split("\n");
187
+ buffer = lines.pop() ?? "";
188
+ for (const line of lines) {
189
+ if (!line.startsWith("data: ")) continue;
190
+ const data = line.slice(6).trim();
191
+ if (data === "[DONE]") continue;
192
+ try {
193
+ const event = JSON.parse(data);
194
+ handleEvent(event);
195
+ } catch {
154
196
  }
155
- } catch {
156
197
  }
157
198
  }
158
199
  }
200
+ if (ctx.hadStreamError) return;
159
201
  const assistantMessage = {
160
202
  id: generateMessageId(),
161
203
  role: "assistant",
162
- content: agentResponse?.message ?? accumulatedContent,
163
- response: agentResponse ?? void 0,
164
- agent: capturedAgent ?? void 0,
204
+ content: ctx.agentResponse?.message ?? ctx.accumulatedContent,
205
+ response: ctx.agentResponse ?? void 0,
206
+ agent: ctx.capturedAgent ?? void 0,
165
207
  timestamp: /* @__PURE__ */ new Date()
166
208
  };
167
209
  dispatch({
168
210
  type: "SEND_SUCCESS",
169
211
  message: assistantMessage,
170
- streamingContent: accumulatedContent,
171
- conversationId: capturedConversationId
212
+ streamingContent: ctx.accumulatedContent,
213
+ conversationId: ctx.capturedConversationId
172
214
  });
173
215
  } catch (err) {
174
216
  clearTimeout(timeoutId);
@@ -199,7 +241,8 @@ function useAgentChat(config) {
199
241
  }, []);
200
242
  const submitFeedback = useCallback(
201
243
  async (messageId, rating, comment) => {
202
- const { apiUrl, feedbackPath = "/feedback", headers = {} } = configRef.current;
244
+ const { apiUrl, feedbackPath = "/feedback", headers: headersOrFn } = configRef.current;
245
+ const headers = typeof headersOrFn === "function" ? await headersOrFn() : headersOrFn ?? {};
203
246
  await fetch(`${apiUrl}${feedbackPath}`, {
204
247
  method: "POST",
205
248
  headers: { "Content-Type": "application/json", ...headers },
@@ -210,12 +253,13 @@ function useAgentChat(config) {
210
253
  );
211
254
  const retry = useCallback(async () => {
212
255
  if (lastUserMessageRef.current) {
213
- await sendMessage(lastUserMessageRef.current);
256
+ await sendMessage(lastUserMessageRef.current, lastUserAttachmentsRef.current);
214
257
  }
215
258
  }, [sendMessage]);
216
259
  const reset = useCallback(() => {
217
260
  dispatch({ type: "RESET" });
218
261
  lastUserMessageRef.current = null;
262
+ lastUserAttachmentsRef.current = void 0;
219
263
  }, []);
220
264
  const actions = {
221
265
  sendMessage,
@@ -575,7 +619,10 @@ function useCharacterDrain(target, msPerChar = 15) {
575
619
  const elapsed = now - lastTimeRef.current;
576
620
  const charsToAdvance = Math.floor(elapsed / msPerCharRef.current);
577
621
  if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {
578
- const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
622
+ let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
623
+ while (nextIndex < currentTarget.length && currentTarget[nextIndex - 1].trim() === "") {
624
+ nextIndex++;
625
+ }
579
626
  indexRef.current = nextIndex;
580
627
  lastTimeRef.current = now;
581
628
  setDisplayed(currentTarget.slice(0, nextIndex));
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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":["import { 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","import { 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","import { 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","import { 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","import { 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","import { 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":["useCallback","useRef","initialState","useState","useCallback","useState","useCallback","useRef","useState","useRef","useEffect"]}
1
+ {"version":3,"sources":["../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":["'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":["useCallback","useRef","initialState","useState","useCallback","useState","useCallback","useRef","useState","useRef","useEffect"]}