@bernierllc/admin-agent-chat-ui 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +332 -27
  3. package/dist/components/AdminAgentInput.d.ts +4 -0
  4. package/dist/components/AdminAgentInput.d.ts.map +1 -0
  5. package/dist/components/AdminAgentInput.js +72 -0
  6. package/dist/components/AdminAgentInput.js.map +1 -0
  7. package/dist/components/AdminAgentPanel.d.ts +4 -0
  8. package/dist/components/AdminAgentPanel.d.ts.map +1 -0
  9. package/dist/components/AdminAgentPanel.js +26 -0
  10. package/dist/components/AdminAgentPanel.js.map +1 -0
  11. package/dist/components/AdminAgentPanelHeader.d.ts +4 -0
  12. package/dist/components/AdminAgentPanelHeader.d.ts.map +1 -0
  13. package/dist/components/AdminAgentPanelHeader.js +42 -0
  14. package/dist/components/AdminAgentPanelHeader.js.map +1 -0
  15. package/dist/components/AdminAgentProvider.d.ts +4 -0
  16. package/dist/components/AdminAgentProvider.d.ts.map +1 -0
  17. package/dist/components/AdminAgentProvider.js +235 -0
  18. package/dist/components/AdminAgentProvider.js.map +1 -0
  19. package/dist/components/AdminAgentTrigger.d.ts +4 -0
  20. package/dist/components/AdminAgentTrigger.d.ts.map +1 -0
  21. package/dist/components/AdminAgentTrigger.js +28 -0
  22. package/dist/components/AdminAgentTrigger.js.map +1 -0
  23. package/dist/components/AgentStatusBar.d.ts +4 -0
  24. package/dist/components/AgentStatusBar.d.ts.map +1 -0
  25. package/dist/components/AgentStatusBar.js +42 -0
  26. package/dist/components/AgentStatusBar.js.map +1 -0
  27. package/dist/components/AssistantMessageContent.d.ts +4 -0
  28. package/dist/components/AssistantMessageContent.d.ts.map +1 -0
  29. package/dist/components/AssistantMessageContent.js +11 -0
  30. package/dist/components/AssistantMessageContent.js.map +1 -0
  31. package/dist/components/ChangeSummaryCard.d.ts +4 -0
  32. package/dist/components/ChangeSummaryCard.d.ts.map +1 -0
  33. package/dist/components/ChangeSummaryCard.js +55 -0
  34. package/dist/components/ChangeSummaryCard.js.map +1 -0
  35. package/dist/components/MessageBubble.d.ts +4 -0
  36. package/dist/components/MessageBubble.d.ts.map +1 -0
  37. package/dist/components/MessageBubble.js +34 -0
  38. package/dist/components/MessageBubble.js.map +1 -0
  39. package/dist/components/MessageList.d.ts +4 -0
  40. package/dist/components/MessageList.d.ts.map +1 -0
  41. package/dist/components/MessageList.js +41 -0
  42. package/dist/components/MessageList.js.map +1 -0
  43. package/dist/components/ToolResultCard.d.ts +4 -0
  44. package/dist/components/ToolResultCard.d.ts.map +1 -0
  45. package/dist/components/ToolResultCard.js +55 -0
  46. package/dist/components/ToolResultCard.js.map +1 -0
  47. package/dist/components/UserMessageContent.d.ts +4 -0
  48. package/dist/components/UserMessageContent.d.ts.map +1 -0
  49. package/dist/components/UserMessageContent.js +11 -0
  50. package/dist/components/UserMessageContent.js.map +1 -0
  51. package/dist/context.d.ts +4 -0
  52. package/dist/context.d.ts.map +1 -0
  53. package/dist/context.js +10 -0
  54. package/dist/context.js.map +1 -0
  55. package/dist/errors.d.ts +13 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +25 -0
  58. package/dist/errors.js.map +1 -0
  59. package/dist/hooks/useAdminAgentChat.d.ts +7 -0
  60. package/dist/hooks/useAdminAgentChat.d.ts.map +1 -0
  61. package/dist/hooks/useAdminAgentChat.js +22 -0
  62. package/dist/hooks/useAdminAgentChat.js.map +1 -0
  63. package/dist/index.d.ts +16 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +26 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/types.d.ts +120 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +9 -0
  70. package/dist/types.js.map +1 -0
  71. package/package.json +68 -7
@@ -0,0 +1,235 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ import { useCallback, useRef, useState } from 'react';
10
+ import { AdminAgentContext } from '../context';
11
+ import { AdminAgentStreamError } from '../errors';
12
+ function generateId() {
13
+ return Date.now().toString(36) + Math.random().toString(36).slice(2);
14
+ }
15
+ function parseStreamEvent(line) {
16
+ const trimmed = line.trim();
17
+ if (!trimmed)
18
+ return null;
19
+ try {
20
+ return JSON.parse(trimmed);
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export function AdminAgentProvider({ url, headers, children, fetchFn, }) {
27
+ const [messages, setMessages] = useState([]);
28
+ const [status, setStatus] = useState('idle');
29
+ const [isOpen, setIsOpen] = useState(false);
30
+ const [currentToolName, setCurrentToolName] = useState(null);
31
+ const inProgressIdRef = useRef(null);
32
+ const abortRef = useRef(null);
33
+ const effectiveFetch = fetchFn ?? globalThis.fetch.bind(globalThis);
34
+ const getOrCreateAssistantMessage = useCallback(() => {
35
+ if (inProgressIdRef.current)
36
+ return inProgressIdRef.current;
37
+ const id = generateId();
38
+ inProgressIdRef.current = id;
39
+ const msg = {
40
+ id,
41
+ role: 'assistant',
42
+ content: '',
43
+ timestamp: new Date().toISOString(),
44
+ };
45
+ setMessages((prev) => [...prev, msg]);
46
+ return id;
47
+ }, []);
48
+ const applyStreamEvent = useCallback((event) => {
49
+ switch (event.type) {
50
+ case 'text-delta': {
51
+ const id = getOrCreateAssistantMessage();
52
+ setStatus('responding');
53
+ setMessages((prev) => prev.map((m) => m.id === id ? { ...m, content: m.content + event.delta } : m));
54
+ break;
55
+ }
56
+ case 'tool-call-start': {
57
+ const id = getOrCreateAssistantMessage();
58
+ setStatus('executing');
59
+ setCurrentToolName(event.toolName);
60
+ const pendingResult = {
61
+ toolName: event.toolName,
62
+ toolCallId: event.toolCallId,
63
+ success: false,
64
+ summary: '',
65
+ };
66
+ setMessages((prev) => prev.map((m) => m.id === id
67
+ ? {
68
+ ...m,
69
+ toolResults: [...(m.toolResults ?? []), pendingResult],
70
+ }
71
+ : m));
72
+ break;
73
+ }
74
+ case 'tool-call-result': {
75
+ const id = inProgressIdRef.current;
76
+ setStatus('thinking');
77
+ setCurrentToolName(null);
78
+ if (!id)
79
+ break;
80
+ setMessages((prev) => prev.map((m) => {
81
+ if (m.id !== id)
82
+ return m;
83
+ const updatedResults = (m.toolResults ?? []).map((tr) => tr.toolCallId === event.toolCallId
84
+ ? {
85
+ ...tr,
86
+ success: event.success,
87
+ summary: event.summary,
88
+ data: event.data,
89
+ }
90
+ : tr);
91
+ return { ...m, toolResults: updatedResults };
92
+ }));
93
+ break;
94
+ }
95
+ case 'change-summary': {
96
+ const id = inProgressIdRef.current;
97
+ if (!id)
98
+ break;
99
+ setMessages((prev) => prev.map((m) => m.id === id ? { ...m, changeSummary: event.summary } : m));
100
+ break;
101
+ }
102
+ case 'done': {
103
+ inProgressIdRef.current = null;
104
+ setStatus('idle');
105
+ setCurrentToolName(null);
106
+ break;
107
+ }
108
+ case 'error': {
109
+ inProgressIdRef.current = null;
110
+ setStatus('error');
111
+ setCurrentToolName(null);
112
+ const errMsg = {
113
+ id: generateId(),
114
+ role: 'assistant',
115
+ content: event.message,
116
+ timestamp: new Date().toISOString(),
117
+ };
118
+ setMessages((prev) => [...prev, errMsg]);
119
+ break;
120
+ }
121
+ }
122
+ }, [getOrCreateAssistantMessage]);
123
+ const sendMessage = useCallback(async (text) => {
124
+ const trimmed = text.trim();
125
+ if (!trimmed)
126
+ return;
127
+ // Cancel any in-flight request
128
+ abortRef.current?.abort();
129
+ const controller = new AbortController();
130
+ abortRef.current = controller;
131
+ // Append user message
132
+ const userMsg = {
133
+ id: generateId(),
134
+ role: 'user',
135
+ content: trimmed,
136
+ timestamp: new Date().toISOString(),
137
+ };
138
+ setMessages((prev) => [...prev, userMsg]);
139
+ setStatus('thinking');
140
+ inProgressIdRef.current = null;
141
+ let response;
142
+ try {
143
+ response = await effectiveFetch(url, {
144
+ method: 'POST',
145
+ headers: {
146
+ 'Content-Type': 'application/json',
147
+ ...headers,
148
+ },
149
+ body: JSON.stringify({ message: trimmed }),
150
+ signal: controller.signal,
151
+ });
152
+ }
153
+ catch (err) {
154
+ if (controller.signal.aborted)
155
+ return;
156
+ const cause = err instanceof Error ? err : undefined;
157
+ throw new AdminAgentStreamError('Fetch failed', { cause });
158
+ }
159
+ if (!response.ok) {
160
+ setStatus('error');
161
+ const errMsg = {
162
+ id: generateId(),
163
+ role: 'assistant',
164
+ content: `Request failed: ${response.status} ${response.statusText}`,
165
+ timestamp: new Date().toISOString(),
166
+ };
167
+ setMessages((prev) => [...prev, errMsg]);
168
+ return;
169
+ }
170
+ const body = response.body;
171
+ if (!body) {
172
+ setStatus('idle');
173
+ return;
174
+ }
175
+ const reader = body.getReader();
176
+ const decoder = new TextDecoder();
177
+ let buffer = '';
178
+ try {
179
+ let done = false;
180
+ while (!done) {
181
+ const result = await reader.read();
182
+ done = result.done;
183
+ if (done)
184
+ break;
185
+ buffer += decoder.decode(result.value, { stream: true });
186
+ const lines = buffer.split('\n');
187
+ // Keep the last (potentially incomplete) line in the buffer
188
+ buffer = lines.pop() ?? '';
189
+ for (const line of lines) {
190
+ const event = parseStreamEvent(line);
191
+ if (event)
192
+ applyStreamEvent(event);
193
+ }
194
+ }
195
+ // Flush any remaining data in the buffer
196
+ if (buffer.trim()) {
197
+ const event = parseStreamEvent(buffer);
198
+ if (event)
199
+ applyStreamEvent(event);
200
+ }
201
+ }
202
+ catch (err) {
203
+ if (controller.signal.aborted)
204
+ return;
205
+ const cause = err instanceof Error ? err : undefined;
206
+ throw new AdminAgentStreamError('Stream read failed', { cause });
207
+ }
208
+ finally {
209
+ reader.releaseLock();
210
+ }
211
+ }, [url, headers, effectiveFetch, applyStreamEvent]);
212
+ const abort = useCallback(() => {
213
+ abortRef.current?.abort();
214
+ abortRef.current = null;
215
+ inProgressIdRef.current = null;
216
+ setStatus('idle');
217
+ setCurrentToolName(null);
218
+ }, []);
219
+ const toggle = useCallback(() => setIsOpen((v) => !v), []);
220
+ const open = useCallback(() => setIsOpen(true), []);
221
+ const close = useCallback(() => setIsOpen(false), []);
222
+ const value = {
223
+ messages,
224
+ status,
225
+ isOpen,
226
+ currentToolName,
227
+ sendMessage,
228
+ abort,
229
+ toggle,
230
+ open,
231
+ close,
232
+ };
233
+ return (_jsx(AdminAgentContext.Provider, { value: value, children: children }));
234
+ }
235
+ //# sourceMappingURL=AdminAgentProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminAgentProvider.js","sourceRoot":"","sources":["../../src/components/AdminAgentProvider.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { AdminAgentTriggerProps } from '../types';
3
+ export declare function AdminAgentTrigger({ className, position, icon, }: AdminAgentTriggerProps): React.ReactElement;
4
+ //# sourceMappingURL=AdminAgentTrigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminAgentTrigger.d.ts","sourceRoot":"","sources":["../../src/components/AdminAgentTrigger.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAiBvD,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAyB,EACzB,IAAI,GACL,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CAuC7C"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAdminAgentChat } from '../hooks/useAdminAgentChat';
3
+ const SparklesIcon = () => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("path", { d: "M12 2l2.09 6.26L20 10l-5.91 1.74L12 18l-2.09-6.26L4 10l5.91-1.74z" }), _jsx("path", { d: "M5 3l.94 2.82L8.5 7l-2.56.18L5 10l-.94-2.82L1.5 7l2.56-.18z" }), _jsx("path", { d: "M19 15l.94 2.82L22.5 19l-2.56.18L19 22l-.94-2.82L15.5 19l2.56-.18z" })] }));
4
+ export function AdminAgentTrigger({ className, position = 'bottom-right', icon, }) {
5
+ const { toggle, isOpen } = useAdminAgentChat();
6
+ const positionStyle = position === 'bottom-right'
7
+ ? { right: '24px', bottom: '24px' }
8
+ : { left: '24px', bottom: '24px' };
9
+ const buttonStyle = {
10
+ position: 'fixed',
11
+ ...positionStyle,
12
+ width: '56px',
13
+ height: '56px',
14
+ borderRadius: '50%',
15
+ background: isOpen ? '#1a1a2e' : '#4f46e5',
16
+ color: '#fff',
17
+ border: 'none',
18
+ cursor: 'pointer',
19
+ display: 'flex',
20
+ alignItems: 'center',
21
+ justifyContent: 'center',
22
+ boxShadow: '0 4px 14px rgba(0,0,0,0.25)',
23
+ zIndex: 1000,
24
+ transition: 'background 0.2s',
25
+ };
26
+ return (_jsx("button", { type: "button", "aria-label": isOpen ? 'Close admin agent' : 'Open admin agent', "aria-expanded": isOpen, style: buttonStyle, className: className, onClick: toggle, "data-testid": "admin-agent-trigger", children: icon ?? _jsx(SparklesIcon, {}) }));
27
+ }
28
+ //# sourceMappingURL=AdminAgentTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminAgentTrigger.js","sourceRoot":"","sources":["../../src/components/AdminAgentTrigger.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG/D,MAAM,YAAY,GAAa,GAAG,EAAE,CAAC,CACnC,eACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,cAAc,iBACP,MAAM,aAElB,eAAM,CAAC,EAAC,mEAAmE,GAAG,EAC9E,eAAM,CAAC,EAAC,6DAA6D,GAAG,EACxE,eAAM,CAAC,EAAC,oEAAoE,GAAG,IAC3E,CACP,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAQ,GAAG,cAAc,EACzB,IAAI,GACmB;IACvB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAE/C,MAAM,aAAa,GACjB,QAAQ,KAAK,cAAc;QACzB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;QACnC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAEvC,MAAM,WAAW,GAAwB;QACvC,QAAQ,EAAE,OAAO;QACjB,GAAG,aAAa;QAChB,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,KAAK;QACnB,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC1C,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;QACxB,SAAS,EAAE,6BAA6B;QACxC,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,iBAAiB;KAC9B,CAAC;IAEF,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,gBACD,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,mBAC9C,MAAM,EACrB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,MAAM,iBACH,qBAAqB,YAEhC,IAAI,IAAI,KAAC,YAAY,KAAG,GAClB,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { AgentStatusBarProps } from '../types';
3
+ export declare function AgentStatusBar({ status, executingTool, className, }: AgentStatusBarProps): React.ReactElement | null;
4
+ //# sourceMappingURL=AgentStatusBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentStatusBar.d.ts","sourceRoot":"","sources":["../../src/components/AgentStatusBar.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAmBjE,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,SAAS,GACV,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAyCjD"}
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ function statusLabel(status, executingTool) {
3
+ switch (status) {
4
+ case 'idle':
5
+ return '';
6
+ case 'thinking':
7
+ return 'Thinking…';
8
+ case 'executing':
9
+ return executingTool
10
+ ? `Executing ${executingTool}…`
11
+ : 'Executing…';
12
+ case 'responding':
13
+ return 'Responding…';
14
+ case 'error':
15
+ return 'Error — retry?';
16
+ }
17
+ }
18
+ export function AgentStatusBar({ status, executingTool, className, }) {
19
+ const label = statusLabel(status, executingTool);
20
+ if (!label)
21
+ return null;
22
+ const isError = status === 'error';
23
+ const barStyle = {
24
+ padding: '6px 16px',
25
+ fontSize: '12px',
26
+ color: isError ? '#dc2626' : '#6b7280',
27
+ background: isError ? '#fef2f2' : '#f9fafb',
28
+ borderTop: `1px solid ${isError ? '#fecaca' : '#e5e7eb'}`,
29
+ display: 'flex',
30
+ alignItems: 'center',
31
+ gap: '6px',
32
+ };
33
+ return (_jsxs("div", { role: "status", "aria-live": "polite", style: barStyle, className: className, "data-testid": "agent-status-bar", "data-status": status, children: [!isError && (_jsx("span", { "aria-hidden": "true", style: {
34
+ display: 'inline-block',
35
+ width: '6px',
36
+ height: '6px',
37
+ borderRadius: '50%',
38
+ background: '#4f46e5',
39
+ animation: 'pulse 1.5s infinite',
40
+ } })), label] }));
41
+ }
42
+ //# sourceMappingURL=AgentStatusBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentStatusBar.js","sourceRoot":"","sources":["../../src/components/AgentStatusBar.tsx"],"names":[],"mappings":";AAWA,SAAS,WAAW,CAAC,MAAmB,EAAE,aAAsB;IAC9D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,EAAE,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,WAAW,CAAC;QACrB,KAAK,WAAW;YACd,OAAO,aAAa;gBAClB,CAAC,CAAC,aAAa,aAAa,GAAG;gBAC/B,CAAC,CAAC,YAAY,CAAC;QACnB,KAAK,YAAY;YACf,OAAO,aAAa,CAAC;QACvB,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,SAAS,GACW;IACpB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,OAAO,GAAG,MAAM,KAAK,OAAO,CAAC;IACnC,MAAM,QAAQ,GAAwB;QACpC,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACtC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC3C,SAAS,EAAE,aAAa,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;QACzD,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,GAAG,EAAE,KAAK;KACX,CAAC;IAEF,OAAO,CACL,eACE,IAAI,EAAC,QAAQ,eACH,QAAQ,EAClB,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,SAAS,iBACR,kBAAkB,iBACjB,MAAM,aAElB,CAAC,OAAO,IAAI,CACX,8BACc,MAAM,EAClB,KAAK,EAAE;oBACL,OAAO,EAAE,cAAc;oBACvB,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,KAAK;oBACb,YAAY,EAAE,KAAK;oBACnB,UAAU,EAAE,SAAS;oBACrB,SAAS,EAAE,qBAAqB;iBACjC,GACD,CACH,EACA,KAAK,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { AssistantMessageContentProps } from '../types';
3
+ export declare function AssistantMessageContent({ content, className, }: AssistantMessageContentProps): React.ReactElement;
4
+ //# sourceMappingURL=AssistantMessageContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantMessageContent.d.ts","sourceRoot":"","sources":["../../src/components/AssistantMessageContent.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AAE7D,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,SAAS,GACV,EAAE,4BAA4B,GAAG,KAAK,CAAC,YAAY,CAiBnD"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export function AssistantMessageContent({ content, className, }) {
3
+ const style = {
4
+ whiteSpace: 'pre-wrap',
5
+ wordBreak: 'break-word',
6
+ lineHeight: 1.5,
7
+ color: '#111827',
8
+ };
9
+ return (_jsx("div", { style: style, className: className, "data-testid": "assistant-message-content", children: content }));
10
+ }
11
+ //# sourceMappingURL=AssistantMessageContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantMessageContent.js","sourceRoot":"","sources":["../../src/components/AssistantMessageContent.tsx"],"names":[],"mappings":";AAWA,MAAM,UAAU,uBAAuB,CAAC,EACtC,OAAO,EACP,SAAS,GACoB;IAC7B,MAAM,KAAK,GAAwB;QACjC,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,YAAY;QACvB,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,SAAS;KACjB,CAAC;IAEF,OAAO,CACL,cACE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,iBACR,2BAA2B,YAEtC,OAAO,GACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { ChangeSummaryCardProps } from '../types';
3
+ export declare function ChangeSummaryCard({ summary, defaultExpanded, }: ChangeSummaryCardProps): React.ReactElement;
4
+ //# sourceMappingURL=ChangeSummaryCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangeSummaryCard.d.ts","sourceRoot":"","sources":["../../src/components/ChangeSummaryCard.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,eAAuB,GACxB,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CAqF7C"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ import { useState } from 'react';
10
+ export function ChangeSummaryCard({ summary, defaultExpanded = false, }) {
11
+ const [isExpanded, setIsExpanded] = useState(defaultExpanded);
12
+ const cardStyle = {
13
+ margin: '8px 0 0',
14
+ border: '1px solid #e5e7eb',
15
+ borderRadius: '8px',
16
+ overflow: 'hidden',
17
+ fontSize: '13px',
18
+ };
19
+ const headerStyle = {
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ justifyContent: 'space-between',
23
+ padding: '8px 12px',
24
+ background: '#f9fafb',
25
+ borderBottom: isExpanded ? '1px solid #e5e7eb' : 'none',
26
+ cursor: 'pointer',
27
+ fontWeight: 600,
28
+ color: '#374151',
29
+ };
30
+ const statsStyle = {
31
+ display: 'flex',
32
+ gap: '12px',
33
+ padding: '8px 12px',
34
+ background: '#fff',
35
+ borderBottom: '1px solid #f3f4f6',
36
+ fontSize: '12px',
37
+ color: '#6b7280',
38
+ };
39
+ const markdownStyle = {
40
+ padding: '8px 12px',
41
+ background: '#fff',
42
+ whiteSpace: 'pre-wrap',
43
+ lineHeight: 1.5,
44
+ color: '#374151',
45
+ fontFamily: 'inherit',
46
+ margin: 0,
47
+ };
48
+ return (_jsxs("div", { style: cardStyle, "data-testid": "change-summary-card", children: [_jsxs("div", { style: headerStyle, role: "button", "aria-expanded": isExpanded, tabIndex: 0, onClick: () => setIsExpanded((v) => !v), onKeyDown: (e) => {
49
+ if (e.key === 'Enter' || e.key === ' ') {
50
+ e.preventDefault();
51
+ setIsExpanded((v) => !v);
52
+ }
53
+ }, children: [_jsx("span", { children: "Change Summary" }), _jsx("span", { "aria-hidden": "true", children: isExpanded ? '▲' : '▼' })] }), isExpanded && (_jsxs(_Fragment, { children: [_jsxs("div", { style: statsStyle, children: [_jsxs("span", { children: [_jsx("strong", { children: summary.totalChanges }), " total"] }), _jsxs("span", { style: { color: '#16a34a' }, children: [_jsx("strong", { children: summary.successfulChanges }), " succeeded"] }), summary.failedChanges > 0 && (_jsxs("span", { style: { color: '#dc2626' }, children: [_jsx("strong", { children: summary.failedChanges }), " failed"] }))] }), _jsx("pre", { style: markdownStyle, children: summary.markdown })] }))] }));
54
+ }
55
+ //# sourceMappingURL=ChangeSummaryCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangeSummaryCard.js","sourceRoot":"","sources":["../../src/components/ChangeSummaryCard.tsx"],"names":[],"mappings":";AAAA;;;;;;EAME;AAEF,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGxC,MAAM,UAAU,iBAAiB,CAAC,EAChC,OAAO,EACP,eAAe,GAAG,KAAK,GACA;IACvB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;IAE9D,MAAM,SAAS,GAAwB;QACrC,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,mBAAmB;QAC3B,YAAY,EAAE,KAAK;QACnB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,MAAM;KACjB,CAAC;IAEF,MAAM,WAAW,GAAwB;QACvC,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,eAAe;QAC/B,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,SAAS;QACrB,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM;QACvD,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,SAAS;KACjB,CAAC;IAEF,MAAM,UAAU,GAAwB;QACtC,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM;QACX,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,MAAM;QAClB,YAAY,EAAE,mBAAmB;QACjC,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,SAAS;KACjB,CAAC;IAEF,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,MAAM;QAClB,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,CAAC;KACV,CAAC;IAEF,OAAO,CACL,eACE,KAAK,EAAE,SAAS,iBACJ,qBAAqB,aAEjC,eACE,KAAK,EAAE,WAAW,EAClB,IAAI,EAAC,QAAQ,mBACE,UAAU,EACzB,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EACvC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;oBACf,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;wBACvC,CAAC,CAAC,cAAc,EAAE,CAAC;wBACnB,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3B,CAAC;gBACH,CAAC,aAED,4CAA2B,EAC3B,8BAAkB,MAAM,YAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,IACpD,EAEL,UAAU,IAAI,CACb,8BACE,eAAK,KAAK,EAAE,UAAU,aACpB,2BACE,2BAAS,OAAO,CAAC,YAAY,GAAU,cAClC,EACP,gBAAM,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,aAC/B,2BAAS,OAAO,CAAC,iBAAiB,GAAU,kBACvC,EACN,OAAO,CAAC,aAAa,GAAG,CAAC,IAAI,CAC5B,gBAAM,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,aAC/B,2BAAS,OAAO,CAAC,aAAa,GAAU,eACnC,CACR,IACG,EACN,cAAK,KAAK,EAAE,aAAa,YAAG,OAAO,CAAC,QAAQ,GAAO,IAClD,CACJ,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { MessageBubbleProps } from '../types';
3
+ export declare function MessageBubble({ message, className, }: MessageBubbleProps): React.ReactElement;
4
+ //# sourceMappingURL=MessageBubble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../src/components/MessageBubble.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAS,GACV,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAuEzC"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { AssistantMessageContent } from './AssistantMessageContent';
3
+ import { ChangeSummaryCard } from './ChangeSummaryCard';
4
+ import { ToolResultCard } from './ToolResultCard';
5
+ import { UserMessageContent } from './UserMessageContent';
6
+ export function MessageBubble({ message, className, }) {
7
+ const isUser = message.role === 'user';
8
+ const wrapperStyle = {
9
+ display: 'flex',
10
+ flexDirection: 'column',
11
+ alignItems: isUser ? 'flex-end' : 'flex-start',
12
+ padding: '4px 16px',
13
+ };
14
+ const bubbleStyle = {
15
+ maxWidth: '80%',
16
+ padding: '10px 14px',
17
+ borderRadius: isUser ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
18
+ background: isUser ? '#4f46e5' : '#f3f4f6',
19
+ color: isUser ? '#fff' : '#111827',
20
+ };
21
+ const metaStyle = {
22
+ fontSize: '11px',
23
+ color: '#9ca3af',
24
+ marginTop: '4px',
25
+ paddingLeft: isUser ? '0' : '2px',
26
+ paddingRight: isUser ? '2px' : '0',
27
+ };
28
+ const timestamp = new Date(message.timestamp).toLocaleTimeString(undefined, {
29
+ hour: '2-digit',
30
+ minute: '2-digit',
31
+ });
32
+ return (_jsxs("div", { style: wrapperStyle, className: className, "data-testid": "message-bubble", "data-role": message.role, children: [_jsx("div", { style: bubbleStyle, children: isUser ? (_jsx(UserMessageContent, { content: message.content })) : (_jsx(AssistantMessageContent, { content: message.content })) }), !isUser && message.toolResults && message.toolResults.length > 0 && (_jsx("div", { style: { maxWidth: '80%', width: '100%' }, children: message.toolResults.map((tr) => (_jsx(ToolResultCard, { toolName: tr.toolName, success: tr.success, summary: tr.summary, data: tr.data }, tr.toolCallId))) })), !isUser && message.changeSummary && (_jsx("div", { style: { maxWidth: '80%', width: '100%' }, children: _jsx(ChangeSummaryCard, { summary: message.changeSummary }) })), _jsx("div", { style: metaStyle, children: _jsx("time", { dateTime: message.timestamp, children: timestamp }) })] }));
33
+ }
34
+ //# sourceMappingURL=MessageBubble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBubble.js","sourceRoot":"","sources":["../../src/components/MessageBubble.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,MAAM,UAAU,aAAa,CAAC,EAC5B,OAAO,EACP,SAAS,GACU;IACnB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC;IAEvC,MAAM,YAAY,GAAwB;QACxC,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;QAC9C,OAAO,EAAE,UAAU;KACpB,CAAC;IAEF,MAAM,WAAW,GAAwB;QACvC,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB;QAClE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC1C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KACnC,CAAC;IAEF,MAAM,SAAS,GAAwB;QACrC,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,KAAK;QAChB,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;QACjC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;KACnC,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE;QAC1E,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;IAEH,OAAO,CACL,eACE,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,SAAS,iBACR,gBAAgB,eACjB,OAAO,CAAC,IAAI,aAEvB,cAAK,KAAK,EAAE,WAAW,YACpB,MAAM,CAAC,CAAC,CAAC,CACR,KAAC,kBAAkB,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAI,CACjD,CAAC,CAAC,CAAC,CACF,KAAC,uBAAuB,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAI,CACtD,GACG,EAEL,CAAC,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACnE,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAC3C,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAC/B,KAAC,cAAc,IAEb,QAAQ,EAAE,EAAE,CAAC,QAAQ,EACrB,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,IAAI,EAAE,EAAE,CAAC,IAAI,IAJR,EAAE,CAAC,UAAU,CAKlB,CACH,CAAC,GACE,CACP,EAEA,CAAC,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,CACnC,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAC5C,KAAC,iBAAiB,IAAC,OAAO,EAAE,OAAO,CAAC,aAAa,GAAI,GACjD,CACP,EAED,cAAK,KAAK,EAAE,SAAS,YACnB,eAAM,QAAQ,EAAE,OAAO,CAAC,SAAS,YAAG,SAAS,GAAQ,GACjD,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { MessageListProps } from '../types';
3
+ export declare function MessageList({ messages, className, }: MessageListProps): React.ReactElement;
4
+ //# sourceMappingURL=MessageList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAQA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAS,GACV,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CA+CvC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ import { useEffect, useRef } from 'react';
10
+ import { MessageBubble } from './MessageBubble';
11
+ export function MessageList({ messages, className, }) {
12
+ const bottomRef = useRef(null);
13
+ useEffect(() => {
14
+ const el = bottomRef.current;
15
+ if (el && typeof el.scrollIntoView === 'function') {
16
+ el.scrollIntoView({ behavior: 'smooth' });
17
+ }
18
+ }, [messages]);
19
+ const listStyle = {
20
+ flex: 1,
21
+ overflowY: 'auto',
22
+ padding: '8px 0',
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ };
26
+ const emptyStyle = {
27
+ flex: 1,
28
+ display: 'flex',
29
+ alignItems: 'center',
30
+ justifyContent: 'center',
31
+ color: '#9ca3af',
32
+ fontSize: '14px',
33
+ padding: '32px',
34
+ textAlign: 'center',
35
+ };
36
+ if (messages.length === 0) {
37
+ return (_jsx("div", { style: listStyle, className: className, "data-testid": "message-list", children: _jsx("div", { style: emptyStyle, children: "Ask the admin agent anything \u2014 it can view and modify your data." }) }));
38
+ }
39
+ return (_jsxs("div", { style: listStyle, className: className, "data-testid": "message-list", children: [messages.map((msg) => (_jsx(MessageBubble, { message: msg }, msg.id))), _jsx("div", { ref: bottomRef })] }));
40
+ }
41
+ //# sourceMappingURL=MessageList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":";AAAA;;;;;;EAME;AAEF,OAAc,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAS,GACQ;IACjB,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YAClD,EAAE,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,SAAS,GAAwB;QACrC,IAAI,EAAE,CAAC;QACP,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;KACxB,CAAC;IAEF,MAAM,UAAU,GAAwB;QACtC,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;QACxB,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,MAAM;QACf,SAAS,EAAE,QAAQ;KACpB,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CACL,cAAK,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,iBAAc,cAAc,YACrE,cAAK,KAAK,EAAE,UAAU,sFAEhB,GACF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAK,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,iBAAc,cAAc,aACpE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACrB,KAAC,aAAa,IAAc,OAAO,EAAE,GAAG,IAApB,GAAG,CAAC,EAAE,CAAkB,CAC7C,CAAC,EACF,cAAK,GAAG,EAAE,SAAS,GAAI,IACnB,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { ToolResultCardProps } from '../types';
3
+ export declare function ToolResultCard({ toolName, success, summary, data, expanded, }: ToolResultCardProps): React.ReactElement;
4
+ //# sourceMappingURL=ToolResultCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolResultCard.d.ts","sourceRoot":"","sources":["../../src/components/ToolResultCard.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,OAAO,EACP,IAAI,EACJ,QAAgB,GACjB,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAmF1C"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ import { useState } from 'react';
10
+ export function ToolResultCard({ toolName, success, summary, data, expanded = false, }) {
11
+ const [isExpanded, setIsExpanded] = useState(expanded);
12
+ const cardStyle = {
13
+ margin: '4px 0',
14
+ padding: '8px 12px',
15
+ borderRadius: '6px',
16
+ background: success ? '#f0fdf4' : '#fef2f2',
17
+ border: `1px solid ${success ? '#bbf7d0' : '#fecaca'}`,
18
+ fontSize: '12px',
19
+ };
20
+ const headerStyle = {
21
+ display: 'flex',
22
+ alignItems: 'center',
23
+ gap: '8px',
24
+ cursor: data !== undefined ? 'pointer' : 'default',
25
+ };
26
+ const indicatorStyle = {
27
+ width: '8px',
28
+ height: '8px',
29
+ borderRadius: '50%',
30
+ flexShrink: 0,
31
+ background: success ? '#16a34a' : '#dc2626',
32
+ };
33
+ const toolNameStyle = {
34
+ fontWeight: 600,
35
+ color: success ? '#15803d' : '#b91c1c',
36
+ };
37
+ const summaryStyle = {
38
+ color: success ? '#166534' : '#991b1b',
39
+ marginLeft: '16px',
40
+ };
41
+ const dataStyle = {
42
+ marginTop: '6px',
43
+ padding: '6px 8px',
44
+ background: '#fff',
45
+ borderRadius: '4px',
46
+ fontFamily: 'monospace',
47
+ fontSize: '11px',
48
+ whiteSpace: 'pre-wrap',
49
+ wordBreak: 'break-all',
50
+ color: '#374151',
51
+ };
52
+ const hasData = data !== undefined;
53
+ return (_jsxs("div", { style: cardStyle, "data-testid": "tool-result-card", "data-success": success, "data-tool": toolName, children: [hasData ? (_jsxs("button", { type: "button", style: { ...headerStyle, background: 'none', border: 'none', width: '100%', textAlign: 'left', padding: 0, cursor: 'pointer' }, "aria-expanded": isExpanded, onClick: () => setIsExpanded((v) => !v), children: [_jsx("span", { style: indicatorStyle, "aria-hidden": "true" }), _jsx("span", { style: toolNameStyle, children: toolName }), _jsx("span", { style: { marginLeft: 'auto', color: '#6b7280' }, children: isExpanded ? '▲' : '▼' })] })) : (_jsxs("div", { style: headerStyle, children: [_jsx("span", { style: indicatorStyle, "aria-hidden": "true" }), _jsx("span", { style: toolNameStyle, children: toolName })] })), summary && _jsx("div", { style: summaryStyle, children: summary }), hasData && isExpanded && (_jsx("pre", { style: dataStyle, children: JSON.stringify(data, null, 2) }))] }));
54
+ }
55
+ //# sourceMappingURL=ToolResultCard.js.map