@surf-kit/agent 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -1
- package/dist/agent-BNSmiexZ.d.cts +44 -0
- package/dist/agent-BNSmiexZ.d.ts +44 -0
- package/dist/agent-identity/index.cjs +157 -0
- package/dist/agent-identity/index.cjs.map +1 -0
- package/dist/agent-identity/index.d.cts +35 -0
- package/dist/agent-identity/index.d.ts +35 -0
- package/dist/agent-identity/index.js +127 -0
- package/dist/agent-identity/index.js.map +1 -0
- package/dist/chat/index.cjs +1281 -0
- package/dist/chat/index.cjs.map +1 -0
- package/dist/chat/index.d.cts +72 -0
- package/dist/chat/index.d.ts +72 -0
- package/dist/chat/index.js +1239 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat--OifhIRe.d.ts +24 -0
- package/dist/chat-ChYl2XjV.d.cts +24 -0
- package/dist/confidence/index.cjs +253 -0
- package/dist/confidence/index.cjs.map +1 -0
- package/dist/confidence/index.d.cts +40 -0
- package/dist/confidence/index.d.ts +40 -0
- package/dist/confidence/index.js +222 -0
- package/dist/confidence/index.js.map +1 -0
- package/dist/feedback/index.cjs +186 -0
- package/dist/feedback/index.cjs.map +1 -0
- package/dist/feedback/index.d.cts +27 -0
- package/dist/feedback/index.d.ts +27 -0
- package/dist/feedback/index.js +157 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/{hooks-B8CSeOsn.d.cts → hooks-BGs8-4GK.d.ts} +4 -99
- package/dist/{hooks-B8CSeOsn.d.ts → hooks-DLfF18IU.d.cts} +4 -99
- package/dist/hooks.d.cts +4 -1
- package/dist/hooks.d.ts +4 -1
- package/dist/index-BazLnae1.d.cts +67 -0
- package/dist/index-BazLnae1.d.ts +67 -0
- package/dist/index.cjs +889 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -321
- package/dist/index.d.ts +15 -321
- package/dist/index.js +879 -142
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.cjs +1588 -0
- package/dist/layouts/index.cjs.map +1 -0
- package/dist/layouts/index.d.cts +46 -0
- package/dist/layouts/index.d.ts +46 -0
- package/dist/layouts/index.js +1548 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/mcp/index.cjs +522 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +2 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +492 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/response/index.cjs +519 -0
- package/dist/response/index.cjs.map +1 -0
- package/dist/response/index.d.cts +44 -0
- package/dist/response/index.d.ts +44 -0
- package/dist/response/index.js +478 -0
- package/dist/response/index.js.map +1 -0
- package/dist/sources/index.cjs +243 -0
- package/dist/sources/index.cjs.map +1 -0
- package/dist/sources/index.d.cts +44 -0
- package/dist/sources/index.d.ts +44 -0
- package/dist/sources/index.js +212 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/streaming/index.cjs +531 -0
- package/dist/streaming/index.cjs.map +1 -0
- package/dist/streaming/index.d.cts +81 -0
- package/dist/streaming/index.d.ts +81 -0
- package/dist/streaming/index.js +495 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming-DbQxScpi.d.ts +39 -0
- package/dist/streaming-DfT22A0z.d.cts +39 -0
- package/package.json +62 -17
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/streaming/index.ts
|
|
21
|
+
var streaming_exports = {};
|
|
22
|
+
__export(streaming_exports, {
|
|
23
|
+
RetrievalProgress: () => RetrievalProgress,
|
|
24
|
+
StreamingList: () => StreamingList,
|
|
25
|
+
StreamingMessage: () => StreamingMessage,
|
|
26
|
+
StreamingStructure: () => StreamingStructure,
|
|
27
|
+
TextGlimmer: () => TextGlimmer,
|
|
28
|
+
ThinkingIndicator: () => ThinkingIndicator,
|
|
29
|
+
ToolExecution: () => ToolExecution,
|
|
30
|
+
TypewriterText: () => TypewriterText,
|
|
31
|
+
TypingIndicator: () => TypingIndicator,
|
|
32
|
+
VerificationProgress: () => VerificationProgress
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(streaming_exports);
|
|
35
|
+
|
|
36
|
+
// src/streaming/StreamingMessage/StreamingMessage.tsx
|
|
37
|
+
var import_react2 = require("react");
|
|
38
|
+
var import_core = require("@surf-kit/core");
|
|
39
|
+
|
|
40
|
+
// src/hooks/useCharacterDrain.ts
|
|
41
|
+
var import_react = require("react");
|
|
42
|
+
function useCharacterDrain(target, msPerChar = 15) {
|
|
43
|
+
const [displayed, setDisplayed] = (0, import_react.useState)("");
|
|
44
|
+
const indexRef = (0, import_react.useRef)(0);
|
|
45
|
+
const lastTimeRef = (0, import_react.useRef)(0);
|
|
46
|
+
const rafRef = (0, import_react.useRef)(null);
|
|
47
|
+
const drainTargetRef = (0, import_react.useRef)("");
|
|
48
|
+
const msPerCharRef = (0, import_react.useRef)(msPerChar);
|
|
49
|
+
msPerCharRef.current = msPerChar;
|
|
50
|
+
if (target !== "") {
|
|
51
|
+
drainTargetRef.current = target;
|
|
52
|
+
}
|
|
53
|
+
const drainTarget = drainTargetRef.current;
|
|
54
|
+
const isDraining = displayed.length < drainTarget.length;
|
|
55
|
+
const tickRef = (0, import_react.useRef)(() => {
|
|
56
|
+
});
|
|
57
|
+
tickRef.current = (now) => {
|
|
58
|
+
const currentTarget = drainTargetRef.current;
|
|
59
|
+
if (currentTarget === "") {
|
|
60
|
+
rafRef.current = null;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (lastTimeRef.current === 0) lastTimeRef.current = now;
|
|
64
|
+
const elapsed = now - lastTimeRef.current;
|
|
65
|
+
const charsToAdvance = Math.floor(elapsed / msPerCharRef.current);
|
|
66
|
+
if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {
|
|
67
|
+
const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length);
|
|
68
|
+
indexRef.current = nextIndex;
|
|
69
|
+
lastTimeRef.current = now;
|
|
70
|
+
setDisplayed(currentTarget.slice(0, nextIndex));
|
|
71
|
+
}
|
|
72
|
+
if (indexRef.current < currentTarget.length) {
|
|
73
|
+
rafRef.current = requestAnimationFrame((t) => tickRef.current(t));
|
|
74
|
+
} else {
|
|
75
|
+
rafRef.current = null;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
(0, import_react.useEffect)(() => {
|
|
79
|
+
if (drainTargetRef.current !== "" && indexRef.current < drainTargetRef.current.length && rafRef.current === null) {
|
|
80
|
+
rafRef.current = requestAnimationFrame((t) => tickRef.current(t));
|
|
81
|
+
}
|
|
82
|
+
}, [drainTarget]);
|
|
83
|
+
(0, import_react.useEffect)(() => {
|
|
84
|
+
if (target === "" && !isDraining && displayed !== "") {
|
|
85
|
+
indexRef.current = 0;
|
|
86
|
+
lastTimeRef.current = 0;
|
|
87
|
+
drainTargetRef.current = "";
|
|
88
|
+
setDisplayed("");
|
|
89
|
+
}
|
|
90
|
+
}, [target, isDraining, displayed]);
|
|
91
|
+
(0, import_react.useEffect)(() => {
|
|
92
|
+
return () => {
|
|
93
|
+
if (rafRef.current !== null) {
|
|
94
|
+
cancelAnimationFrame(rafRef.current);
|
|
95
|
+
rafRef.current = null;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}, []);
|
|
99
|
+
return { displayed, isDraining };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/streaming/StreamingMessage/StreamingMessage.tsx
|
|
103
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
104
|
+
var phaseLabels = {
|
|
105
|
+
idle: "",
|
|
106
|
+
waiting: "Waiting...",
|
|
107
|
+
thinking: "Thinking...",
|
|
108
|
+
retrieving: "Searching...",
|
|
109
|
+
generating: "Writing...",
|
|
110
|
+
verifying: "Verifying..."
|
|
111
|
+
};
|
|
112
|
+
function StreamingMessage({
|
|
113
|
+
stream,
|
|
114
|
+
onComplete,
|
|
115
|
+
showPhases = true,
|
|
116
|
+
className
|
|
117
|
+
}) {
|
|
118
|
+
const onCompleteRef = (0, import_react2.useRef)(onComplete);
|
|
119
|
+
onCompleteRef.current = onComplete;
|
|
120
|
+
const wasActiveRef = (0, import_react2.useRef)(stream.active);
|
|
121
|
+
(0, import_react2.useEffect)(() => {
|
|
122
|
+
if (wasActiveRef.current && !stream.active) {
|
|
123
|
+
onCompleteRef.current?.();
|
|
124
|
+
}
|
|
125
|
+
wasActiveRef.current = stream.active;
|
|
126
|
+
}, [stream.active]);
|
|
127
|
+
const phaseLabel = phaseLabels[stream.phase];
|
|
128
|
+
const { displayed: displayedContent } = useCharacterDrain(stream.content);
|
|
129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, "data-testid": "streaming-message", children: [
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "aria-live": "assertive", className: "sr-only", children: [
|
|
131
|
+
stream.active && stream.phase !== "idle" && "Response started",
|
|
132
|
+
!stream.active && stream.content && "Response complete"
|
|
133
|
+
] }),
|
|
134
|
+
/* @__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: [
|
|
135
|
+
showPhases && stream.active && stream.phase !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
136
|
+
"div",
|
|
137
|
+
{
|
|
138
|
+
className: "flex items-center gap-2 mb-2 text-sm text-text-secondary",
|
|
139
|
+
"data-testid": "phase-indicator",
|
|
140
|
+
children: [
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Spinner, { size: "sm" }) }),
|
|
142
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: phaseLabel })
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
),
|
|
146
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-sm leading-relaxed text-text-primary whitespace-pre-wrap", children: [
|
|
147
|
+
displayedContent,
|
|
148
|
+
stream.active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
149
|
+
"span",
|
|
150
|
+
{
|
|
151
|
+
className: "inline-block w-0.5 h-4 bg-accent align-text-bottom animate-pulse ml-0.5",
|
|
152
|
+
"aria-hidden": "true",
|
|
153
|
+
"data-testid": "streaming-cursor"
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
] })
|
|
157
|
+
] })
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/streaming/ThinkingIndicator/ThinkingIndicator.tsx
|
|
162
|
+
var import_hooks = require("@surf-kit/hooks");
|
|
163
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
164
|
+
function ThinkingIndicator({ label = "Thinking...", className }) {
|
|
165
|
+
const reducedMotion = (0, import_hooks.useReducedMotion)();
|
|
166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
167
|
+
"span",
|
|
168
|
+
{
|
|
169
|
+
role: "status",
|
|
170
|
+
className: `inline-flex items-center gap-2 text-sm motion-safe:animate-fadeSlideUpSm ${className ?? ""}`,
|
|
171
|
+
"data-testid": "thinking-indicator",
|
|
172
|
+
children: [
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-text-secondary", children: label }),
|
|
174
|
+
!reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex gap-1", "aria-hidden": "true", "data-testid": "animated-dots", children: [
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:0ms]" }),
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:150ms]" }),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:300ms]" })
|
|
178
|
+
] })
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/streaming/ToolExecution/ToolExecution.tsx
|
|
185
|
+
var import_core2 = require("@surf-kit/core");
|
|
186
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
187
|
+
var defaultLabels = {
|
|
188
|
+
search: "Searching knowledge base...",
|
|
189
|
+
retrieve: "Retrieving documents...",
|
|
190
|
+
calculate: "Calculating..."
|
|
191
|
+
};
|
|
192
|
+
function ToolExecution({ tool, label, className }) {
|
|
193
|
+
const displayLabel = label ?? defaultLabels[tool] ?? `Running ${tool}...`;
|
|
194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
195
|
+
"div",
|
|
196
|
+
{
|
|
197
|
+
className: `flex items-center gap-2 text-sm text-text-secondary ${className ?? ""}`,
|
|
198
|
+
role: "status",
|
|
199
|
+
"data-testid": "tool-execution",
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core2.Spinner, { size: "sm" }) }),
|
|
202
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: displayLabel })
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/streaming/RetrievalProgress/RetrievalProgress.tsx
|
|
209
|
+
var import_core3 = require("@surf-kit/core");
|
|
210
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
211
|
+
function RetrievalProgress({ sources, isActive, className }) {
|
|
212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
213
|
+
"div",
|
|
214
|
+
{
|
|
215
|
+
className: `space-y-2 ${className ?? ""}`,
|
|
216
|
+
role: "status",
|
|
217
|
+
"aria-label": isActive ? `Retrieving sources, ${sources.length} found so far` : `${sources.length} sources found`,
|
|
218
|
+
"data-testid": "retrieval-progress",
|
|
219
|
+
children: [
|
|
220
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 text-sm text-text-secondary", children: [
|
|
221
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core3.Spinner, { size: "sm" }) }),
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Retrieving sources..." })
|
|
223
|
+
] }),
|
|
224
|
+
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)(
|
|
225
|
+
"li",
|
|
226
|
+
{
|
|
227
|
+
className: "text-sm text-text-secondary flex items-center gap-2 animate-in fade-in slide-in-from-left-2",
|
|
228
|
+
style: { animationDelay: `${index * 100}ms`, animationFillMode: "both" },
|
|
229
|
+
"data-testid": "retrieval-source-item",
|
|
230
|
+
children: [
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-accent flex-shrink-0", "aria-hidden": "true" }),
|
|
232
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate", children: source.title })
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
source.document_id
|
|
236
|
+
)) })
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/streaming/VerificationProgress/VerificationProgress.tsx
|
|
243
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
244
|
+
function VerificationProgress({
|
|
245
|
+
isActive,
|
|
246
|
+
label = "Checking accuracy...",
|
|
247
|
+
className
|
|
248
|
+
}) {
|
|
249
|
+
if (!isActive) return null;
|
|
250
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
251
|
+
"div",
|
|
252
|
+
{
|
|
253
|
+
className: `flex items-center gap-2 text-sm ${className ?? ""}`,
|
|
254
|
+
role: "status",
|
|
255
|
+
"data-testid": "verification-progress",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
258
|
+
"svg",
|
|
259
|
+
{
|
|
260
|
+
className: "w-4 h-4 animate-spin text-accent",
|
|
261
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
262
|
+
fill: "none",
|
|
263
|
+
viewBox: "0 0 24 24",
|
|
264
|
+
"aria-hidden": "true",
|
|
265
|
+
children: [
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
267
|
+
/* @__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" })
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
),
|
|
271
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-accent animate-pulse", children: label })
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/streaming/TypewriterText/TypewriterText.tsx
|
|
278
|
+
var import_react3 = require("react");
|
|
279
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
280
|
+
function TypewriterText({
|
|
281
|
+
text,
|
|
282
|
+
speed = 30,
|
|
283
|
+
delay = 0,
|
|
284
|
+
onComplete,
|
|
285
|
+
className = "",
|
|
286
|
+
showCursor = true
|
|
287
|
+
}) {
|
|
288
|
+
const [displayedText, setDisplayedText] = (0, import_react3.useState)("");
|
|
289
|
+
const [isComplete, setIsComplete] = (0, import_react3.useState)(false);
|
|
290
|
+
(0, import_react3.useEffect)(() => {
|
|
291
|
+
setDisplayedText("");
|
|
292
|
+
setIsComplete(false);
|
|
293
|
+
let index = 0;
|
|
294
|
+
let interval;
|
|
295
|
+
const timeout = setTimeout(() => {
|
|
296
|
+
interval = setInterval(() => {
|
|
297
|
+
if (index < text.length) {
|
|
298
|
+
setDisplayedText(text.slice(0, index + 1));
|
|
299
|
+
index++;
|
|
300
|
+
} else {
|
|
301
|
+
clearInterval(interval);
|
|
302
|
+
setIsComplete(true);
|
|
303
|
+
onComplete?.();
|
|
304
|
+
}
|
|
305
|
+
}, speed);
|
|
306
|
+
}, delay);
|
|
307
|
+
return () => {
|
|
308
|
+
clearTimeout(timeout);
|
|
309
|
+
clearInterval(interval);
|
|
310
|
+
};
|
|
311
|
+
}, [text, speed, delay, onComplete]);
|
|
312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className, children: [
|
|
313
|
+
displayedText,
|
|
314
|
+
showCursor && !isComplete && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "typewriter-cursor", "aria-hidden": "true" })
|
|
315
|
+
] });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// src/streaming/TypingIndicator/TypingIndicator.tsx
|
|
319
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
320
|
+
var import_hooks2 = require("@surf-kit/hooks");
|
|
321
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
322
|
+
var bounceKeyframes = `
|
|
323
|
+
@keyframes typing-bounce {
|
|
324
|
+
0%, 80%, 100% { transform: translateY(0); }
|
|
325
|
+
40% { transform: translateY(-6px); }
|
|
326
|
+
}
|
|
327
|
+
`;
|
|
328
|
+
function TypingIndicator({
|
|
329
|
+
label,
|
|
330
|
+
dotCount = 3,
|
|
331
|
+
className
|
|
332
|
+
}) {
|
|
333
|
+
const reducedMotion = (0, import_hooks2.useReducedMotion)();
|
|
334
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
335
|
+
"span",
|
|
336
|
+
{
|
|
337
|
+
role: "status",
|
|
338
|
+
"aria-label": label ?? "typing",
|
|
339
|
+
className: (0, import_tailwind_merge.twMerge)("inline-flex items-center gap-2", className),
|
|
340
|
+
"data-testid": "typing-indicator",
|
|
341
|
+
children: [
|
|
342
|
+
!reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: bounceKeyframes }),
|
|
343
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm text-text-secondary", children: label }),
|
|
344
|
+
/* @__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)(
|
|
345
|
+
"span",
|
|
346
|
+
{
|
|
347
|
+
className: "w-2 h-2 rounded-full bg-text-secondary",
|
|
348
|
+
style: reducedMotion ? void 0 : {
|
|
349
|
+
animation: "typing-bounce 1.4s infinite ease-in-out",
|
|
350
|
+
animationDelay: `${i * 160}ms`
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
i
|
|
354
|
+
)) })
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/streaming/TextGlimmer/TextGlimmer.tsx
|
|
361
|
+
var import_tailwind_merge2 = require("tailwind-merge");
|
|
362
|
+
var import_hooks3 = require("@surf-kit/hooks");
|
|
363
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
364
|
+
var shimmerKeyframes = `
|
|
365
|
+
@keyframes text-shimmer {
|
|
366
|
+
0% { background-position: 200% 0; }
|
|
367
|
+
100% { background-position: -200% 0; }
|
|
368
|
+
}
|
|
369
|
+
`;
|
|
370
|
+
var widthPattern = ["100%", "90%", "60%"];
|
|
371
|
+
function TextGlimmer({ lines = 3, className }) {
|
|
372
|
+
const reducedMotion = (0, import_hooks3.useReducedMotion)();
|
|
373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
374
|
+
"div",
|
|
375
|
+
{
|
|
376
|
+
role: "status",
|
|
377
|
+
"aria-label": "Loading",
|
|
378
|
+
className: (0, import_tailwind_merge2.twMerge)("flex flex-col gap-2", className),
|
|
379
|
+
"data-testid": "text-glimmer",
|
|
380
|
+
children: [
|
|
381
|
+
!reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: shimmerKeyframes }),
|
|
382
|
+
Array.from({ length: lines }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
383
|
+
"div",
|
|
384
|
+
{
|
|
385
|
+
className: "h-3 rounded bg-surface-raised",
|
|
386
|
+
style: {
|
|
387
|
+
width: widthPattern[i % widthPattern.length],
|
|
388
|
+
...reducedMotion ? void 0 : {
|
|
389
|
+
backgroundImage: "linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent)",
|
|
390
|
+
backgroundSize: "200% 100%",
|
|
391
|
+
animation: "text-shimmer 1.5s infinite ease-in-out"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
"data-testid": "glimmer-line"
|
|
395
|
+
},
|
|
396
|
+
i
|
|
397
|
+
))
|
|
398
|
+
]
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/streaming/StreamingList/StreamingList.tsx
|
|
404
|
+
var import_tailwind_merge3 = require("tailwind-merge");
|
|
405
|
+
var import_hooks4 = require("@surf-kit/hooks");
|
|
406
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
407
|
+
var fadeSlideInKeyframes = `
|
|
408
|
+
@keyframes fadeSlideIn {
|
|
409
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
410
|
+
to { opacity: 1; transform: translateY(0); }
|
|
411
|
+
}
|
|
412
|
+
`;
|
|
413
|
+
function StreamingList({
|
|
414
|
+
items,
|
|
415
|
+
renderItem,
|
|
416
|
+
isStreaming = false,
|
|
417
|
+
className,
|
|
418
|
+
emptyMessage
|
|
419
|
+
}) {
|
|
420
|
+
const reducedMotion = (0, import_hooks4.useReducedMotion)();
|
|
421
|
+
if (items.length === 0 && !isStreaming) {
|
|
422
|
+
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;
|
|
423
|
+
}
|
|
424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
425
|
+
"ul",
|
|
426
|
+
{
|
|
427
|
+
"aria-live": "polite",
|
|
428
|
+
className: (0, import_tailwind_merge3.twMerge)("list-none p-0 m-0", className),
|
|
429
|
+
"data-testid": "streaming-list",
|
|
430
|
+
children: [
|
|
431
|
+
!reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: fadeSlideInKeyframes }),
|
|
432
|
+
items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
433
|
+
"li",
|
|
434
|
+
{
|
|
435
|
+
style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
|
|
436
|
+
"data-testid": "streaming-list-item",
|
|
437
|
+
children: renderItem(item, index)
|
|
438
|
+
},
|
|
439
|
+
index
|
|
440
|
+
)),
|
|
441
|
+
isStreaming && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { "data-testid": "streaming-list-loading", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TypingIndicator, {}) })
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/streaming/StreamingStructure/StreamingStructure.tsx
|
|
448
|
+
var import_tailwind_merge4 = require("tailwind-merge");
|
|
449
|
+
var import_hooks5 = require("@surf-kit/hooks");
|
|
450
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
451
|
+
var fadeSlideInKeyframes2 = `
|
|
452
|
+
@keyframes fadeSlideIn {
|
|
453
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
454
|
+
to { opacity: 1; transform: translateY(0); }
|
|
455
|
+
}
|
|
456
|
+
`;
|
|
457
|
+
function renderValue(value, reducedMotion) {
|
|
458
|
+
if (value === null) {
|
|
459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "null" });
|
|
460
|
+
}
|
|
461
|
+
if (value === void 0) {
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "italic text-text-secondary", children: "undefined" });
|
|
463
|
+
}
|
|
464
|
+
if (Array.isArray(value)) {
|
|
465
|
+
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)) });
|
|
466
|
+
}
|
|
467
|
+
if (typeof value === "object") {
|
|
468
|
+
return renderNestedDl(value, reducedMotion);
|
|
469
|
+
}
|
|
470
|
+
return String(value);
|
|
471
|
+
}
|
|
472
|
+
function renderNestedDl(data, reducedMotion) {
|
|
473
|
+
const entries = Object.entries(data);
|
|
474
|
+
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)(
|
|
475
|
+
"div",
|
|
476
|
+
{
|
|
477
|
+
style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
|
|
478
|
+
children: [
|
|
479
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
|
|
480
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
|
|
481
|
+
]
|
|
482
|
+
},
|
|
483
|
+
key
|
|
484
|
+
)) });
|
|
485
|
+
}
|
|
486
|
+
function StreamingStructure({
|
|
487
|
+
data,
|
|
488
|
+
isStreaming = false,
|
|
489
|
+
className
|
|
490
|
+
}) {
|
|
491
|
+
const reducedMotion = (0, import_hooks5.useReducedMotion)();
|
|
492
|
+
const entries = Object.entries(data);
|
|
493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
494
|
+
"dl",
|
|
495
|
+
{
|
|
496
|
+
"aria-live": "polite",
|
|
497
|
+
className: (0, import_tailwind_merge4.twMerge)("m-0", className),
|
|
498
|
+
"data-testid": "streaming-structure",
|
|
499
|
+
children: [
|
|
500
|
+
!reducedMotion && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: fadeSlideInKeyframes2 }),
|
|
501
|
+
entries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
502
|
+
"div",
|
|
503
|
+
{
|
|
504
|
+
style: reducedMotion ? void 0 : { animation: "fadeSlideIn 0.3s ease-out" },
|
|
505
|
+
"data-testid": "streaming-structure-entry",
|
|
506
|
+
children: [
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { className: "font-medium text-text-primary text-sm", children: key }),
|
|
508
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { className: "text-text-secondary text-sm ml-0 mb-3", children: renderValue(value, reducedMotion) })
|
|
509
|
+
]
|
|
510
|
+
},
|
|
511
|
+
key
|
|
512
|
+
)),
|
|
513
|
+
isStreaming && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "streaming-structure-loading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextGlimmer, { lines: 1 }) })
|
|
514
|
+
]
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
519
|
+
0 && (module.exports = {
|
|
520
|
+
RetrievalProgress,
|
|
521
|
+
StreamingList,
|
|
522
|
+
StreamingMessage,
|
|
523
|
+
StreamingStructure,
|
|
524
|
+
TextGlimmer,
|
|
525
|
+
ThinkingIndicator,
|
|
526
|
+
ToolExecution,
|
|
527
|
+
TypewriterText,
|
|
528
|
+
TypingIndicator,
|
|
529
|
+
VerificationProgress
|
|
530
|
+
});
|
|
531
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/streaming/index.ts","../../src/streaming/StreamingMessage/StreamingMessage.tsx","../../src/hooks/useCharacterDrain.ts","../../src/streaming/ThinkingIndicator/ThinkingIndicator.tsx","../../src/streaming/ToolExecution/ToolExecution.tsx","../../src/streaming/RetrievalProgress/RetrievalProgress.tsx","../../src/streaming/VerificationProgress/VerificationProgress.tsx","../../src/streaming/TypewriterText/TypewriterText.tsx","../../src/streaming/TypingIndicator/TypingIndicator.tsx","../../src/streaming/TextGlimmer/TextGlimmer.tsx","../../src/streaming/StreamingList/StreamingList.tsx","../../src/streaming/StreamingStructure/StreamingStructure.tsx"],"sourcesContent":["export { StreamingMessage } from './StreamingMessage'\nexport type { StreamingMessageProps } from './StreamingMessage'\n\nexport { ThinkingIndicator } from './ThinkingIndicator'\nexport type { ThinkingIndicatorProps } from './ThinkingIndicator'\n\nexport { ToolExecution } from './ToolExecution'\nexport type { ToolExecutionProps } from './ToolExecution'\n\nexport { RetrievalProgress } from './RetrievalProgress'\nexport type { RetrievalProgressProps } from './RetrievalProgress'\n\nexport { VerificationProgress } from './VerificationProgress'\nexport type { VerificationProgressProps } from './VerificationProgress'\n\nexport { TypewriterText } from './TypewriterText'\nexport type { TypewriterTextProps } from './TypewriterText'\n\nexport { TypingIndicator } from './TypingIndicator'\nexport type { TypingIndicatorProps } from './TypingIndicator'\n\nexport { TextGlimmer } from './TextGlimmer'\nexport type { TextGlimmerProps } from './TextGlimmer'\n\nexport { StreamingList } from './StreamingList'\nexport type { StreamingListProps } from './StreamingList'\n\nexport { StreamingStructure } from './StreamingStructure'\nexport type { StreamingStructureProps } from './StreamingStructure'\n","import React, { useEffect, useRef } from 'react'\nimport { Spinner } from '@surf-kit/core'\nimport type { StreamState } from '../../types/streaming'\nimport { useCharacterDrain } from '../../hooks/useCharacterDrain'\n\ntype StreamingMessageProps = {\n stream: StreamState\n onComplete?: () => void\n showPhases?: boolean\n className?: string\n}\n\nconst phaseLabels: Record<StreamState['phase'], string> = {\n idle: '',\n waiting: 'Waiting...',\n thinking: 'Thinking...',\n retrieving: 'Searching...',\n generating: 'Writing...',\n verifying: 'Verifying...',\n}\n\nfunction StreamingMessage({\n stream,\n onComplete,\n showPhases = true,\n className,\n}: StreamingMessageProps) {\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\n const wasActiveRef = useRef(stream.active)\n\n useEffect(() => {\n if (wasActiveRef.current && !stream.active) {\n onCompleteRef.current?.()\n }\n wasActiveRef.current = stream.active\n }, [stream.active])\n\n const phaseLabel = phaseLabels[stream.phase]\n const { displayed: displayedContent } = useCharacterDrain(stream.content)\n\n return (\n <div className={className} data-testid=\"streaming-message\">\n {/* Screen reader announcements */}\n <div aria-live=\"assertive\" className=\"sr-only\">\n {stream.active && stream.phase !== 'idle' && 'Response started'}\n {!stream.active && stream.content && 'Response complete'}\n </div>\n\n <div className=\"max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft\">\n {showPhases && stream.active && stream.phase !== 'idle' && (\n <div\n className=\"flex items-center gap-2 mb-2 text-sm text-text-secondary\"\n data-testid=\"phase-indicator\"\n >\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n <span>{phaseLabel}</span>\n </div>\n )}\n\n <div className=\"text-sm leading-relaxed text-text-primary whitespace-pre-wrap\">\n {displayedContent}\n {stream.active && (\n <span\n className=\"inline-block w-0.5 h-4 bg-accent align-text-bottom animate-pulse ml-0.5\"\n aria-hidden=\"true\"\n data-testid=\"streaming-cursor\"\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport { StreamingMessage }\nexport type { StreamingMessageProps }\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","import React from 'react'\nimport { useReducedMotion } from '@surf-kit/hooks'\n\ntype ThinkingIndicatorProps = {\n label?: string\n className?: string\n}\n\nfunction ThinkingIndicator({ label = 'Thinking...', className }: ThinkingIndicatorProps) {\n const reducedMotion = useReducedMotion()\n\n return (\n <span\n role=\"status\"\n className={`inline-flex items-center gap-2 text-sm motion-safe:animate-fadeSlideUpSm ${className ?? ''}`}\n data-testid=\"thinking-indicator\"\n >\n <span className=\"text-text-secondary\">{label}</span>\n {!reducedMotion && (\n <span className=\"flex gap-1\" aria-hidden=\"true\" data-testid=\"animated-dots\">\n <span className=\"w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:0ms]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:150ms]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-current animate-bounce [animation-delay:300ms]\" />\n </span>\n )}\n </span>\n )\n}\n\nexport { ThinkingIndicator }\nexport type { ThinkingIndicatorProps }\n","import React from 'react'\nimport { Spinner } from '@surf-kit/core'\n\ntype ToolExecutionProps = {\n tool: string\n label?: string\n className?: string\n}\n\nconst defaultLabels: Record<string, string> = {\n search: 'Searching knowledge base...',\n retrieve: 'Retrieving documents...',\n calculate: 'Calculating...',\n}\n\nfunction ToolExecution({ tool, label, className }: ToolExecutionProps) {\n const displayLabel = label ?? defaultLabels[tool] ?? `Running ${tool}...`\n\n return (\n <div\n className={`flex items-center gap-2 text-sm text-text-secondary ${className ?? ''}`}\n role=\"status\"\n data-testid=\"tool-execution\"\n >\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n <span>{displayLabel}</span>\n </div>\n )\n}\n\nexport { ToolExecution }\nexport type { ToolExecutionProps }\n","import React from 'react'\nimport { Spinner } from '@surf-kit/core'\nimport type { Source } from '../../types/agent'\n\ntype RetrievalProgressProps = {\n sources: Source[]\n isActive: boolean\n className?: string\n}\n\nfunction RetrievalProgress({ sources, isActive, className }: RetrievalProgressProps) {\n return (\n <div\n className={`space-y-2 ${className ?? ''}`}\n role=\"status\"\n aria-label={\n isActive\n ? `Retrieving sources, ${sources.length} found so far`\n : `${sources.length} sources found`\n }\n data-testid=\"retrieval-progress\"\n >\n {isActive && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n <span>Retrieving sources...</span>\n </div>\n )}\n\n {sources.length > 0 && (\n <ul className=\"space-y-1\" data-testid=\"source-list\">\n {sources.map((source, index) => (\n <li\n key={source.document_id}\n className=\"text-sm text-text-secondary flex items-center gap-2 animate-in fade-in slide-in-from-left-2\"\n style={{ animationDelay: `${index * 100}ms`, animationFillMode: 'both' }}\n data-testid=\"retrieval-source-item\"\n >\n <span className=\"w-1.5 h-1.5 rounded-full bg-accent flex-shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{source.title}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n\nexport { RetrievalProgress }\nexport type { RetrievalProgressProps }\n","import React from 'react'\n\ntype VerificationProgressProps = {\n isActive: boolean\n label?: string\n className?: string\n}\n\nfunction VerificationProgress({\n isActive,\n label = 'Checking accuracy...',\n className,\n}: VerificationProgressProps) {\n if (!isActive) return null\n\n return (\n <div\n className={`flex items-center gap-2 text-sm ${className ?? ''}`}\n role=\"status\"\n data-testid=\"verification-progress\"\n >\n <svg\n className=\"w-4 h-4 animate-spin text-accent\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\" />\n </svg>\n <span className=\"text-accent animate-pulse\">{label}</span>\n </div>\n )\n}\n\nexport { VerificationProgress }\nexport type { VerificationProgressProps }\n","import React, { useEffect, useState } from 'react'\n\nexport type TypewriterTextProps = {\n text: string\n speed?: number // ms per char, default 30\n delay?: number // ms to wait before starting, default 0\n onComplete?: () => void\n className?: string\n showCursor?: boolean // default true\n}\n\nexport function TypewriterText({\n text,\n speed = 30,\n delay = 0,\n onComplete,\n className = '',\n showCursor = true,\n}: TypewriterTextProps) {\n const [displayedText, setDisplayedText] = useState('')\n const [isComplete, setIsComplete] = useState(false)\n\n useEffect(() => {\n setDisplayedText('')\n setIsComplete(false)\n let index = 0\n let interval: ReturnType<typeof setInterval>\n const timeout = setTimeout(() => {\n interval = setInterval(() => {\n if (index < text.length) {\n setDisplayedText(text.slice(0, index + 1))\n index++\n } else {\n clearInterval(interval)\n setIsComplete(true)\n onComplete?.()\n }\n }, speed)\n }, delay)\n return () => {\n clearTimeout(timeout)\n clearInterval(interval)\n }\n }, [text, speed, delay, onComplete])\n\n return (\n <span className={className}>\n {displayedText}\n {showCursor && !isComplete && (\n <span className=\"typewriter-cursor\" aria-hidden=\"true\" />\n )}\n </span>\n )\n}\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { useReducedMotion } from '@surf-kit/hooks'\n\ntype TypingIndicatorProps = {\n label?: string\n dotCount?: number\n className?: string\n}\n\nconst bounceKeyframes = `\n@keyframes typing-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n}\n`\n\nfunction TypingIndicator({\n label,\n dotCount = 3,\n className,\n}: TypingIndicatorProps) {\n const reducedMotion = useReducedMotion()\n\n return (\n <span\n role=\"status\"\n aria-label={label ?? 'typing'}\n className={twMerge('inline-flex items-center gap-2', className)}\n data-testid=\"typing-indicator\"\n >\n {!reducedMotion && <style>{bounceKeyframes}</style>}\n {label && (\n <span className=\"text-sm text-text-secondary\">{label}</span>\n )}\n <span className=\"flex gap-1\" data-testid=\"typing-dots\">\n {Array.from({ length: dotCount }, (_, i) => (\n <span\n key={i}\n className=\"w-2 h-2 rounded-full bg-text-secondary\"\n style={\n reducedMotion\n ? undefined\n : {\n animation: 'typing-bounce 1.4s infinite ease-in-out',\n animationDelay: `${i * 160}ms`,\n }\n }\n />\n ))}\n </span>\n </span>\n )\n}\n\nexport { TypingIndicator }\nexport type { TypingIndicatorProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { useReducedMotion } from '@surf-kit/hooks'\n\ntype TextGlimmerProps = {\n lines?: number\n className?: string\n}\n\nconst shimmerKeyframes = `\n@keyframes text-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n`\n\nconst widthPattern = ['100%', '90%', '60%']\n\nfunction TextGlimmer({ lines = 3, className }: TextGlimmerProps) {\n const reducedMotion = useReducedMotion()\n\n return (\n <div\n role=\"status\"\n aria-label=\"Loading\"\n className={twMerge('flex flex-col gap-2', className)}\n data-testid=\"text-glimmer\"\n >\n {!reducedMotion && <style>{shimmerKeyframes}</style>}\n {Array.from({ length: lines }, (_, i) => (\n <div\n key={i}\n className=\"h-3 rounded bg-surface-raised\"\n style={{\n width: widthPattern[i % widthPattern.length],\n ...(reducedMotion\n ? undefined\n : {\n backgroundImage:\n 'linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent)',\n backgroundSize: '200% 100%',\n animation: 'text-shimmer 1.5s infinite ease-in-out',\n }),\n }}\n data-testid=\"glimmer-line\"\n />\n ))}\n </div>\n )\n}\n\nexport { TextGlimmer }\nexport type { TextGlimmerProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { useReducedMotion } from '@surf-kit/hooks'\nimport { TypingIndicator } from '../TypingIndicator'\n\ntype StreamingListProps<T> = {\n items: T[]\n renderItem: (item: T, index: number) => React.ReactNode\n isStreaming?: boolean\n className?: string\n emptyMessage?: string\n}\n\nconst fadeSlideInKeyframes = `\n@keyframes fadeSlideIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n`\n\nfunction StreamingList<T>({\n items,\n renderItem,\n isStreaming = false,\n className,\n emptyMessage,\n}: StreamingListProps<T>) {\n const reducedMotion = useReducedMotion()\n\n if (items.length === 0 && !isStreaming) {\n return emptyMessage ? (\n <p className={twMerge('text-sm text-text-secondary', className)} data-testid=\"streaming-list-empty\">\n {emptyMessage}\n </p>\n ) : null\n }\n\n return (\n <ul\n aria-live=\"polite\"\n className={twMerge('list-none p-0 m-0', className)}\n data-testid=\"streaming-list\"\n >\n {!reducedMotion && <style>{fadeSlideInKeyframes}</style>}\n {items.map((item, index) => (\n <li\n key={index}\n style={\n reducedMotion\n ? undefined\n : { animation: 'fadeSlideIn 0.3s ease-out' }\n }\n data-testid=\"streaming-list-item\"\n >\n {renderItem(item, index)}\n </li>\n ))}\n {isStreaming && (\n <li data-testid=\"streaming-list-loading\">\n <TypingIndicator />\n </li>\n )}\n </ul>\n )\n}\n\nexport { StreamingList }\nexport type { StreamingListProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { useReducedMotion } from '@surf-kit/hooks'\nimport { TextGlimmer } from '../TextGlimmer'\n\ntype StreamingStructureProps = {\n data: Record<string, unknown>\n isStreaming?: boolean\n className?: string\n}\n\nconst fadeSlideInKeyframes = `\n@keyframes fadeSlideIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n`\n\nfunction renderValue(value: unknown, reducedMotion: boolean): React.ReactNode {\n if (value === null) {\n return <span className=\"italic text-text-secondary\">null</span>\n }\n if (value === undefined) {\n return <span className=\"italic text-text-secondary\">undefined</span>\n }\n if (Array.isArray(value)) {\n return (\n <ol className=\"list-decimal pl-4 m-0\">\n {value.map((item, i) => (\n <li key={i} className=\"text-text-secondary text-sm\">\n {renderValue(item, reducedMotion)}\n </li>\n ))}\n </ol>\n )\n }\n if (typeof value === 'object') {\n return renderNestedDl(value as Record<string, unknown>, reducedMotion)\n }\n return String(value)\n}\n\nfunction renderNestedDl(\n data: Record<string, unknown>,\n reducedMotion: boolean,\n): React.ReactNode {\n const entries = Object.entries(data)\n return (\n <dl className=\"pl-4 m-0\" data-testid=\"streaming-structure-nested\">\n {entries.map(([key, value]) => (\n <div\n key={key}\n style={\n reducedMotion\n ? undefined\n : { animation: 'fadeSlideIn 0.3s ease-out' }\n }\n >\n <dt className=\"font-medium text-text-primary text-sm\">{key}</dt>\n <dd className=\"text-text-secondary text-sm ml-0 mb-3\">\n {renderValue(value, reducedMotion)}\n </dd>\n </div>\n ))}\n </dl>\n )\n}\n\nfunction StreamingStructure({\n data,\n isStreaming = false,\n className,\n}: StreamingStructureProps) {\n const reducedMotion = useReducedMotion()\n const entries = Object.entries(data)\n\n return (\n <dl\n aria-live=\"polite\"\n className={twMerge('m-0', className)}\n data-testid=\"streaming-structure\"\n >\n {!reducedMotion && <style>{fadeSlideInKeyframes}</style>}\n {entries.map(([key, value]) => (\n <div\n key={key}\n style={\n reducedMotion\n ? undefined\n : { animation: 'fadeSlideIn 0.3s ease-out' }\n }\n data-testid=\"streaming-structure-entry\"\n >\n <dt className=\"font-medium text-text-primary text-sm\">{key}</dt>\n <dd className=\"text-text-secondary text-sm ml-0 mb-3\">\n {renderValue(value, reducedMotion)}\n </dd>\n </div>\n ))}\n {isStreaming && (\n <div data-testid=\"streaming-structure-loading\">\n <TextGlimmer lines={1} />\n </div>\n )}\n </dl>\n )\n}\n\nexport { StreamingStructure }\nexport type { StreamingStructureProps }\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_core","import_jsx_runtime","import_core","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_hooks","import_jsx_runtime","import_tailwind_merge","import_hooks","import_jsx_runtime","import_tailwind_merge","import_hooks","import_jsx_runtime","import_tailwind_merge","import_hooks","import_jsx_runtime","fadeSlideInKeyframes"]}
|