@surf-kit/agent 0.2.2 → 0.4.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 +733 -222
  2. package/dist/chat/index.cjs.map +1 -1
  3. package/dist/chat/index.d.cts +13 -7
  4. package/dist/chat/index.d.ts +13 -7
  5. package/dist/chat/index.js +715 -204
  6. package/dist/chat/index.js.map +1 -1
  7. package/dist/{chat-ChYl2XjV.d.cts → chat-BRY3xGg_.d.cts} +11 -2
  8. package/dist/{chat--OifhIRe.d.ts → chat-CcKc6OAR.d.ts} +11 -2
  9. package/dist/{hooks-BGs8-4GK.d.ts → hooks-BLeiVk-x.d.ts} +22 -5
  10. package/dist/{hooks-DLfF18IU.d.cts → hooks-CSGGLd7j.d.cts} +22 -5
  11. package/dist/hooks.cjs +160 -85
  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 +160 -85
  16. package/dist/hooks.js.map +1 -1
  17. package/dist/index.cjs +794 -283
  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 +758 -247
  22. package/dist/index.js.map +1 -1
  23. package/dist/layouts/index.cjs +754 -243
  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 +733 -222
  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 +100 -15
  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 +99 -14
  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 +213 -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 +183 -73
  48. package/dist/streaming/index.js.map +1 -1
  49. package/dist/{streaming-DfT22A0z.d.cts → streaming-BHPXnwwo.d.cts} +3 -1
  50. package/dist/{streaming-DbQxScpi.d.ts → streaming-C6mbU7My.d.ts} +3 -1
  51. package/package.json +17 -5
@@ -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,87 @@ 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_remark_gfm = __toESM(require("remark-gfm"), 1);
122
+ var import_tailwind_merge = require("tailwind-merge");
104
123
  var import_jsx_runtime = require("react/jsx-runtime");
124
+ function normalizeMarkdownLists(content) {
125
+ return content.replace(/:\s+-\s+/g, ":\n\n- ");
126
+ }
127
+ function ResponseMessage({ content, className }) {
128
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
129
+ "div",
130
+ {
131
+ className: (0, import_tailwind_merge.twMerge)(
132
+ "text-sm leading-relaxed text-text-primary",
133
+ "[&_p]:my-2",
134
+ "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6",
135
+ "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6",
136
+ "[&_li]:my-1",
137
+ "[&_strong]:text-text-primary [&_strong]:font-semibold",
138
+ "[&_em]:text-text-secondary",
139
+ "[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2",
140
+ "[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5",
141
+ "[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1",
142
+ "[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono",
143
+ "[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto",
144
+ "[&_hr]:my-3 [&_hr]:border-border",
145
+ "[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary",
146
+ "[&_table]:w-full [&_table]:text-sm [&_table]:border-collapse [&_table]:my-2",
147
+ "[&_thead]:border-b [&_thead]:border-border",
148
+ "[&_th]:text-left [&_th]:px-2 [&_th]:py-1.5 [&_th]:font-semibold",
149
+ "[&_td]:px-2 [&_td]:py-1.5 [&_td]:border-t [&_td]:border-border/50",
150
+ "[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80",
151
+ className
152
+ ),
153
+ "data-testid": "response-message",
154
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
155
+ import_react_markdown.default,
156
+ {
157
+ remarkPlugins: [import_remark_gfm.default],
158
+ rehypePlugins: [import_rehype_sanitize.default],
159
+ components: {
160
+ script: () => null,
161
+ iframe: () => null,
162
+ p: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "my-2", children }),
163
+ ul: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "my-2 list-disc pl-6", children }),
164
+ ol: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "my-2 list-decimal pl-6", children }),
165
+ li: ({ children, ...props }) => {
166
+ let content2 = children;
167
+ if (props.ordered) {
168
+ content2 = import_react2.default.Children.map(children, (child, i) => {
169
+ if (i === 0 && typeof child === "string") {
170
+ return child.replace(/^\d+[.)]\s*/, "");
171
+ }
172
+ return child;
173
+ });
174
+ }
175
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { className: "my-1", children: content2 });
176
+ },
177
+ strong: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "font-semibold", children }),
178
+ em: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { className: "italic text-text-secondary", children }),
179
+ h1: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-base font-bold mt-4 mb-2", children }),
180
+ h2: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-sm font-bold mt-3 mb-1", children }),
181
+ h3: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-sm font-semibold mt-2 mb-1", children }),
182
+ hr: () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { className: "my-3 border-border" }),
183
+ code: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: "bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono", children }),
184
+ table: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-x-auto my-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: "w-full text-sm border-collapse", children }) }),
185
+ thead: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { className: "border-b border-border", children }),
186
+ th: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "text-left px-2 py-1.5 font-semibold", children }),
187
+ td: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "px-2 py-1.5 border-t border-border/50", children })
188
+ },
189
+ children: normalizeMarkdownLists(content)
190
+ }
191
+ )
192
+ }
193
+ );
194
+ }
195
+
196
+ // src/streaming/StreamingMessage/StreamingMessage.tsx
197
+ var import_jsx_runtime2 = require("react/jsx-runtime");
105
198
  var phaseLabels = {
106
199
  idle: "",
107
200
  waiting: "Waiting...",
@@ -110,72 +203,99 @@ var phaseLabels = {
110
203
  generating: "Writing...",
111
204
  verifying: "Verifying..."
112
205
  };
206
+ var CURSOR_STYLES = `
207
+ .sk-streaming-cursor > :not(ul,ol,blockquote,div:has(table)):last-child::after,
208
+ .sk-streaming-cursor > :is(ul,ol):last-child > li:last-child::after,
209
+ .sk-streaming-cursor > blockquote:last-child > p:last-child::after,
210
+ .sk-streaming-cursor > div:has(table):last-child table tbody tr:last-child td:last-child::after {
211
+ content: "";
212
+ display: inline-block;
213
+ width: 2px;
214
+ height: 1em;
215
+ background: var(--color-accent, #38bdf8);
216
+ animation: sk-cursor-blink 0.8s steps(1) infinite;
217
+ margin-left: 2px;
218
+ vertical-align: text-bottom;
219
+ }
220
+ @keyframes sk-cursor-blink {
221
+ 0%, 60% { opacity: 1; }
222
+ 61%, 100% { opacity: 0; }
223
+ }
224
+ `;
113
225
  function StreamingMessage({
114
226
  stream,
115
227
  onComplete,
228
+ onDraining,
116
229
  showPhases = true,
117
230
  className
118
231
  }) {
119
- const onCompleteRef = (0, import_react2.useRef)(onComplete);
232
+ const onCompleteRef = (0, import_react3.useRef)(onComplete);
120
233
  onCompleteRef.current = onComplete;
121
- const wasActiveRef = (0, import_react2.useRef)(stream.active);
122
- (0, import_react2.useEffect)(() => {
234
+ const onDrainingRef = (0, import_react3.useRef)(onDraining);
235
+ onDrainingRef.current = onDraining;
236
+ const wasActiveRef = (0, import_react3.useRef)(stream.active);
237
+ (0, import_react3.useEffect)(() => {
123
238
  if (wasActiveRef.current && !stream.active) {
124
239
  onCompleteRef.current?.();
125
240
  }
126
241
  wasActiveRef.current = stream.active;
127
242
  }, [stream.active]);
128
243
  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: [
244
+ const { displayed: rawDisplayed, isDraining } = useCharacterDrain(stream.content);
245
+ const displayedContent = stream.active || isDraining ? rawDisplayed.trimEnd() : rawDisplayed;
246
+ (0, import_react3.useEffect)(() => {
247
+ onDrainingRef.current?.(isDraining);
248
+ }, [isDraining]);
249
+ const agentLabel = stream.agent ? stream.agent.replace("_agent", "").replace("_", " ") : null;
250
+ const showPhaseIndicator = showPhases && stream.active && stream.phase !== "idle" && !displayedContent;
251
+ const showCursor = (stream.active || isDraining) && !!displayedContent;
252
+ 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: [
253
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { "aria-live": "assertive", className: "sr-only", children: [
132
254
  stream.active && stream.phase !== "idle" && "Response started",
133
255
  !stream.active && stream.content && "Response complete"
134
256
  ] }),
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)(
257
+ showCursor && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: CURSOR_STYLES }),
258
+ 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 }),
259
+ /* @__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: [
260
+ showPhaseIndicator && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
137
261
  "div",
138
262
  {
139
- className: "flex items-center gap-2 mb-2 text-sm text-text-secondary",
263
+ className: "flex items-center gap-2 text-sm text-text-secondary",
140
264
  "data-testid": "phase-indicator",
141
265
  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 })
266
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
267
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: phaseLabel })
144
268
  ]
145
269
  }
146
270
  ),
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
- ] })
271
+ displayedContent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
272
+ ResponseMessage,
273
+ {
274
+ content: displayedContent,
275
+ className: showCursor ? "sk-streaming-cursor" : void 0
276
+ }
277
+ )
158
278
  ] })
159
279
  ] });
160
280
  }
161
281
 
162
282
  // src/streaming/ThinkingIndicator/ThinkingIndicator.tsx
163
283
  var import_hooks = require("@surf-kit/hooks");
164
- var import_jsx_runtime2 = require("react/jsx-runtime");
284
+ var import_jsx_runtime3 = require("react/jsx-runtime");
165
285
  function ThinkingIndicator({ label = "Thinking...", className }) {
166
286
  const reducedMotion = (0, import_hooks.useReducedMotion)();
167
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
287
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
168
288
  "span",
169
289
  {
170
290
  role: "status",
171
291
  className: `inline-flex items-center gap-2 text-sm motion-safe:animate-fadeSlideUpSm ${className ?? ""}`,
172
292
  "data-testid": "thinking-indicator",
173
293
  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]" })
294
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-text-secondary", children: label }),
295
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex gap-1", "aria-hidden": "true", "data-testid": "animated-dots", children: [
296
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:0ms]" }),
297
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:150ms]" }),
298
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:300ms]" })
179
299
  ] })
180
300
  ]
181
301
  }
@@ -184,7 +304,7 @@ function ThinkingIndicator({ label = "Thinking...", className }) {
184
304
 
185
305
  // src/streaming/ToolExecution/ToolExecution.tsx
186
306
  var import_core2 = require("@surf-kit/core");
187
- var import_jsx_runtime3 = require("react/jsx-runtime");
307
+ var import_jsx_runtime4 = require("react/jsx-runtime");
188
308
  var defaultLabels = {
189
309
  search: "Searching knowledge base...",
190
310
  retrieve: "Retrieving documents...",
@@ -192,15 +312,15 @@ var defaultLabels = {
192
312
  };
193
313
  function ToolExecution({ tool, label, className }) {
194
314
  const displayLabel = label ?? defaultLabels[tool] ?? `Running ${tool}...`;
195
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
315
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
196
316
  "div",
197
317
  {
198
318
  className: `flex items-center gap-2 text-sm text-text-secondary ${className ?? ""}`,
199
319
  role: "status",
200
320
  "data-testid": "tool-execution",
201
321
  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 })
322
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core2.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: displayLabel })
204
324
  ]
205
325
  }
206
326
  );
@@ -208,9 +328,9 @@ function ToolExecution({ tool, label, className }) {
208
328
 
209
329
  // src/streaming/RetrievalProgress/RetrievalProgress.tsx
210
330
  var import_core3 = require("@surf-kit/core");
211
- var import_jsx_runtime4 = require("react/jsx-runtime");
331
+ var import_jsx_runtime5 = require("react/jsx-runtime");
212
332
  function RetrievalProgress({ sources, isActive, className }) {
213
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
333
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
214
334
  "div",
215
335
  {
216
336
  className: `space-y-2 ${className ?? ""}`,
@@ -218,19 +338,19 @@ function RetrievalProgress({ sources, isActive, className }) {
218
338
  "aria-label": isActive ? `Retrieving sources, ${sources.length} found so far` : `${sources.length} sources found`,
219
339
  "data-testid": "retrieval-progress",
220
340
  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..." })
341
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-sm text-text-secondary", children: [
342
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core3.WaveLoader, { size: "sm", color: "#38bdf8" }) }),
343
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Retrieving sources..." })
224
344
  ] }),
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)(
345
+ 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
346
  "li",
227
347
  {
228
348
  className: "text-sm text-text-secondary flex items-center gap-2 animate-in fade-in slide-in-from-left-2",
229
349
  style: { animationDelay: `${index * 100}ms`, animationFillMode: "both" },
230
350
  "data-testid": "retrieval-source-item",
231
351
  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 })
352
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-accent flex-shrink-0", "aria-hidden": "true" }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: source.title })
234
354
  ]
235
355
  },
236
356
  source.document_id
@@ -241,21 +361,21 @@ function RetrievalProgress({ sources, isActive, className }) {
241
361
  }
242
362
 
243
363
  // src/streaming/VerificationProgress/VerificationProgress.tsx
244
- var import_jsx_runtime5 = require("react/jsx-runtime");
364
+ var import_jsx_runtime6 = require("react/jsx-runtime");
245
365
  function VerificationProgress({
246
366
  isActive,
247
367
  label = "Checking accuracy...",
248
368
  className
249
369
  }) {
250
370
  if (!isActive) return null;
251
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
371
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
252
372
  "div",
253
373
  {
254
374
  className: `flex items-center gap-2 text-sm ${className ?? ""}`,
255
375
  role: "status",
256
376
  "data-testid": "verification-progress",
257
377
  children: [
258
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
378
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
259
379
  "svg",
260
380
  {
261
381
  className: "w-4 h-4 animate-spin text-accent",
@@ -264,20 +384,20 @@ function VerificationProgress({
264
384
  viewBox: "0 0 24 24",
265
385
  "aria-hidden": "true",
266
386
  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" })
387
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
388
+ /* @__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
389
  ]
270
390
  }
271
391
  ),
272
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-accent animate-pulse", children: label })
392
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-accent animate-pulse", children: label })
273
393
  ]
274
394
  }
275
395
  );
276
396
  }
277
397
 
278
398
  // src/streaming/TypewriterText/TypewriterText.tsx
279
- var import_react3 = require("react");
280
- var import_jsx_runtime6 = require("react/jsx-runtime");
399
+ var import_react4 = require("react");
400
+ var import_jsx_runtime7 = require("react/jsx-runtime");
281
401
  function TypewriterText({
282
402
  text,
283
403
  speed = 30,
@@ -286,9 +406,9 @@ function TypewriterText({
286
406
  className = "",
287
407
  showCursor = true
288
408
  }) {
289
- const [displayedText, setDisplayedText] = (0, import_react3.useState)("");
290
- const [isComplete, setIsComplete] = (0, import_react3.useState)(false);
291
- (0, import_react3.useEffect)(() => {
409
+ const [displayedText, setDisplayedText] = (0, import_react4.useState)("");
410
+ const [isComplete, setIsComplete] = (0, import_react4.useState)(false);
411
+ (0, import_react4.useEffect)(() => {
292
412
  setDisplayedText("");
293
413
  setIsComplete(false);
294
414
  let index = 0;
@@ -310,16 +430,16 @@ function TypewriterText({
310
430
  clearInterval(interval);
311
431
  };
312
432
  }, [text, speed, delay, onComplete]);
313
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className, children: [
433
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className, children: [
314
434
  displayedText,
315
- showCursor && !isComplete && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "typewriter-cursor", "aria-hidden": "true" })
435
+ showCursor && !isComplete && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "typewriter-cursor", "aria-hidden": "true" })
316
436
  ] });
317
437
  }
318
438
 
319
439
  // src/streaming/TypingIndicator/TypingIndicator.tsx
320
- var import_tailwind_merge = require("tailwind-merge");
440
+ var import_tailwind_merge3 = require("tailwind-merge");
321
441
  var import_hooks2 = require("@surf-kit/hooks");
322
- var import_jsx_runtime7 = require("react/jsx-runtime");
442
+ var import_jsx_runtime8 = require("react/jsx-runtime");
323
443
  var bounceKeyframes = `
324
444
  @keyframes typing-bounce {
325
445
  0%, 80%, 100% { transform: translateY(0); }
@@ -332,17 +452,17 @@ function TypingIndicator({
332
452
  className
333
453
  }) {
334
454
  const reducedMotion = (0, import_hooks2.useReducedMotion)();
335
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
455
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
336
456
  "span",
337
457
  {
338
458
  role: "status",
339
459
  "aria-label": label ?? "typing",
340
- className: (0, import_tailwind_merge.twMerge)("inline-flex items-center gap-2", className),
460
+ className: (0, import_tailwind_merge3.twMerge)("inline-flex items-center gap-2", className),
341
461
  "data-testid": "typing-indicator",
342
462
  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)(
463
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: bounceKeyframes }),
464
+ label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm text-text-secondary", children: label }),
465
+ /* @__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
466
  "span",
347
467
  {
348
468
  className: "w-2 h-2 rounded-full bg-text-secondary",
@@ -359,9 +479,9 @@ function TypingIndicator({
359
479
  }
360
480
 
361
481
  // src/streaming/TextGlimmer/TextGlimmer.tsx
362
- var import_tailwind_merge2 = require("tailwind-merge");
482
+ var import_tailwind_merge4 = require("tailwind-merge");
363
483
  var import_hooks3 = require("@surf-kit/hooks");
364
- var import_jsx_runtime8 = require("react/jsx-runtime");
484
+ var import_jsx_runtime9 = require("react/jsx-runtime");
365
485
  var shimmerKeyframes = `
366
486
  @keyframes text-shimmer {
367
487
  0% { background-position: 200% 0; }
@@ -371,16 +491,16 @@ var shimmerKeyframes = `
371
491
  var widthPattern = ["100%", "90%", "60%"];
372
492
  function TextGlimmer({ lines = 3, className }) {
373
493
  const reducedMotion = (0, import_hooks3.useReducedMotion)();
374
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
494
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
375
495
  "div",
376
496
  {
377
497
  role: "status",
378
498
  "aria-label": "Loading",
379
- className: (0, import_tailwind_merge2.twMerge)("flex flex-col gap-2", className),
499
+ className: (0, import_tailwind_merge4.twMerge)("flex flex-col gap-2", className),
380
500
  "data-testid": "text-glimmer",
381
501
  children: [
382
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: shimmerKeyframes }),
383
- Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
502
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: shimmerKeyframes }),
503
+ Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
384
504
  "div",
385
505
  {
386
506
  className: "h-3 rounded bg-surface-raised",
@@ -402,9 +522,9 @@ function TextGlimmer({ lines = 3, className }) {
402
522
  }
403
523
 
404
524
  // src/streaming/StreamingList/StreamingList.tsx
405
- var import_tailwind_merge3 = require("tailwind-merge");
525
+ var import_tailwind_merge5 = require("tailwind-merge");
406
526
  var import_hooks4 = require("@surf-kit/hooks");
407
- var import_jsx_runtime9 = require("react/jsx-runtime");
527
+ var import_jsx_runtime10 = require("react/jsx-runtime");
408
528
  var fadeSlideInKeyframes = `
409
529
  @keyframes fadeSlideIn {
410
530
  from { opacity: 0; transform: translateY(8px); }
@@ -420,17 +540,17 @@ function StreamingList({
420
540
  }) {
421
541
  const reducedMotion = (0, import_hooks4.useReducedMotion)();
422
542
  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;
543
+ 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
544
  }
425
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
545
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
426
546
  "ul",
427
547
  {
428
548
  "aria-live": "polite",
429
- className: (0, import_tailwind_merge3.twMerge)("list-none p-0 m-0", className),
549
+ className: (0, import_tailwind_merge5.twMerge)("list-none p-0 m-0", className),
430
550
  "data-testid": "streaming-list",
431
551
  children: [
432
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: fadeSlideInKeyframes }),
433
- items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
552
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: fadeSlideInKeyframes }),
553
+ items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
434
554
  "li",
435
555
  {
436
556
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
@@ -439,16 +559,16 @@ function StreamingList({
439
559
  },
440
560
  index
441
561
  )),
442
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { "data-testid": "streaming-list-loading", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TypingIndicator, {}) })
562
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("li", { "data-testid": "streaming-list-loading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TypingIndicator, {}) })
443
563
  ]
444
564
  }
445
565
  );
446
566
  }
447
567
 
448
568
  // src/streaming/StreamingStructure/StreamingStructure.tsx
449
- var import_tailwind_merge4 = require("tailwind-merge");
569
+ var import_tailwind_merge6 = require("tailwind-merge");
450
570
  var import_hooks5 = require("@surf-kit/hooks");
451
- var import_jsx_runtime10 = require("react/jsx-runtime");
571
+ var import_jsx_runtime11 = require("react/jsx-runtime");
452
572
  var fadeSlideInKeyframes2 = `
453
573
  @keyframes fadeSlideIn {
454
574
  from { opacity: 0; transform: translateY(8px); }
@@ -457,13 +577,13 @@ var fadeSlideInKeyframes2 = `
457
577
  `;
458
578
  function renderValue(value, reducedMotion) {
459
579
  if (value === null) {
460
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "null" });
580
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "italic text-text-secondary", children: "null" });
461
581
  }
462
582
  if (value === void 0) {
463
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "undefined" });
583
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "italic text-text-secondary", children: "undefined" });
464
584
  }
465
585
  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)) });
586
+ 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
587
  }
468
588
  if (typeof value === "object") {
469
589
  return renderNestedDl(value, reducedMotion);
@@ -472,13 +592,13 @@ function renderValue(value, reducedMotion) {
472
592
  }
473
593
  function renderNestedDl(data, reducedMotion) {
474
594
  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)(
595
+ 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
596
  "div",
477
597
  {
478
598
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
479
599
  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) })
600
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
601
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
482
602
  ]
483
603
  },
484
604
  key
@@ -491,27 +611,27 @@ function StreamingStructure({
491
611
  }) {
492
612
  const reducedMotion = (0, import_hooks5.useReducedMotion)();
493
613
  const entries = Object.entries(data);
494
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
614
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
495
615
  "dl",
496
616
  {
497
617
  "aria-live": "polite",
498
- className: (0, import_tailwind_merge4.twMerge)("m-0", className),
618
+ className: (0, import_tailwind_merge6.twMerge)("m-0", className),
499
619
  "data-testid": "streaming-structure",
500
620
  children: [
501
- !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: fadeSlideInKeyframes2 }),
502
- entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
621
+ !reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: fadeSlideInKeyframes2 }),
622
+ entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
503
623
  "div",
504
624
  {
505
625
  style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
506
626
  "data-testid": "streaming-structure-entry",
507
627
  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) })
628
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
629
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
510
630
  ]
511
631
  },
512
632
  key
513
633
  )),
514
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "streaming-structure-loading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextGlimmer, { lines: 1 }) })
634
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { "data-testid": "streaming-structure-loading", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TextGlimmer, { lines: 1 }) })
515
635
  ]
516
636
  }
517
637
  );