@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,44 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { a as AgentResponse$1 } from '../agent-BNSmiexZ.js';
|
|
3
|
+
import { C as ChatError } from '../chat--OifhIRe.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
type AgentResponseProps = {
|
|
7
|
+
response: AgentResponse$1;
|
|
8
|
+
showSources?: boolean;
|
|
9
|
+
showConfidence?: boolean;
|
|
10
|
+
showVerification?: boolean;
|
|
11
|
+
onFollowUp?: (suggestion: string) => void;
|
|
12
|
+
onNavigateSource?: (source: AgentResponse$1['sources'][number]) => void;
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
declare function AgentResponse({ response, showSources, showConfidence, showVerification, onFollowUp, onNavigateSource, className, }: AgentResponseProps): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
type ResponseMessageProps = {
|
|
18
|
+
content: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
};
|
|
21
|
+
declare function ResponseMessage({ content, className }: ResponseMessageProps): react_jsx_runtime.JSX.Element;
|
|
22
|
+
|
|
23
|
+
type StructuredResponseProps = {
|
|
24
|
+
uiHint: AgentResponse$1['ui_hint'];
|
|
25
|
+
data: Record<string, unknown> | null;
|
|
26
|
+
className?: string;
|
|
27
|
+
};
|
|
28
|
+
declare function StructuredResponse({ uiHint, data, className }: StructuredResponseProps): react_jsx_runtime.JSX.Element | null;
|
|
29
|
+
|
|
30
|
+
type FollowUpChipsProps = {
|
|
31
|
+
suggestions: string[];
|
|
32
|
+
onSelect: (suggestion: string) => void;
|
|
33
|
+
className?: string;
|
|
34
|
+
};
|
|
35
|
+
declare function FollowUpChips({ suggestions, onSelect, className }: FollowUpChipsProps): react_jsx_runtime.JSX.Element | null;
|
|
36
|
+
|
|
37
|
+
type ErrorResponseProps = {
|
|
38
|
+
error: ChatError;
|
|
39
|
+
onRetry?: () => void;
|
|
40
|
+
className?: string;
|
|
41
|
+
};
|
|
42
|
+
declare function ErrorResponse({ error, onRetry, className }: ErrorResponseProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
|
|
44
|
+
export { AgentResponse, type AgentResponseProps, ErrorResponse, type ErrorResponseProps, FollowUpChips, type FollowUpChipsProps, ResponseMessage, type ResponseMessageProps, StructuredResponse, type StructuredResponseProps };
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
// src/response/AgentResponse/AgentResponse.tsx
|
|
2
|
+
import { Badge as Badge2 } from "@surf-kit/core";
|
|
3
|
+
|
|
4
|
+
// src/response/ResponseMessage/ResponseMessage.tsx
|
|
5
|
+
import ReactMarkdown from "react-markdown";
|
|
6
|
+
import rehypeSanitize from "rehype-sanitize";
|
|
7
|
+
import { twMerge } from "tailwind-merge";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
function normalizeMarkdownLists(content) {
|
|
10
|
+
return content.replace(/:\s+-\s+/g, ":\n\n- ");
|
|
11
|
+
}
|
|
12
|
+
function ResponseMessage({ content, className }) {
|
|
13
|
+
return /* @__PURE__ */ jsx(
|
|
14
|
+
"div",
|
|
15
|
+
{
|
|
16
|
+
className: twMerge(
|
|
17
|
+
"text-sm leading-relaxed text-text-primary",
|
|
18
|
+
"[&_p]:my-2",
|
|
19
|
+
"[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6",
|
|
20
|
+
"[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6",
|
|
21
|
+
"[&_li]:my-1",
|
|
22
|
+
"[&_strong]:text-text-primary [&_strong]:font-semibold",
|
|
23
|
+
"[&_em]:text-text-secondary",
|
|
24
|
+
"[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2",
|
|
25
|
+
"[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5",
|
|
26
|
+
"[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1",
|
|
27
|
+
"[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono",
|
|
28
|
+
"[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto",
|
|
29
|
+
"[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary",
|
|
30
|
+
"[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80",
|
|
31
|
+
className
|
|
32
|
+
),
|
|
33
|
+
"data-testid": "response-message",
|
|
34
|
+
children: /* @__PURE__ */ jsx(
|
|
35
|
+
ReactMarkdown,
|
|
36
|
+
{
|
|
37
|
+
rehypePlugins: [rehypeSanitize],
|
|
38
|
+
components: {
|
|
39
|
+
script: () => null,
|
|
40
|
+
iframe: () => null,
|
|
41
|
+
p: ({ children }) => /* @__PURE__ */ jsx("p", { className: "my-2", children }),
|
|
42
|
+
ul: ({ children }) => /* @__PURE__ */ jsx("ul", { className: "my-2 list-disc pl-6", children }),
|
|
43
|
+
ol: ({ children }) => /* @__PURE__ */ jsx("ol", { className: "my-2 list-decimal pl-6", children }),
|
|
44
|
+
li: ({ children }) => /* @__PURE__ */ jsx("li", { className: "my-1", children }),
|
|
45
|
+
strong: ({ children }) => /* @__PURE__ */ jsx("strong", { className: "font-semibold", children }),
|
|
46
|
+
h1: ({ children }) => /* @__PURE__ */ jsx("h1", { className: "text-base font-bold mt-4 mb-2", children }),
|
|
47
|
+
h2: ({ children }) => /* @__PURE__ */ jsx("h2", { className: "text-sm font-bold mt-3 mb-1", children }),
|
|
48
|
+
h3: ({ children }) => /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mt-2 mb-1", children }),
|
|
49
|
+
code: ({ children }) => /* @__PURE__ */ jsx("code", { className: "bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono", children })
|
|
50
|
+
},
|
|
51
|
+
children: normalizeMarkdownLists(content)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/response/StructuredResponse/StructuredResponse.tsx
|
|
59
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
60
|
+
function tryParse(value) {
|
|
61
|
+
if (value === void 0 || value === null) return null;
|
|
62
|
+
if (typeof value === "string") {
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(value);
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
function renderSteps(data) {
|
|
72
|
+
const steps = tryParse(data.steps);
|
|
73
|
+
if (!steps || !Array.isArray(steps)) return null;
|
|
74
|
+
return /* @__PURE__ */ jsx2("ol", { className: "flex flex-col gap-2", "data-testid": "structured-steps", children: steps.map((step, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3", children: [
|
|
75
|
+
/* @__PURE__ */ jsx2(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: "mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent text-[11px] font-semibold text-white",
|
|
79
|
+
"aria-hidden": "true",
|
|
80
|
+
children: i + 1
|
|
81
|
+
}
|
|
82
|
+
),
|
|
83
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm text-text-primary leading-relaxed", children: step })
|
|
84
|
+
] }, i)) });
|
|
85
|
+
}
|
|
86
|
+
function renderTable(data) {
|
|
87
|
+
const columns = tryParse(data.columns);
|
|
88
|
+
const rawRows = tryParse(data.rows);
|
|
89
|
+
if (columns && rawRows && Array.isArray(columns) && Array.isArray(rawRows)) {
|
|
90
|
+
return /* @__PURE__ */ jsx2("div", { className: "overflow-x-auto rounded-lg border border-border", "data-testid": "structured-table", children: /* @__PURE__ */ jsxs("table", { role: "table", className: "w-full border-collapse text-sm", children: [
|
|
91
|
+
/* @__PURE__ */ jsx2("thead", { className: "bg-surface-raised", children: /* @__PURE__ */ jsx2("tr", { children: columns.map((col) => /* @__PURE__ */ jsx2(
|
|
92
|
+
"th",
|
|
93
|
+
{
|
|
94
|
+
className: "text-left px-4 py-2.5 font-semibold text-text-primary border-b border-border",
|
|
95
|
+
children: col
|
|
96
|
+
},
|
|
97
|
+
col
|
|
98
|
+
)) }) }),
|
|
99
|
+
/* @__PURE__ */ jsx2("tbody", { children: rawRows.map((row, i) => {
|
|
100
|
+
const cells = Array.isArray(row) ? row : columns.map((col) => row[col]);
|
|
101
|
+
return /* @__PURE__ */ jsx2("tr", { className: "even:bg-surface-raised/40", children: cells.map((cell, j) => /* @__PURE__ */ jsx2("td", { className: "px-4 py-2 text-text-secondary border-b border-border", children: String(cell ?? "") }, j)) }, i);
|
|
102
|
+
}) })
|
|
103
|
+
] }) });
|
|
104
|
+
}
|
|
105
|
+
const entries = Object.entries(data);
|
|
106
|
+
return /* @__PURE__ */ jsx2("div", { className: "overflow-x-auto rounded-lg border border-border", "data-testid": "structured-table", children: /* @__PURE__ */ jsx2("table", { role: "table", className: "w-full border-collapse text-sm", children: /* @__PURE__ */ jsx2("tbody", { children: entries.map(([key, value]) => /* @__PURE__ */ jsxs("tr", { className: "even:bg-surface-raised/40", children: [
|
|
107
|
+
/* @__PURE__ */ jsx2("td", { className: "px-4 py-2 text-text-primary font-medium border-b border-border w-1/3", children: key }),
|
|
108
|
+
/* @__PURE__ */ jsx2("td", { className: "px-4 py-2 text-text-secondary border-b border-border", children: typeof value === "object" ? JSON.stringify(value) : String(value ?? "") })
|
|
109
|
+
] }, key)) }) }) });
|
|
110
|
+
}
|
|
111
|
+
function renderCard(data) {
|
|
112
|
+
const title = typeof data.title === "string" ? data.title : null;
|
|
113
|
+
const body = typeof data.body === "string" ? data.body : null;
|
|
114
|
+
const link = typeof data.link === "string" ? data.link : null;
|
|
115
|
+
const linkLabel = typeof data.link_label === "string" ? data.link_label : "Learn more";
|
|
116
|
+
return /* @__PURE__ */ jsxs(
|
|
117
|
+
"div",
|
|
118
|
+
{
|
|
119
|
+
className: "rounded-xl border border-border bg-surface-raised p-4 flex flex-col gap-2",
|
|
120
|
+
"data-testid": "structured-card",
|
|
121
|
+
children: [
|
|
122
|
+
title && /* @__PURE__ */ jsx2("p", { className: "text-sm font-semibold text-text-primary", children: title }),
|
|
123
|
+
body && /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary leading-relaxed", children: body }),
|
|
124
|
+
link && /* @__PURE__ */ jsxs(
|
|
125
|
+
"a",
|
|
126
|
+
{
|
|
127
|
+
href: link,
|
|
128
|
+
target: "_blank",
|
|
129
|
+
rel: "noopener noreferrer",
|
|
130
|
+
className: "mt-1 inline-flex items-center gap-1 text-xs font-medium text-accent hover:text-accent/80 underline-offset-2 hover:underline transition-colors",
|
|
131
|
+
children: [
|
|
132
|
+
linkLabel,
|
|
133
|
+
/* @__PURE__ */ jsx2("svg", { className: "h-3 w-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function renderList(data) {
|
|
142
|
+
const items = tryParse(data.items);
|
|
143
|
+
const title = typeof data.title === "string" ? data.title : null;
|
|
144
|
+
if (!items || !Array.isArray(items)) return null;
|
|
145
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", "data-testid": "structured-list", children: [
|
|
146
|
+
title && /* @__PURE__ */ jsx2("p", { className: "text-xs font-semibold uppercase tracking-wider text-text-secondary mb-1", children: title }),
|
|
147
|
+
/* @__PURE__ */ jsx2("ul", { className: "flex flex-col gap-1.5", children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2.5", children: [
|
|
148
|
+
/* @__PURE__ */ jsx2("span", { className: "mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-accent", "aria-hidden": "true" }),
|
|
149
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm text-text-primary leading-relaxed", children: item })
|
|
150
|
+
] }, i)) })
|
|
151
|
+
] });
|
|
152
|
+
}
|
|
153
|
+
function renderWarning(data) {
|
|
154
|
+
const severity = typeof data.severity === "string" ? data.severity : "medium";
|
|
155
|
+
const action = typeof data.action === "string" ? data.action : null;
|
|
156
|
+
const details = typeof data.details === "string" ? data.details : null;
|
|
157
|
+
const isHigh = severity === "high";
|
|
158
|
+
return /* @__PURE__ */ jsxs(
|
|
159
|
+
"div",
|
|
160
|
+
{
|
|
161
|
+
role: "alert",
|
|
162
|
+
className: `rounded-xl border p-4 flex gap-3 ${isHigh ? "border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30" : "border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30"}`,
|
|
163
|
+
"data-testid": "structured-warning",
|
|
164
|
+
children: [
|
|
165
|
+
/* @__PURE__ */ jsx2(
|
|
166
|
+
"svg",
|
|
167
|
+
{
|
|
168
|
+
className: `mt-0.5 h-5 w-5 shrink-0 ${isHigh ? "text-red-500" : "text-amber-500"}`,
|
|
169
|
+
fill: "none",
|
|
170
|
+
viewBox: "0 0 24 24",
|
|
171
|
+
stroke: "currentColor",
|
|
172
|
+
strokeWidth: 2,
|
|
173
|
+
children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" })
|
|
174
|
+
}
|
|
175
|
+
),
|
|
176
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
177
|
+
action && /* @__PURE__ */ jsx2("p", { className: `text-sm font-semibold ${isHigh ? "text-red-700 dark:text-red-300" : "text-amber-700 dark:text-amber-300"}`, children: action }),
|
|
178
|
+
details && /* @__PURE__ */ jsx2("p", { className: `text-sm ${isHigh ? "text-red-600 dark:text-red-400" : "text-amber-600 dark:text-amber-400"}`, children: details })
|
|
179
|
+
] })
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
function StructuredResponse({ uiHint, data, className }) {
|
|
185
|
+
if (!data) return null;
|
|
186
|
+
let content;
|
|
187
|
+
switch (uiHint) {
|
|
188
|
+
case "steps":
|
|
189
|
+
content = renderSteps(data);
|
|
190
|
+
break;
|
|
191
|
+
case "table":
|
|
192
|
+
content = renderTable(data);
|
|
193
|
+
break;
|
|
194
|
+
case "card":
|
|
195
|
+
content = renderCard(data);
|
|
196
|
+
break;
|
|
197
|
+
case "list":
|
|
198
|
+
content = renderList(data);
|
|
199
|
+
break;
|
|
200
|
+
case "warning":
|
|
201
|
+
content = renderWarning(data);
|
|
202
|
+
break;
|
|
203
|
+
case "text":
|
|
204
|
+
content = typeof data.text === "string" ? /* @__PURE__ */ jsx2("p", { "data-testid": "structured-text", children: data.text }) : null;
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
content = null;
|
|
208
|
+
}
|
|
209
|
+
if (!content) return null;
|
|
210
|
+
return /* @__PURE__ */ jsx2("div", { className, "data-testid": "structured-response", children: content });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/sources/SourceList/SourceList.tsx
|
|
214
|
+
import { useState } from "react";
|
|
215
|
+
|
|
216
|
+
// src/sources/SourceCard/SourceCard.tsx
|
|
217
|
+
import { Badge } from "@surf-kit/core";
|
|
218
|
+
import { twMerge as twMerge2 } from "tailwind-merge";
|
|
219
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
220
|
+
function getConfidenceIntent(confidence) {
|
|
221
|
+
if (confidence >= 0.8) return "success";
|
|
222
|
+
if (confidence >= 0.5) return "warning";
|
|
223
|
+
return "error";
|
|
224
|
+
}
|
|
225
|
+
function getConfidenceLabel(confidence) {
|
|
226
|
+
if (confidence >= 0.8) return "High";
|
|
227
|
+
if (confidence >= 0.5) return "Medium";
|
|
228
|
+
return "Low";
|
|
229
|
+
}
|
|
230
|
+
function SourceCard({ source, variant = "compact", onNavigate, className }) {
|
|
231
|
+
const handleClick = () => {
|
|
232
|
+
if (onNavigate) {
|
|
233
|
+
onNavigate(source);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
const isCompact = variant === "compact";
|
|
237
|
+
return /* @__PURE__ */ jsx3(
|
|
238
|
+
"div",
|
|
239
|
+
{
|
|
240
|
+
className: twMerge2(
|
|
241
|
+
"rounded-xl border transition-all duration-200",
|
|
242
|
+
"bg-surface border-border",
|
|
243
|
+
onNavigate && "cursor-pointer hover:border-border-strong",
|
|
244
|
+
className
|
|
245
|
+
),
|
|
246
|
+
"data-document-id": source.document_id,
|
|
247
|
+
"data-testid": "source-card",
|
|
248
|
+
children: /* @__PURE__ */ jsxs2(
|
|
249
|
+
"div",
|
|
250
|
+
{
|
|
251
|
+
className: isCompact ? "px-4 py-3" : "px-6 py-4",
|
|
252
|
+
onClick: handleClick,
|
|
253
|
+
role: onNavigate ? "button" : void 0,
|
|
254
|
+
tabIndex: onNavigate ? 0 : void 0,
|
|
255
|
+
onKeyDown: onNavigate ? (e) => {
|
|
256
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
handleClick();
|
|
259
|
+
}
|
|
260
|
+
} : void 0,
|
|
261
|
+
children: [
|
|
262
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between gap-2", children: [
|
|
263
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex-1 min-w-0", children: [
|
|
264
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-text-primary truncate", children: source.title }),
|
|
265
|
+
source.section && /* @__PURE__ */ jsx3("p", { className: "text-[11px] font-semibold uppercase tracking-wider text-text-secondary truncate mt-0.5", children: source.section })
|
|
266
|
+
] }),
|
|
267
|
+
/* @__PURE__ */ jsx3(
|
|
268
|
+
Badge,
|
|
269
|
+
{
|
|
270
|
+
intent: getConfidenceIntent(source.confidence),
|
|
271
|
+
size: "sm",
|
|
272
|
+
children: getConfidenceLabel(source.confidence)
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
] }),
|
|
276
|
+
!isCompact && /* @__PURE__ */ jsx3("p", { className: "text-xs text-text-secondary mt-2 line-clamp-3 leading-relaxed", children: source.snippet })
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/sources/SourceList/SourceList.tsx
|
|
285
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
286
|
+
function SourceList({
|
|
287
|
+
sources,
|
|
288
|
+
variant = "compact",
|
|
289
|
+
collapsible = false,
|
|
290
|
+
defaultExpanded = true,
|
|
291
|
+
onNavigate,
|
|
292
|
+
className
|
|
293
|
+
}) {
|
|
294
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
295
|
+
if (sources.length === 0) return null;
|
|
296
|
+
const content = /* @__PURE__ */ jsx4("div", { className: "flex flex-col gap-1.5", "data-testid": "source-list-items", children: sources.map((source) => /* @__PURE__ */ jsx4(
|
|
297
|
+
SourceCard,
|
|
298
|
+
{
|
|
299
|
+
source,
|
|
300
|
+
variant,
|
|
301
|
+
onNavigate
|
|
302
|
+
},
|
|
303
|
+
source.document_id
|
|
304
|
+
)) });
|
|
305
|
+
if (!collapsible) {
|
|
306
|
+
return /* @__PURE__ */ jsx4("div", { className, "data-testid": "source-list", children: content });
|
|
307
|
+
}
|
|
308
|
+
return /* @__PURE__ */ jsxs3("div", { className, "data-testid": "source-list", children: [
|
|
309
|
+
/* @__PURE__ */ jsxs3(
|
|
310
|
+
"button",
|
|
311
|
+
{
|
|
312
|
+
type: "button",
|
|
313
|
+
onClick: () => setIsExpanded((prev) => !prev),
|
|
314
|
+
"aria-expanded": isExpanded,
|
|
315
|
+
className: "flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-text-secondary hover:text-accent mb-2 transition-colors duration-200",
|
|
316
|
+
children: [
|
|
317
|
+
/* @__PURE__ */ jsx4(
|
|
318
|
+
"svg",
|
|
319
|
+
{
|
|
320
|
+
className: `w-4 h-4 transition-transform ${isExpanded ? "rotate-180" : ""}`,
|
|
321
|
+
fill: "none",
|
|
322
|
+
viewBox: "0 0 24 24",
|
|
323
|
+
stroke: "currentColor",
|
|
324
|
+
strokeWidth: 2,
|
|
325
|
+
children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
"Sources (",
|
|
329
|
+
sources.length,
|
|
330
|
+
")"
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
),
|
|
334
|
+
isExpanded && content
|
|
335
|
+
] });
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/response/FollowUpChips/FollowUpChips.tsx
|
|
339
|
+
import { twMerge as twMerge3 } from "tailwind-merge";
|
|
340
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
341
|
+
function FollowUpChips({ suggestions, onSelect, className }) {
|
|
342
|
+
if (suggestions.length === 0) return null;
|
|
343
|
+
return /* @__PURE__ */ jsx5(
|
|
344
|
+
"div",
|
|
345
|
+
{
|
|
346
|
+
className: twMerge3("flex flex-wrap gap-2 py-1", className),
|
|
347
|
+
role: "group",
|
|
348
|
+
"aria-label": "Follow-up suggestions",
|
|
349
|
+
"data-testid": "follow-up-chips",
|
|
350
|
+
children: suggestions.map((suggestion) => /* @__PURE__ */ jsx5(
|
|
351
|
+
"button",
|
|
352
|
+
{
|
|
353
|
+
type: "button",
|
|
354
|
+
onClick: () => onSelect(suggestion),
|
|
355
|
+
className: twMerge3(
|
|
356
|
+
"px-4 py-1.5 rounded-full text-sm whitespace-nowrap",
|
|
357
|
+
"border border-border bg-transparent text-text-secondary",
|
|
358
|
+
"hover:bg-accent/10 hover:border-interactive hover:text-text-primary",
|
|
359
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
|
|
360
|
+
"transition-all duration-200"
|
|
361
|
+
),
|
|
362
|
+
children: suggestion
|
|
363
|
+
},
|
|
364
|
+
suggestion
|
|
365
|
+
))
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/response/AgentResponse/AgentResponse.tsx
|
|
371
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
372
|
+
function getConfidenceIntent2(overall) {
|
|
373
|
+
if (overall === "high") return "success";
|
|
374
|
+
if (overall === "medium") return "warning";
|
|
375
|
+
return "error";
|
|
376
|
+
}
|
|
377
|
+
function getVerificationIntent(status) {
|
|
378
|
+
if (status === "passed") return "success";
|
|
379
|
+
if (status === "flagged") return "warning";
|
|
380
|
+
return "error";
|
|
381
|
+
}
|
|
382
|
+
function getVerificationLabel(status) {
|
|
383
|
+
if (status === "passed") return "Verified";
|
|
384
|
+
if (status === "flagged") return "Flagged";
|
|
385
|
+
return "Failed";
|
|
386
|
+
}
|
|
387
|
+
function AgentResponse({
|
|
388
|
+
response,
|
|
389
|
+
showSources = true,
|
|
390
|
+
showConfidence = false,
|
|
391
|
+
showVerification = false,
|
|
392
|
+
onFollowUp,
|
|
393
|
+
onNavigateSource,
|
|
394
|
+
className
|
|
395
|
+
}) {
|
|
396
|
+
return /* @__PURE__ */ jsxs4("div", { className: `flex flex-col gap-4 ${className ?? ""}`, "data-testid": "agent-response", children: [
|
|
397
|
+
/* @__PURE__ */ jsx6(ResponseMessage, { content: response.message }),
|
|
398
|
+
response.ui_hint !== "text" && response.structured_data && /* @__PURE__ */ jsx6(
|
|
399
|
+
StructuredResponse,
|
|
400
|
+
{
|
|
401
|
+
uiHint: response.ui_hint,
|
|
402
|
+
data: response.structured_data
|
|
403
|
+
}
|
|
404
|
+
),
|
|
405
|
+
(showConfidence || showVerification) && /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-2 mt-1", "data-testid": "response-meta", children: [
|
|
406
|
+
showConfidence && /* @__PURE__ */ jsxs4(
|
|
407
|
+
Badge2,
|
|
408
|
+
{
|
|
409
|
+
intent: getConfidenceIntent2(response.confidence.overall),
|
|
410
|
+
size: "sm",
|
|
411
|
+
children: [
|
|
412
|
+
response.confidence.overall,
|
|
413
|
+
" confidence"
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
),
|
|
417
|
+
showVerification && /* @__PURE__ */ jsxs4(
|
|
418
|
+
Badge2,
|
|
419
|
+
{
|
|
420
|
+
intent: getVerificationIntent(response.verification.status),
|
|
421
|
+
size: "sm",
|
|
422
|
+
children: [
|
|
423
|
+
getVerificationLabel(response.verification.status),
|
|
424
|
+
" (",
|
|
425
|
+
response.verification.claims_verified,
|
|
426
|
+
"/",
|
|
427
|
+
response.verification.claims_checked,
|
|
428
|
+
")"
|
|
429
|
+
]
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
] }),
|
|
433
|
+
showSources && response.sources.length > 0 && /* @__PURE__ */ jsx6(
|
|
434
|
+
SourceList,
|
|
435
|
+
{
|
|
436
|
+
sources: response.sources,
|
|
437
|
+
variant: "compact",
|
|
438
|
+
collapsible: true,
|
|
439
|
+
defaultExpanded: false,
|
|
440
|
+
onNavigate: onNavigateSource
|
|
441
|
+
}
|
|
442
|
+
),
|
|
443
|
+
response.follow_up_suggestions.length > 0 && onFollowUp && /* @__PURE__ */ jsx6(
|
|
444
|
+
FollowUpChips,
|
|
445
|
+
{
|
|
446
|
+
suggestions: response.follow_up_suggestions,
|
|
447
|
+
onSelect: onFollowUp
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
] });
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/response/ErrorResponse/ErrorResponse.tsx
|
|
454
|
+
import { Alert, Button } from "@surf-kit/core";
|
|
455
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
456
|
+
function ErrorResponse({ error, onRetry, className }) {
|
|
457
|
+
return /* @__PURE__ */ jsx7("div", { role: "alert", className, "data-testid": "error-response", children: /* @__PURE__ */ jsxs5(Alert, { intent: "error", title: "Error", children: [
|
|
458
|
+
/* @__PURE__ */ jsx7("p", { children: error.message }),
|
|
459
|
+
error.retryable && onRetry && /* @__PURE__ */ jsx7("div", { className: "mt-3", children: /* @__PURE__ */ jsx7(
|
|
460
|
+
Button,
|
|
461
|
+
{
|
|
462
|
+
intent: "secondary",
|
|
463
|
+
size: "sm",
|
|
464
|
+
onPress: onRetry,
|
|
465
|
+
"aria-label": "Retry",
|
|
466
|
+
children: "Retry"
|
|
467
|
+
}
|
|
468
|
+
) })
|
|
469
|
+
] }) });
|
|
470
|
+
}
|
|
471
|
+
export {
|
|
472
|
+
AgentResponse,
|
|
473
|
+
ErrorResponse,
|
|
474
|
+
FollowUpChips,
|
|
475
|
+
ResponseMessage,
|
|
476
|
+
StructuredResponse
|
|
477
|
+
};
|
|
478
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/response/AgentResponse/AgentResponse.tsx","../../src/response/ResponseMessage/ResponseMessage.tsx","../../src/response/StructuredResponse/StructuredResponse.tsx","../../src/sources/SourceList/SourceList.tsx","../../src/sources/SourceCard/SourceCard.tsx","../../src/response/FollowUpChips/FollowUpChips.tsx","../../src/response/ErrorResponse/ErrorResponse.tsx"],"sourcesContent":["import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport type { AgentResponse as AgentResponseType } from '../../types/agent'\nimport { ResponseMessage } from '../ResponseMessage'\nimport { StructuredResponse } from '../StructuredResponse'\nimport { SourceList } from '../../sources/SourceList'\nimport { FollowUpChips } from '../FollowUpChips'\n\ntype AgentResponseProps = {\n response: AgentResponseType\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n onFollowUp?: (suggestion: string) => void\n onNavigateSource?: (source: AgentResponseType['sources'][number]) => void\n className?: string\n}\n\nfunction getConfidenceIntent(overall: 'high' | 'medium' | 'low') {\n if (overall === 'high') return 'success' as const\n if (overall === 'medium') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationIntent(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'success' as const\n if (status === 'flagged') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationLabel(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'Verified'\n if (status === 'flagged') return 'Flagged'\n return 'Failed'\n}\n\nfunction AgentResponse({\n response,\n showSources = true,\n showConfidence = false,\n showVerification = false,\n onFollowUp,\n onNavigateSource,\n className,\n}: AgentResponseProps) {\n return (\n <div className={`flex flex-col gap-4 ${className ?? ''}`} data-testid=\"agent-response\">\n {/* Lead message — always shown as a short 1-3 sentence summary */}\n <ResponseMessage content={response.message} />\n\n {/* Structured content — rendered when ui_hint is not plain text */}\n {response.ui_hint !== 'text' && response.structured_data && (\n <StructuredResponse\n uiHint={response.ui_hint}\n data={response.structured_data as Record<string, unknown>}\n />\n )}\n\n {/* Confidence & Verification badges */}\n {(showConfidence || showVerification) && (\n <div className=\"flex flex-wrap items-center gap-2 mt-1\" data-testid=\"response-meta\">\n {showConfidence && (\n <Badge\n intent={getConfidenceIntent(response.confidence.overall)}\n size=\"sm\"\n >\n {response.confidence.overall} confidence\n </Badge>\n )}\n {showVerification && (\n <Badge\n intent={getVerificationIntent(response.verification.status)}\n size=\"sm\"\n >\n {getVerificationLabel(response.verification.status)} ({response.verification.claims_verified}/{response.verification.claims_checked})\n </Badge>\n )}\n </div>\n )}\n\n {/* Sources */}\n {showSources && response.sources.length > 0 && (\n <SourceList\n sources={response.sources}\n variant=\"compact\"\n collapsible\n defaultExpanded={false}\n onNavigate={onNavigateSource}\n />\n )}\n\n {/* Follow-up suggestions */}\n {response.follow_up_suggestions.length > 0 && onFollowUp && (\n <FollowUpChips\n suggestions={response.follow_up_suggestions}\n onSelect={onFollowUp}\n />\n )}\n </div>\n )\n}\n\nexport { AgentResponse }\nexport type { AgentResponseProps }\n","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize from 'rehype-sanitize'\nimport { twMerge } from 'tailwind-merge'\n\ntype ResponseMessageProps = {\n content: string\n className?: string\n}\n\nfunction normalizeMarkdownLists(content: string) {\n // Some providers emit compact list markdown like \"Intro: - item 1 - item 2\".\n // Insert a paragraph break before an inline list marker so markdown parses it as a list.\n return content.replace(/:\\s+-\\s+/g, ':\\n\\n- ')\n}\n\nfunction ResponseMessage({ content, className }: ResponseMessageProps) {\n return (\n <div\n className={twMerge(\n 'text-sm leading-relaxed text-text-primary',\n '[&_p]:my-2',\n '[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6',\n '[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6',\n '[&_li]:my-1',\n '[&_strong]:text-text-primary [&_strong]:font-semibold',\n '[&_em]:text-text-secondary',\n '[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2',\n '[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5',\n '[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1',\n '[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono',\n '[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto',\n '[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary',\n '[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80',\n className,\n )}\n data-testid=\"response-message\"\n >\n <ReactMarkdown\n rehypePlugins={[rehypeSanitize]}\n components={{\n script: () => null,\n iframe: () => null,\n p: ({ children }) => <p className=\"my-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"my-2 list-disc pl-6\">{children}</ul>,\n ol: ({ children }) => <ol className=\"my-2 list-decimal pl-6\">{children}</ol>,\n li: ({ children }) => <li className=\"my-1\">{children}</li>,\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n h1: ({ children }) => <h1 className=\"text-base font-bold mt-4 mb-2\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"text-sm font-bold mt-3 mb-1\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"text-sm font-semibold mt-2 mb-1\">{children}</h3>,\n code: ({ children }) => <code className=\"bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono\">{children}</code>,\n }}\n >\n {normalizeMarkdownLists(content)}\n </ReactMarkdown>\n </div>\n )\n}\n\nexport { ResponseMessage }\nexport type { ResponseMessageProps }\n","import React from 'react'\nimport type { AgentResponse } from '../../types/agent'\n\ntype StructuredResponseProps = {\n uiHint: AgentResponse['ui_hint']\n data: Record<string, unknown> | null\n className?: string\n}\n\n/** Parse a value that may be a JSON-encoded string or already parsed. */\nfunction tryParse<T>(value: unknown): T | null {\n if (value === undefined || value === null) return null\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T\n } catch {\n return null\n }\n }\n return value as T\n}\n\nfunction renderSteps(data: Record<string, unknown>) {\n const steps = tryParse<string[]>(data.steps)\n if (!steps || !Array.isArray(steps)) return null\n return (\n <ol className=\"flex flex-col gap-2\" data-testid=\"structured-steps\">\n {steps.map((step, i) => (\n <li key={i} className=\"flex items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent text-[11px] font-semibold text-white\"\n aria-hidden=\"true\"\n >\n {i + 1}\n </span>\n <span className=\"text-sm text-text-primary leading-relaxed\">{step}</span>\n </li>\n ))}\n </ol>\n )\n}\n\nfunction renderTable(data: Record<string, unknown>) {\n const columns = tryParse<string[]>(data.columns)\n // rows may be array-of-arrays or array-of-objects; normalise to array-of-arrays\n const rawRows = tryParse<unknown[]>(data.rows)\n\n if (columns && rawRows && Array.isArray(columns) && Array.isArray(rawRows)) {\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <thead className=\"bg-surface-raised\">\n <tr>\n {columns.map((col) => (\n <th\n key={col}\n className=\"text-left px-4 py-2.5 font-semibold text-text-primary border-b border-border\"\n >\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rawRows.map((row, i) => {\n const cells = Array.isArray(row)\n ? row\n : columns.map((col) => (row as Record<string, unknown>)[col])\n return (\n <tr key={i} className=\"even:bg-surface-raised/40\">\n {cells.map((cell, j) => (\n <td key={j} className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {String(cell ?? '')}\n </td>\n ))}\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n }\n\n // Fallback: key-value table\n const entries = Object.entries(data)\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <tbody>\n {entries.map(([key, value]) => (\n <tr key={key} className=\"even:bg-surface-raised/40\">\n <td className=\"px-4 py-2 text-text-primary font-medium border-b border-border w-1/3\">\n {key}\n </td>\n <td className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {typeof value === 'object' ? JSON.stringify(value) : String(value ?? '')}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\nfunction renderCard(data: Record<string, unknown>) {\n const title = typeof data.title === 'string' ? data.title : null\n const body = typeof data.body === 'string' ? data.body : null\n const link = typeof data.link === 'string' ? data.link : null\n const linkLabel = typeof data.link_label === 'string' ? data.link_label : 'Learn more'\n\n return (\n <div\n className=\"rounded-xl border border-border bg-surface-raised p-4 flex flex-col gap-2\"\n data-testid=\"structured-card\"\n >\n {title && <p className=\"text-sm font-semibold text-text-primary\">{title}</p>}\n {body && <p className=\"text-sm text-text-secondary leading-relaxed\">{body}</p>}\n {link && (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-1 inline-flex items-center gap-1 text-xs font-medium text-accent hover:text-accent/80 underline-offset-2 hover:underline transition-colors\"\n >\n {linkLabel}\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\" />\n </svg>\n </a>\n )}\n </div>\n )\n}\n\nfunction renderList(data: Record<string, unknown>) {\n const items = tryParse<string[]>(data.items)\n const title = typeof data.title === 'string' ? data.title : null\n if (!items || !Array.isArray(items)) return null\n\n return (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"structured-list\">\n {title && (\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary mb-1\">{title}</p>\n )}\n <ul className=\"flex flex-col gap-1.5\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-start gap-2.5\">\n <span className=\"mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-accent\" aria-hidden=\"true\" />\n <span className=\"text-sm text-text-primary leading-relaxed\">{item}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n\nfunction renderWarning(data: Record<string, unknown>) {\n const severity = typeof data.severity === 'string' ? data.severity : 'medium'\n const action = typeof data.action === 'string' ? data.action : null\n const details = typeof data.details === 'string' ? data.details : null\n const isHigh = severity === 'high'\n\n return (\n <div\n role=\"alert\"\n className={`rounded-xl border p-4 flex gap-3 ${\n isHigh\n ? 'border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30'\n : 'border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30'\n }`}\n data-testid=\"structured-warning\"\n >\n <svg\n className={`mt-0.5 h-5 w-5 shrink-0 ${isHigh ? 'text-red-500' : 'text-amber-500'}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n <div className=\"flex flex-col gap-1\">\n {action && (\n <p className={`text-sm font-semibold ${isHigh ? 'text-red-700 dark:text-red-300' : 'text-amber-700 dark:text-amber-300'}`}>\n {action}\n </p>\n )}\n {details && (\n <p className={`text-sm ${isHigh ? 'text-red-600 dark:text-red-400' : 'text-amber-600 dark:text-amber-400'}`}>\n {details}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nfunction StructuredResponse({ uiHint, data, className }: StructuredResponseProps) {\n if (!data) return null\n\n let content: React.ReactNode\n\n switch (uiHint) {\n case 'steps':\n content = renderSteps(data)\n break\n case 'table':\n content = renderTable(data)\n break\n case 'card':\n content = renderCard(data)\n break\n case 'list':\n content = renderList(data)\n break\n case 'warning':\n content = renderWarning(data)\n break\n case 'text':\n content = typeof data.text === 'string'\n ? <p data-testid=\"structured-text\">{data.text}</p>\n : null\n break\n default:\n content = null\n }\n\n if (!content) return null\n\n return (\n <div className={className} data-testid=\"structured-response\">\n {content}\n </div>\n )\n}\n\nexport { StructuredResponse }\nexport type { StructuredResponseProps }\n","import React, { useState } from 'react'\nimport type { Source } from '../../types/agent'\nimport { SourceCard } from '../SourceCard'\n\ntype SourceListProps = {\n sources: Source[]\n variant?: 'compact' | 'expanded'\n collapsible?: boolean\n defaultExpanded?: boolean\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction SourceList({\n sources,\n variant = 'compact',\n collapsible = false,\n defaultExpanded = true,\n onNavigate,\n className,\n}: SourceListProps) {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded)\n\n if (sources.length === 0) return null\n\n const content = (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"source-list-items\">\n {sources.map((source) => (\n <SourceCard\n key={source.document_id}\n source={source}\n variant={variant}\n onNavigate={onNavigate}\n />\n ))}\n </div>\n )\n\n if (!collapsible) {\n return (\n <div className={className} data-testid=\"source-list\">\n {content}\n </div>\n )\n }\n\n return (\n <div className={className} data-testid=\"source-list\">\n <button\n type=\"button\"\n onClick={() => setIsExpanded(prev => !prev)}\n aria-expanded={isExpanded}\n className=\"flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-text-secondary hover:text-accent mb-2 transition-colors duration-200\"\n >\n <svg\n className={`w-4 h-4 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n Sources ({sources.length})\n </button>\n {isExpanded && content}\n </div>\n )\n}\n\nexport { SourceList }\nexport type { SourceListProps }\n","import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport { twMerge } from 'tailwind-merge'\nimport type { Source } from '../../types/agent'\n\ntype SourceCardProps = {\n source: Source\n variant?: 'compact' | 'expanded'\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction getConfidenceIntent(confidence: number) {\n if (confidence >= 0.8) return 'success' as const\n if (confidence >= 0.5) return 'warning' as const\n return 'error' as const\n}\n\nfunction getConfidenceLabel(confidence: number) {\n if (confidence >= 0.8) return 'High'\n if (confidence >= 0.5) return 'Medium'\n return 'Low'\n}\n\nfunction SourceCard({ source, variant = 'compact', onNavigate, className }: SourceCardProps) {\n const handleClick = () => {\n if (onNavigate) {\n onNavigate(source)\n }\n }\n\n const isCompact = variant === 'compact'\n\n return (\n <div\n className={twMerge(\n 'rounded-xl border transition-all duration-200',\n 'bg-surface border-border',\n onNavigate && 'cursor-pointer hover:border-border-strong',\n className,\n )}\n data-document-id={source.document_id}\n data-testid=\"source-card\"\n >\n <div\n className={isCompact ? 'px-4 py-3' : 'px-6 py-4'}\n onClick={handleClick}\n role={onNavigate ? 'button' : undefined}\n tabIndex={onNavigate ? 0 : undefined}\n onKeyDown={\n onNavigate\n ? (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }\n : undefined\n }\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {source.title}\n </p>\n {source.section && (\n <p className=\"text-[11px] font-semibold uppercase tracking-wider text-text-secondary truncate mt-0.5\">\n {source.section}\n </p>\n )}\n </div>\n <Badge\n intent={getConfidenceIntent(source.confidence)}\n size=\"sm\"\n >\n {getConfidenceLabel(source.confidence)}\n </Badge>\n </div>\n {!isCompact && (\n <p className=\"text-xs text-text-secondary mt-2 line-clamp-3 leading-relaxed\">\n {source.snippet}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nexport { SourceCard }\nexport type { SourceCardProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\n\ntype FollowUpChipsProps = {\n suggestions: string[]\n onSelect: (suggestion: string) => void\n className?: string\n}\n\nfunction FollowUpChips({ suggestions, onSelect, className }: FollowUpChipsProps) {\n if (suggestions.length === 0) return null\n\n return (\n <div\n className={twMerge('flex flex-wrap gap-2 py-1', className)}\n role=\"group\"\n aria-label=\"Follow-up suggestions\"\n data-testid=\"follow-up-chips\"\n >\n {suggestions.map(suggestion => (\n <button\n key={suggestion}\n type=\"button\"\n onClick={() => onSelect(suggestion)}\n className={twMerge(\n 'px-4 py-1.5 rounded-full text-sm whitespace-nowrap',\n 'border border-border bg-transparent text-text-secondary',\n 'hover:bg-accent/10 hover:border-interactive hover:text-text-primary',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'transition-all duration-200',\n )}\n >\n {suggestion}\n </button>\n ))}\n </div>\n )\n}\n\nexport { FollowUpChips }\nexport type { FollowUpChipsProps }\n","import React from 'react'\nimport { Alert, Button } from '@surf-kit/core'\nimport type { ChatError } from '../../types/chat'\n\ntype ErrorResponseProps = {\n error: ChatError\n onRetry?: () => void\n className?: string\n}\n\nfunction ErrorResponse({ error, onRetry, className }: ErrorResponseProps) {\n return (\n <div role=\"alert\" className={className} data-testid=\"error-response\">\n <Alert intent=\"error\" title=\"Error\">\n <p>{error.message}</p>\n {error.retryable && onRetry && (\n <div className=\"mt-3\">\n <Button\n intent=\"secondary\"\n size=\"sm\"\n onPress={onRetry}\n aria-label=\"Retry\"\n >\n Retry\n </Button>\n </div>\n )}\n </Alert>\n </div>\n )\n}\n\nexport { ErrorResponse }\nexport type { ErrorResponseProps }\n"],"mappings":"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","names":["Badge","jsx","twMerge","jsx","jsxs","jsx","jsxs","twMerge","jsx","jsx","jsxs","getConfidenceIntent","Badge","jsx","jsxs"]}
|