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