@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.
Files changed (51) hide show
  1. package/dist/chat/index.cjs +625 -204
  2. package/dist/chat/index.cjs.map +1 -1
  3. package/dist/chat/index.d.cts +11 -6
  4. package/dist/chat/index.d.ts +11 -6
  5. package/dist/chat/index.js +606 -185
  6. package/dist/chat/index.js.map +1 -1
  7. package/dist/{chat--OifhIRe.d.ts → chat-BIIDOGrD.d.ts} +10 -1
  8. package/dist/{chat-ChYl2XjV.d.cts → chat-CGamM7Mz.d.cts} +10 -1
  9. package/dist/{hooks-DLfF18IU.d.cts → hooks-B1NYoLLs.d.cts} +21 -5
  10. package/dist/{hooks-BGs8-4GK.d.ts → hooks-CTeEqnBQ.d.ts} +21 -5
  11. package/dist/hooks.cjs +126 -81
  12. package/dist/hooks.cjs.map +1 -1
  13. package/dist/hooks.d.cts +3 -3
  14. package/dist/hooks.d.ts +3 -3
  15. package/dist/hooks.js +126 -81
  16. package/dist/hooks.js.map +1 -1
  17. package/dist/index.cjs +686 -265
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +645 -224
  22. package/dist/index.js.map +1 -1
  23. package/dist/layouts/index.cjs +646 -225
  24. package/dist/layouts/index.cjs.map +1 -1
  25. package/dist/layouts/index.d.cts +1 -1
  26. package/dist/layouts/index.d.ts +1 -1
  27. package/dist/layouts/index.js +622 -201
  28. package/dist/layouts/index.js.map +1 -1
  29. package/dist/mcp/index.cjs +1 -1
  30. package/dist/mcp/index.cjs.map +1 -1
  31. package/dist/mcp/index.js +2 -2
  32. package/dist/mcp/index.js.map +1 -1
  33. package/dist/response/index.cjs +66 -12
  34. package/dist/response/index.cjs.map +1 -1
  35. package/dist/response/index.d.cts +2 -2
  36. package/dist/response/index.d.ts +2 -2
  37. package/dist/response/index.js +64 -10
  38. package/dist/response/index.js.map +1 -1
  39. package/dist/sources/index.cjs +30 -1
  40. package/dist/sources/index.cjs.map +1 -1
  41. package/dist/sources/index.js +30 -1
  42. package/dist/sources/index.js.map +1 -1
  43. package/dist/streaming/index.cjs +202 -93
  44. package/dist/streaming/index.cjs.map +1 -1
  45. package/dist/streaming/index.d.cts +4 -3
  46. package/dist/streaming/index.d.ts +4 -3
  47. package/dist/streaming/index.js +172 -73
  48. package/dist/streaming/index.js.map +1 -1
  49. package/dist/{streaming-DbQxScpi.d.ts → streaming-Bx-ff2tt.d.ts} +1 -1
  50. package/dist/{streaming-DfT22A0z.d.cts → streaming-x7umFHoP.d.cts} +1 -1
  51. package/package.json +15 -4
@@ -1,8 +1,10 @@
1
1
  'use client';
2
2
  "use strict";
3
+ var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
6
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
9
  var __export = (target, all) => {
8
10
  for (var name in all)
@@ -16,6 +18,14 @@ var __copyProps = (to, from, except, desc) => {
16
18
  }
17
19
  return to;
18
20
  };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
19
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
30
 
21
31
  // src/streaming/index.ts
@@ -35,7 +45,8 @@ __export(streaming_exports, {
35
45
  module.exports = __toCommonJS(streaming_exports);
36
46
 
37
47
  // src/streaming/StreamingMessage/StreamingMessage.tsx
38
- var import_react2 = require("react");
48
+ var import_react3 = require("react");
49
+ var import_tailwind_merge2 = require("tailwind-merge");
39
50
  var import_core = require("@surf-kit/core");
40
51
 
41
52
  // src/hooks/useCharacterDrain.ts
@@ -65,7 +76,10 @@ function useCharacterDrain(target, msPerChar = 15) {
65
76
  const elapsed = now - lastTimeRef.current;
66
77
  const charsToAdvance = Math.floor(elapsed / msPerCharRef.current);
67
78
  if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {
68
- const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
79
+ let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
80
+ while (nextIndex < currentTarget.length && currentTarget[nextIndex - 1].trim() === "") {
81
+ nextIndex++;
82
+ }
69
83
  indexRef.current = nextIndex;
70
84
  lastTimeRef.current = now;
71
85
  setDisplayed(currentTarget.slice(0, nextIndex));
@@ -100,8 +114,77 @@ function useCharacterDrain(target, msPerChar = 15) {
100
114
  return { displayed, isDraining };
101
115
  }
102
116
 
103
- // src/streaming/StreamingMessage/StreamingMessage.tsx
117
+ // src/response/ResponseMessage/ResponseMessage.tsx
118
+ var import_react2 = __toESM(require("react"), 1);
119
+ var import_react_markdown = __toESM(require("react-markdown"), 1);
120
+ var import_rehype_sanitize = __toESM(require("rehype-sanitize"), 1);
121
+ var import_tailwind_merge = require("tailwind-merge");
104
122
  var import_jsx_runtime = require("react/jsx-runtime");
123
+ function normalizeMarkdownLists(content) {
124
+ return content.replace(/:\s+-\s+/g, ":\n\n- ");
125
+ }
126
+ function ResponseMessage({ content, className }) {
127
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
128
+ "div",
129
+ {
130
+ className: (0, import_tailwind_merge.twMerge)(
131
+ "text-sm leading-relaxed text-text-primary",
132
+ "[&_p]:my-2",
133
+ "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6",
134
+ "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6",
135
+ "[&_li]:my-1",
136
+ "[&_strong]:text-text-primary [&_strong]:font-semibold",
137
+ "[&_em]:text-text-secondary",
138
+ "[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2",
139
+ "[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5",
140
+ "[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1",
141
+ "[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono",
142
+ "[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto",
143
+ "[&_hr]:my-3 [&_hr]:border-border",
144
+ "[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary",
145
+ "[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80",
146
+ className
147
+ ),
148
+ "data-testid": "response-message",
149
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
150
+ import_react_markdown.default,
151
+ {
152
+ rehypePlugins: [import_rehype_sanitize.default],
153
+ components: {
154
+ script: () => null,
155
+ iframe: () => null,
156
+ p: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "my-2", children }),
157
+ ul: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "my-2 list-disc pl-6", children }),
158
+ ol: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "my-2 list-decimal pl-6", children }),
159
+ li: ({ children, ...props }) => {
160
+ let content2 = children;
161
+ if (props.ordered) {
162
+ content2 = import_react2.default.Children.map(children, (child, i) => {
163
+ if (i === 0 && typeof child === "string") {
164
+ return child.replace(/^\d+[.)]\s*/, "");
165
+ }
166
+ return child;
167
+ });
168
+ }
169
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { className: "my-1", children: content2 });
170
+ },
171
+ strong: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "font-semibold", children }),
172
+ em: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { className: "italic text-text-secondary", children }),
173
+ h1: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-base font-bold mt-4 mb-2", children }),
174
+ h2: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-sm font-bold mt-3 mb-1", children }),
175
+ h3: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-sm font-semibold mt-2 mb-1", children }),
176
+ hr: () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { className: "my-3 border-border" }),
177
+ code: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: "bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono", children })
178
+ },
179
+ children: normalizeMarkdownLists(content)
180
+ }
181
+ )
182
+ }
183
+ );
184
+ }
185
+
186
+ // src/streaming/StreamingMessage/StreamingMessage.tsx
187
+ var import_jsx_runtime2 = require("react/jsx-runtime");
105
188
  var phaseLabels = {
106
189
  idle: "",
107
190
  waiting: "Waiting...",
@@ -110,72 +193,98 @@ var phaseLabels = {
110
193
  generating: "Writing...",
111
194
  verifying: "Verifying..."
112
195
  };
196
+ var CURSOR_STYLES = `
197
+ .sk-streaming-cursor > :not(ul,ol,blockquote):last-child::after,
198
+ .sk-streaming-cursor > :is(ul,ol):last-child > li:last-child::after,
199
+ .sk-streaming-cursor > blockquote:last-child > p:last-child::after {
200
+ content: "";
201
+ display: inline-block;
202
+ width: 2px;
203
+ height: 1em;
204
+ background: var(--color-accent, #38bdf8);
205
+ animation: sk-cursor-blink 0.8s steps(1) infinite;
206
+ margin-left: 2px;
207
+ vertical-align: text-bottom;
208
+ }
209
+ @keyframes sk-cursor-blink {
210
+ 0%, 60% { opacity: 1; }
211
+ 61%, 100% { opacity: 0; }
212
+ }
213
+ `;
113
214
  function StreamingMessage({
114
215
  stream,
115
216
  onComplete,
217
+ onDraining,
116
218
  showPhases = true,
117
219
  className
118
220
  }) {
119
- const onCompleteRef = (0, import_react2.useRef)(onComplete);
221
+ const onCompleteRef = (0, import_react3.useRef)(onComplete);
120
222
  onCompleteRef.current = onComplete;
121
- const wasActiveRef = (0, import_react2.useRef)(stream.active);
122
- (0, import_react2.useEffect)(() => {
223
+ const onDrainingRef = (0, import_react3.useRef)(onDraining);
224
+ onDrainingRef.current = onDraining;
225
+ const wasActiveRef = (0, import_react3.useRef)(stream.active);
226
+ (0, import_react3.useEffect)(() => {
123
227
  if (wasActiveRef.current && !stream.active) {
124
228
  onCompleteRef.current?.();
125
229
  }
126
230
  wasActiveRef.current = stream.active;
127
231
  }, [stream.active]);
128
232
  const phaseLabel = phaseLabels[stream.phase];
129
- const { displayed: displayedContent } = useCharacterDrain(stream.content);
130
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, "data-testid": "streaming-message", children: [
131
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "aria-live": "assertive", className: "sr-only", children: [
233
+ const { displayed: rawDisplayed, isDraining } = useCharacterDrain(stream.content);
234
+ const displayedContent = stream.active || isDraining ? rawDisplayed.trimEnd() : rawDisplayed;
235
+ (0, import_react3.useEffect)(() => {
236
+ onDrainingRef.current?.(isDraining);
237
+ }, [isDraining]);
238
+ const agentLabel = stream.agent ? stream.agent.replace("_agent", "").replace("_", " ") : null;
239
+ const showPhaseIndicator = showPhases && stream.active && stream.phase !== "idle" && !displayedContent;
240
+ const showCursor = (stream.active || isDraining) && !!displayedContent;
241
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: (0, import_tailwind_merge2.twMerge)("flex w-full flex-col items-start", className), "data-testid": "streaming-message", children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { "aria-live": "assertive", className: "sr-only", children: [
132
243
  stream.active && stream.phase !== "idle" && "Response started",
133
244
  !stream.active && stream.content && "Response complete"
134
245
  ] }),
135
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft", children: [
136
- showPhases && stream.active && stream.phase !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
246
+ showCursor && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: CURSOR_STYLES }),
247
+ agentLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-[11px] font-display font-semibold uppercase tracking-[0.08em] text-text-muted px-1 mb-1.5", children: agentLabel }),
248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft", children: [
249
+ showPhaseIndicator && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
137
250
  "div",
138
251
  {
139
- className: "flex items-center gap-2 mb-2 text-sm text-text-secondary",
252
+ className: "flex items-center gap-2 text-sm text-text-secondary",
140
253
  "data-testid": "phase-indicator",
141
254
  children: [
142
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Spinner, { size: "sm" }) }),
143
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: phaseLabel })
255
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
256
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: phaseLabel })
144
257
  ]
145
258
  }
146
259
  ),
147
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-sm leading-relaxed text-text-primary whitespace-pre-wrap", children: [
148
- displayedContent,
149
- stream.active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
150
- "span",
151
- {
152
- className: "inline-block w-0.5 h-4 bg-accent align-text-bottom animate-pulse ml-0.5",
153
- "aria-hidden": "true",
154
- "data-testid": "streaming-cursor"
155
- }
156
- )
157
- ] })
260
+ displayedContent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
261
+ ResponseMessage,
262
+ {
263
+ content: displayedContent,
264
+ className: showCursor ? "sk-streaming-cursor" : void 0
265
+ }
266
+ )
158
267
  ] })
159
268
  ] });
160
269
  }
161
270
 
162
271
  // src/streaming/ThinkingIndicator/ThinkingIndicator.tsx
163
272
  var import_hooks = require("@surf-kit/hooks");
164
- var import_jsx_runtime2 = require("react/jsx-runtime");
273
+ var import_jsx_runtime3 = require("react/jsx-runtime");
165
274
  function ThinkingIndicator({ label = "Thinking...", className }) {
166
275
  const reducedMotion = (0, import_hooks.useReducedMotion)();
167
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
276
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
168
277
  "span",
169
278
  {
170
279
  role: "status",
171
280
  className: `inline-flex items-center gap-2 text-sm motion-safe:animate-fadeSlideUpSm ${className ?? ""}`,
172
281
  "data-testid": "thinking-indicator",
173
282
  children: [
174
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-text-secondary", children: label }),
175
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex gap-1", "aria-hidden": "true", "data-testid": "animated-dots", children: [
176
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:0ms]" }),
177
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:150ms]" }),
178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:300ms]" })
283
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-text-secondary", children: label }),
284
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex gap-1", "aria-hidden": "true", "data-testid": "animated-dots", children: [
285
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:0ms]" }),
286
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:150ms]" }),
287
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:300ms]" })
179
288
  ] })
180
289
  ]
181
290
  }
@@ -184,7 +293,7 @@ function ThinkingIndicator({ label = "Thinking...", className }) {
184
293
 
185
294
  // src/streaming/ToolExecution/ToolExecution.tsx
186
295
  var import_core2 = require("@surf-kit/core");
187
- var import_jsx_runtime3 = require("react/jsx-runtime");
296
+ var import_jsx_runtime4 = require("react/jsx-runtime");
188
297
  var defaultLabels = {
189
298
  search: "Searching knowledge base...",
190
299
  retrieve: "Retrieving documents...",
@@ -192,15 +301,15 @@ var defaultLabels = {
192
301
  };
193
302
  function ToolExecution({ tool, label, className }) {
194
303
  const displayLabel = label ?? defaultLabels[tool] ?? `Running ${tool}...`;
195
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
304
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
196
305
  "div",
197
306
  {
198
307
  className: `flex items-center gap-2 text-sm text-text-secondary ${className ?? ""}`,
199
308
  role: "status",
200
309
  "data-testid": "tool-execution",
201
310
  children: [
202
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core2.Spinner, { size: "sm" }) }),
203
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: displayLabel })
311
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core2.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
312
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: displayLabel })
204
313
  ]
205
314
  }
206
315
  );
@@ -208,9 +317,9 @@ function ToolExecution({ tool, label, className }) {
208
317
 
209
318
  // src/streaming/RetrievalProgress/RetrievalProgress.tsx
210
319
  var import_core3 = require("@surf-kit/core");
211
- var import_jsx_runtime4 = require("react/jsx-runtime");
320
+ var import_jsx_runtime5 = require("react/jsx-runtime");
212
321
  function RetrievalProgress({ sources, isActive, className }) {
213
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
322
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
214
323
  "div",
215
324
  {
216
325
  className: `space-y-2 ${className ?? ""}`,
@@ -218,19 +327,19 @@ function RetrievalProgress({ sources, isActive, className }) {
218
327
  "aria-label": isActive ? `Retrieving sources, ${sources.length} found so far` : `${sources.length} sources found`,
219
328
  "data-testid": "retrieval-progress",
220
329
  children: [
221
- isActive && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 text-sm text-text-secondary", children: [
222
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core3.Spinner, { size: "sm" }) }),
223
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Retrieving sources..." })
330
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-sm text-text-secondary", children: [
331
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core3.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
332
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Retrieving sources..." })
224
333
  ] }),
225
- sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "space-y-1", "data-testid": "source-list", children: sources.map((source, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
334
+ sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "space-y-1", "data-testid": "source-list", children: sources.map((source, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
226
335
  "li",
227
336
  {
228
337
  className: "text-sm text-text-secondary flex items-center gap-2 animate-in fade-in slide-in-from-left-2",
229
338
  style: { animationDelay: `${index * 100}ms`, animationFillMode: "both" },
230
339
  "data-testid": "retrieval-source-item",
231
340
  children: [
232
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-accent flex-shrink-0", "aria-hidden": "true" }),
233
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate", children: source.title })
341
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-accent flex-shrink-0", "aria-hidden": "true" }),
342
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: source.title })
234
343
  ]
235
344
  },
236
345
  source.document_id
@@ -241,21 +350,21 @@ function RetrievalProgress({ sources, isActive, className }) {
241
350
  }
242
351
 
243
352
  // src/streaming/VerificationProgress/VerificationProgress.tsx
244
- var import_jsx_runtime5 = require("react/jsx-runtime");
353
+ var import_jsx_runtime6 = require("react/jsx-runtime");
245
354
  function VerificationProgress({
246
355
  isActive,
247
356
  label = "Checking accuracy...",
248
357
  className
249
358
  }) {
250
359
  if (!isActive) return null;
251
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
360
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
252
361
  "div",
253
362
  {
254
363
  className: `flex items-center gap-2 text-sm ${className ?? ""}`,
255
364
  role: "status",
256
365
  "data-testid": "verification-progress",
257
366
  children: [
258
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
367
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
259
368
  "svg",
260
369
  {
261
370
  className: "w-4 h-4 animate-spin text-accent",
@@ -264,20 +373,20 @@ function VerificationProgress({
264
373
  viewBox: "0 0 24 24",
265
374
  "aria-hidden": "true",
266
375
  children: [
267
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
268
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
376
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
377
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
269
378
  ]
270
379
  }
271
380
  ),
272
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-accent animate-pulse", children: label })
381
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-accent animate-pulse", children: label })
273
382
  ]
274
383
  }
275
384
  );
276
385
  }
277
386
 
278
387
  // src/streaming/TypewriterText/TypewriterText.tsx
279
- var import_react3 = require("react");
280
- var import_jsx_runtime6 = require("react/jsx-runtime");
388
+ var import_react4 = require("react");
389
+ var import_jsx_runtime7 = require("react/jsx-runtime");
281
390
  function TypewriterText({
282
391
  text,
283
392
  speed = 30,
@@ -286,9 +395,9 @@ function TypewriterText({
286
395
  className = "",
287
396
  showCursor = true
288
397
  }) {
289
- const [displayedText, setDisplayedText] = (0, import_react3.useState)("");
290
- const [isComplete, setIsComplete] = (0, import_react3.useState)(false);
291
- (0, import_react3.useEffect)(() => {
398
+ const [displayedText, setDisplayedText] = (0, import_react4.useState)("");
399
+ const [isComplete, setIsComplete] = (0, import_react4.useState)(false);
400
+ (0, import_react4.useEffect)(() => {
292
401
  setDisplayedText("");
293
402
  setIsComplete(false);
294
403
  let index = 0;
@@ -310,16 +419,16 @@ function TypewriterText({
310
419
  clearInterval(interval);
311
420
  };
312
421
  }, [text, speed, delay, onComplete]);
313
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className, children: [
422
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className, children: [
314
423
  displayedText,
315
- showCursor && !isComplete && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "typewriter-cursor", "aria-hidden": "true" })
424
+ showCursor && !isComplete && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "typewriter-cursor", "aria-hidden": "true" })
316
425
  ] });
317
426
  }
318
427
 
319
428
  // src/streaming/TypingIndicator/TypingIndicator.tsx
320
- var import_tailwind_merge = require("tailwind-merge");
429
+ var import_tailwind_merge3 = require("tailwind-merge");
321
430
  var import_hooks2 = require("@surf-kit/hooks");
322
- var import_jsx_runtime7 = require("react/jsx-runtime");
431
+ var import_jsx_runtime8 = require("react/jsx-runtime");
323
432
  var bounceKeyframes = `
324
433
  @keyframes typing-bounce {
325
434
  0%, 80%, 100% { transform: translateY(0); }
@@ -332,17 +441,17 @@ function TypingIndicator({
332
441
  className
333
442
  }) {
334
443
  const reducedMotion = (0, import_hooks2.useReducedMotion)();
335
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
444
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
336
445
  "span",
337
446
  {
338
447
  role: "status",
339
448
  "aria-label": label ?? "typing",
340
- className: (0, import_tailwind_merge.twMerge)("inline-flex items-center gap-2", className),
449
+ className: (0, import_tailwind_merge3.twMerge)("inline-flex items-center gap-2", className),
341
450
  "data-testid": "typing-indicator",
342
451
  children: [
343
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: bounceKeyframes }),
344
- label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm text-text-secondary", children: label }),
345
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "flex gap-1", "data-testid": "typing-dots", children: Array.from({ length: dotCount }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
452
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: bounceKeyframes }),
453
+ label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm text-text-secondary", children: label }),
454
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "flex gap-1", "data-testid": "typing-dots", children: Array.from({ length: dotCount }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
346
455
  "span",
347
456
  {
348
457
  className: "w-2 h-2 rounded-full bg-text-secondary",
@@ -359,9 +468,9 @@ function TypingIndicator({
359
468
  }
360
469
 
361
470
  // src/streaming/TextGlimmer/TextGlimmer.tsx
362
- var import_tailwind_merge2 = require("tailwind-merge");
471
+ var import_tailwind_merge4 = require("tailwind-merge");
363
472
  var import_hooks3 = require("@surf-kit/hooks");
364
- var import_jsx_runtime8 = require("react/jsx-runtime");
473
+ var import_jsx_runtime9 = require("react/jsx-runtime");
365
474
  var shimmerKeyframes = `
366
475
  @keyframes text-shimmer {
367
476
  0% { background-position: 200% 0; }
@@ -371,16 +480,16 @@ var shimmerKeyframes = `
371
480
  var widthPattern = ["100%", "90%", "60%"];
372
481
  function TextGlimmer({ lines = 3, className }) {
373
482
  const reducedMotion = (0, import_hooks3.useReducedMotion)();
374
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
483
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
375
484
  "div",
376
485
  {
377
486
  role: "status",
378
487
  "aria-label": "Loading",
379
- className: (0, import_tailwind_merge2.twMerge)("flex flex-col gap-2", className),
488
+ className: (0, import_tailwind_merge4.twMerge)("flex flex-col gap-2", className),
380
489
  "data-testid": "text-glimmer",
381
490
  children: [
382
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: shimmerKeyframes }),
383
- Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
491
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: shimmerKeyframes }),
492
+ Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
384
493
  "div",
385
494
  {
386
495
  className: "h-3 rounded bg-surface-raised",
@@ -402,9 +511,9 @@ function TextGlimmer({ lines = 3, className }) {
402
511
  }
403
512
 
404
513
  // src/streaming/StreamingList/StreamingList.tsx
405
- var import_tailwind_merge3 = require("tailwind-merge");
514
+ var import_tailwind_merge5 = require("tailwind-merge");
406
515
  var import_hooks4 = require("@surf-kit/hooks");
407
- var import_jsx_runtime9 = require("react/jsx-runtime");
516
+ var import_jsx_runtime10 = require("react/jsx-runtime");
408
517
  var fadeSlideInKeyframes = `
409
518
  @keyframes fadeSlideIn {
410
519
  from { opacity: 0; transform: translateY(8px); }
@@ -420,17 +529,17 @@ function StreamingList({
420
529
  }) {
421
530
  const reducedMotion = (0, import_hooks4.useReducedMotion)();
422
531
  if (items.length === 0 && !isStreaming) {
423
- return emptyMessage ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: (0, import_tailwind_merge3.twMerge)("text-sm text-text-secondary", className), "data-testid": "streaming-list-empty", children: emptyMessage }) : null;
532
+ return emptyMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: (0, import_tailwind_merge5.twMerge)("text-sm text-text-secondary", className), "data-testid": "streaming-list-empty", children: emptyMessage }) : null;
424
533
  }
425
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
534
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
426
535
  "ul",
427
536
  {
428
537
  "aria-live": "polite",
429
- className: (0, import_tailwind_merge3.twMerge)("list-none p-0 m-0", className),
538
+ className: (0, import_tailwind_merge5.twMerge)("list-none p-0 m-0", className),
430
539
  "data-testid": "streaming-list",
431
540
  children: [
432
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: fadeSlideInKeyframes }),
433
- items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
541
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: fadeSlideInKeyframes }),
542
+ items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
434
543
  "li",
435
544
  {
436
545
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
@@ -439,16 +548,16 @@ function StreamingList({
439
548
  },
440
549
  index
441
550
  )),
442
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { "data-testid": "streaming-list-loading", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TypingIndicator, {}) })
551
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("li", { "data-testid": "streaming-list-loading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TypingIndicator, {}) })
443
552
  ]
444
553
  }
445
554
  );
446
555
  }
447
556
 
448
557
  // src/streaming/StreamingStructure/StreamingStructure.tsx
449
- var import_tailwind_merge4 = require("tailwind-merge");
558
+ var import_tailwind_merge6 = require("tailwind-merge");
450
559
  var import_hooks5 = require("@surf-kit/hooks");
451
- var import_jsx_runtime10 = require("react/jsx-runtime");
560
+ var import_jsx_runtime11 = require("react/jsx-runtime");
452
561
  var fadeSlideInKeyframes2 = `
453
562
  @keyframes fadeSlideIn {
454
563
  from { opacity: 0; transform: translateY(8px); }
@@ -457,13 +566,13 @@ var fadeSlideInKeyframes2 = `
457
566
  `;
458
567
  function renderValue(value, reducedMotion) {
459
568
  if (value === null) {
460
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "null" });
569
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "italic text-text-secondary", children: "null" });
461
570
  }
462
571
  if (value === void 0) {
463
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "undefined" });
572
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "italic text-text-secondary", children: "undefined" });
464
573
  }
465
574
  if (Array.isArray(value)) {
466
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ol", { className: "list-decimal pl-4 m-0", children: value.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("li", { className: "text-text-secondary text-sm", children: renderValue(item, reducedMotion) }, i)) });
575
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ol", { className: "list-decimal pl-4 m-0", children: value.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { className: "text-text-secondary text-sm", children: renderValue(item, reducedMotion) }, i)) });
467
576
  }
468
577
  if (typeof value === "object") {
469
578
  return renderNestedDl(value, reducedMotion);
@@ -472,13 +581,13 @@ function renderValue(value, reducedMotion) {
472
581
  }
473
582
  function renderNestedDl(data, reducedMotion) {
474
583
  const entries = Object.entries(data);
475
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dl", { className: "pl-4 m-0", "data-testid": "streaming-structure-nested", children: entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
584
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dl", { className: "pl-4 m-0", "data-testid": "streaming-structure-nested", children: entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
476
585
  "div",
477
586
  {
478
587
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
479
588
  children: [
480
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
481
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
589
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
590
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
482
591
  ]
483
592
  },
484
593
  key
@@ -491,27 +600,27 @@ function StreamingStructure({
491
600
  }) {
492
601
  const reducedMotion = (0, import_hooks5.useReducedMotion)();
493
602
  const entries = Object.entries(data);
494
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
603
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
495
604
  "dl",
496
605
  {
497
606
  "aria-live": "polite",
498
- className: (0, import_tailwind_merge4.twMerge)("m-0", className),
607
+ className: (0, import_tailwind_merge6.twMerge)("m-0", className),
499
608
  "data-testid": "streaming-structure",
500
609
  children: [
501
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: fadeSlideInKeyframes2 }),
502
- entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
610
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: fadeSlideInKeyframes2 }),
611
+ entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
503
612
  "div",
504
613
  {
505
614
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
506
615
  "data-testid": "streaming-structure-entry",
507
616
  children: [
508
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
509
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
617
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
618
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
510
619
  ]
511
620
  },
512
621
  key
513
622
  )),
514
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "streaming-structure-loading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextGlimmer, { lines: 1 }) })
623
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { "data-testid": "streaming-structure-loading", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TextGlimmer, { lines: 1 }) })
515
624
  ]
516
625
  }
517
626
  );