@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.
- package/LICENSE +5 -0
- package/README.md +332 -27
- package/dist/components/AdminAgentInput.d.ts +4 -0
- package/dist/components/AdminAgentInput.d.ts.map +1 -0
- package/dist/components/AdminAgentInput.js +72 -0
- package/dist/components/AdminAgentInput.js.map +1 -0
- package/dist/components/AdminAgentPanel.d.ts +4 -0
- package/dist/components/AdminAgentPanel.d.ts.map +1 -0
- package/dist/components/AdminAgentPanel.js +26 -0
- package/dist/components/AdminAgentPanel.js.map +1 -0
- package/dist/components/AdminAgentPanelHeader.d.ts +4 -0
- package/dist/components/AdminAgentPanelHeader.d.ts.map +1 -0
- package/dist/components/AdminAgentPanelHeader.js +42 -0
- package/dist/components/AdminAgentPanelHeader.js.map +1 -0
- package/dist/components/AdminAgentProvider.d.ts +4 -0
- package/dist/components/AdminAgentProvider.d.ts.map +1 -0
- package/dist/components/AdminAgentProvider.js +235 -0
- package/dist/components/AdminAgentProvider.js.map +1 -0
- package/dist/components/AdminAgentTrigger.d.ts +4 -0
- package/dist/components/AdminAgentTrigger.d.ts.map +1 -0
- package/dist/components/AdminAgentTrigger.js +28 -0
- package/dist/components/AdminAgentTrigger.js.map +1 -0
- package/dist/components/AgentStatusBar.d.ts +4 -0
- package/dist/components/AgentStatusBar.d.ts.map +1 -0
- package/dist/components/AgentStatusBar.js +42 -0
- package/dist/components/AgentStatusBar.js.map +1 -0
- package/dist/components/AssistantMessageContent.d.ts +4 -0
- package/dist/components/AssistantMessageContent.d.ts.map +1 -0
- package/dist/components/AssistantMessageContent.js +11 -0
- package/dist/components/AssistantMessageContent.js.map +1 -0
- package/dist/components/ChangeSummaryCard.d.ts +4 -0
- package/dist/components/ChangeSummaryCard.d.ts.map +1 -0
- package/dist/components/ChangeSummaryCard.js +55 -0
- package/dist/components/ChangeSummaryCard.js.map +1 -0
- package/dist/components/MessageBubble.d.ts +4 -0
- package/dist/components/MessageBubble.d.ts.map +1 -0
- package/dist/components/MessageBubble.js +34 -0
- package/dist/components/MessageBubble.js.map +1 -0
- package/dist/components/MessageList.d.ts +4 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +41 -0
- package/dist/components/MessageList.js.map +1 -0
- package/dist/components/ToolResultCard.d.ts +4 -0
- package/dist/components/ToolResultCard.d.ts.map +1 -0
- package/dist/components/ToolResultCard.js +55 -0
- package/dist/components/ToolResultCard.js.map +1 -0
- package/dist/components/UserMessageContent.d.ts +4 -0
- package/dist/components/UserMessageContent.d.ts.map +1 -0
- package/dist/components/UserMessageContent.js +11 -0
- package/dist/components/UserMessageContent.js.map +1 -0
- package/dist/context.d.ts +4 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +10 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/hooks/useAdminAgentChat.d.ts +7 -0
- package/dist/hooks/useAdminAgentChat.d.ts.map +1 -0
- package/dist/hooks/useAdminAgentChat.js +22 -0
- package/dist/hooks/useAdminAgentChat.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +120 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright (c) 2025 Bernier LLC
|
|
2
|
+
|
|
3
|
+
This file is licensed to the client under a limited-use license.
|
|
4
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
5
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
package/README.md
CHANGED
|
@@ -1,45 +1,350 @@
|
|
|
1
1
|
# @bernierllc/admin-agent-chat-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components for an embedded admin LLM agent: floating trigger, slide-in chat panel, streaming message bubbles, tool-result cards, and change summary.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
This
|
|
7
|
+
This package provides a complete frontend UI for the admin agent chat system. Drop `<AdminAgentProvider>` + `<AdminAgentTrigger>` + `<AdminAgentPanel>` into any React app and get a fully functional floating chat widget that streams responses from an SSE endpoint.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**Architecture:**
|
|
10
|
+
- All business logic lives in the `useAdminAgentChat` hook (headless)
|
|
11
|
+
- Styled components are thin wrappers you can use as-is or replace with your own UI
|
|
12
|
+
- Consumes newline-delimited JSON events from the `admin-agent-nextjs` SSE endpoint
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `@bernierllc/admin-agent-chat-ui`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
14
|
+
## Installation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
```bash
|
|
17
|
+
npm install @bernierllc/admin-agent-chat-ui react react-dom
|
|
18
|
+
```
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
## Quick Start
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
```tsx
|
|
23
|
+
// app/(admin)/layout.tsx
|
|
24
|
+
import {
|
|
25
|
+
AdminAgentProvider,
|
|
26
|
+
AdminAgentTrigger,
|
|
27
|
+
AdminAgentPanel,
|
|
28
|
+
} from '@bernierllc/admin-agent-chat-ui';
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
|
31
|
+
return (
|
|
32
|
+
<AdminAgentProvider url="/api/chat/admin">
|
|
33
|
+
{children}
|
|
34
|
+
<AdminAgentTrigger position="bottom-right" />
|
|
35
|
+
<AdminAgentPanel />
|
|
36
|
+
</AdminAgentProvider>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
23
40
|
|
|
24
|
-
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
41
|
+
This renders a `Sparkles` button fixed at the bottom-right. Clicking it opens a slide-in panel with a full streaming chat interface.
|
|
28
42
|
|
|
29
|
-
##
|
|
43
|
+
## Headless Usage
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
45
|
+
Use only the hook and build your own UI:
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
```tsx
|
|
48
|
+
import { AdminAgentProvider, useAdminAgentChat } from '@bernierllc/admin-agent-chat-ui';
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
function MyChat() {
|
|
51
|
+
const { messages, status, sendMessage, isOpen, toggle } = useAdminAgentChat();
|
|
52
|
+
|
|
53
|
+
if (!isOpen) return null;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div>
|
|
57
|
+
{messages.map((msg) => (
|
|
58
|
+
<div key={msg.id}>
|
|
59
|
+
<strong>{msg.role}</strong>: {msg.content}
|
|
60
|
+
|
|
61
|
+
{msg.toolResults?.map((tr) => (
|
|
62
|
+
<div
|
|
63
|
+
key={tr.toolCallId}
|
|
64
|
+
style={{ color: tr.success ? 'green' : 'red' }}
|
|
65
|
+
>
|
|
66
|
+
[{tr.toolName}] {tr.summary}
|
|
67
|
+
</div>
|
|
68
|
+
))}
|
|
69
|
+
|
|
70
|
+
{msg.changeSummary && (
|
|
71
|
+
<pre>{msg.changeSummary.markdown}</pre>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
))}
|
|
75
|
+
|
|
76
|
+
<p>Status: {status}</p>
|
|
77
|
+
|
|
78
|
+
<button onClick={() => void sendMessage('Hello!')}>Say hello</button>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default function App() {
|
|
84
|
+
return (
|
|
85
|
+
<AdminAgentProvider url="/api/chat/admin">
|
|
86
|
+
<MyChat />
|
|
87
|
+
</AdminAgentProvider>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## SSE Stream Protocol
|
|
93
|
+
|
|
94
|
+
The provider POSTs to `url` with body `{ message: string }` and reads newline-delimited JSON events:
|
|
95
|
+
|
|
96
|
+
```jsonc
|
|
97
|
+
// Each line is one JSON object followed by \n
|
|
98
|
+
{"type":"text-delta","delta":"Hello "}
|
|
99
|
+
{"type":"text-delta","delta":"world"}
|
|
100
|
+
{"type":"tool-call-start","toolCallId":"tc1","toolName":"addService"}
|
|
101
|
+
{"type":"tool-call-result","toolCallId":"tc1","success":true,"summary":"Added Haircut at $45","data":{...}}
|
|
102
|
+
{"type":"change-summary","summary":{...RollupSummary}}
|
|
103
|
+
{"type":"done"}
|
|
104
|
+
|
|
105
|
+
// Error path:
|
|
106
|
+
{"type":"error","message":"Something went wrong"}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Components
|
|
110
|
+
|
|
111
|
+
### `<AdminAgentProvider>`
|
|
112
|
+
|
|
113
|
+
Context provider. Must wrap all other components and `useAdminAgentChat` calls.
|
|
114
|
+
|
|
115
|
+
| Prop | Type | Required | Default | Description |
|
|
116
|
+
|------|------|----------|---------|-------------|
|
|
117
|
+
| `url` | `string` | Yes | — | SSE POST endpoint (e.g. `/api/chat/admin`) |
|
|
118
|
+
| `headers` | `Record<string, string>` | No | `{}` | Extra request headers (e.g. auth token) |
|
|
119
|
+
| `children` | `React.ReactNode` | Yes | — | Your app tree |
|
|
120
|
+
| `fetchFn` | `typeof fetch` | No | `globalThis.fetch` | Override fetch (useful for testing) |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### `<AdminAgentTrigger>`
|
|
125
|
+
|
|
126
|
+
Floating action button that toggles the panel open/closed.
|
|
127
|
+
|
|
128
|
+
| Prop | Type | Required | Default | Description |
|
|
129
|
+
|------|------|----------|---------|-------------|
|
|
130
|
+
| `position` | `'bottom-right' \| 'bottom-left'` | No | `'bottom-right'` | Corner to position the button |
|
|
131
|
+
| `icon` | `React.ReactNode` | No | Sparkles SVG | Override the button icon |
|
|
132
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<AdminAgentTrigger position="bottom-right" />
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### `<AdminAgentPanel>`
|
|
141
|
+
|
|
142
|
+
Slide-in panel from the right edge. Renders nothing when closed.
|
|
143
|
+
|
|
144
|
+
| Prop | Type | Required | Default | Description |
|
|
145
|
+
|------|------|----------|---------|-------------|
|
|
146
|
+
| `width` | `number \| string` | No | `380` | Panel width (px number or CSS string) |
|
|
147
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
<AdminAgentPanel width={420} />
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### `<AdminAgentPanelHeader>`
|
|
156
|
+
|
|
157
|
+
Header bar inside the panel with title and close button.
|
|
158
|
+
|
|
159
|
+
| Prop | Type | Required | Default | Description |
|
|
160
|
+
|------|------|----------|---------|-------------|
|
|
161
|
+
| `title` | `string` | No | `'Admin Agent'` | Panel heading text |
|
|
162
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
42
163
|
|
|
43
164
|
---
|
|
44
165
|
|
|
45
|
-
|
|
166
|
+
### `<MessageList>`
|
|
167
|
+
|
|
168
|
+
Scrollable list of message bubbles. Auto-scrolls to the latest message.
|
|
169
|
+
|
|
170
|
+
| Prop | Type | Required | Default | Description |
|
|
171
|
+
|------|------|----------|---------|-------------|
|
|
172
|
+
| `messages` | `UIMessage[]` | Yes | — | Messages to render |
|
|
173
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### `<MessageBubble>`
|
|
178
|
+
|
|
179
|
+
Single chat bubble. Delegates to `<UserMessageContent>` or `<AssistantMessageContent>` based on role, and renders `<ToolResultCard>` and `<ChangeSummaryCard>` overlays.
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Required | Description |
|
|
182
|
+
|------|------|----------|-------------|
|
|
183
|
+
| `message` | `UIMessage` | Yes | The message to render |
|
|
184
|
+
| `className` | `string` | No | Extra CSS class |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### `<AssistantMessageContent>`
|
|
189
|
+
|
|
190
|
+
Text content area styled for assistant messages.
|
|
191
|
+
|
|
192
|
+
| Prop | Type | Required | Description |
|
|
193
|
+
|------|------|----------|-------------|
|
|
194
|
+
| `content` | `string` | Yes | Text content (rendered with pre-wrap) |
|
|
195
|
+
| `className` | `string` | No | Extra CSS class |
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### `<UserMessageContent>`
|
|
200
|
+
|
|
201
|
+
Text content area styled for user messages (white text on indigo background).
|
|
202
|
+
|
|
203
|
+
| Prop | Type | Required | Description |
|
|
204
|
+
|------|------|----------|-------------|
|
|
205
|
+
| `content` | `string` | Yes | Text content |
|
|
206
|
+
| `className` | `string` | No | Extra CSS class |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### `<AdminAgentInput>`
|
|
211
|
+
|
|
212
|
+
Text input + send button for composing messages. Submits on Enter (Shift+Enter for newline) and disables while the agent is busy.
|
|
213
|
+
|
|
214
|
+
| Prop | Type | Required | Default | Description |
|
|
215
|
+
|------|------|----------|---------|-------------|
|
|
216
|
+
| `placeholder` | `string` | No | `'Message the admin agent…'` | Input placeholder |
|
|
217
|
+
| `disabled` | `boolean` | No | `false` | Force-disable the input |
|
|
218
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `<AgentStatusBar>`
|
|
223
|
+
|
|
224
|
+
Shows contextual status beneath the message list. Returns null when status is `'idle'`.
|
|
225
|
+
|
|
226
|
+
| Prop | Type | Required | Default | Description |
|
|
227
|
+
|------|------|----------|---------|-------------|
|
|
228
|
+
| `status` | `AgentStatus` | Yes | — | Current agent status |
|
|
229
|
+
| `executingTool` | `string` | No | — | Tool name shown during `'executing'` state |
|
|
230
|
+
| `className` | `string` | No | — | Extra CSS class |
|
|
231
|
+
|
|
232
|
+
Status labels:
|
|
233
|
+
|
|
234
|
+
| Status | Label |
|
|
235
|
+
|--------|-------|
|
|
236
|
+
| `idle` | *(hidden)* |
|
|
237
|
+
| `thinking` | `Thinking…` |
|
|
238
|
+
| `executing` | `Executing <toolName>…` |
|
|
239
|
+
| `responding` | `Responding…` |
|
|
240
|
+
| `error` | `Error — retry?` |
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### `<ToolResultCard>`
|
|
245
|
+
|
|
246
|
+
Green (success) or red (failure) card rendered per tool call. Expandable to show raw data.
|
|
247
|
+
|
|
248
|
+
| Prop | Type | Required | Default | Description |
|
|
249
|
+
|------|------|----------|---------|-------------|
|
|
250
|
+
| `toolName` | `string` | Yes | — | Name of the tool that ran |
|
|
251
|
+
| `success` | `boolean` | Yes | — | Whether the tool call succeeded |
|
|
252
|
+
| `summary` | `string` | Yes | — | One-line description of the change |
|
|
253
|
+
| `data` | `unknown` | No | — | Raw data to show when expanded |
|
|
254
|
+
| `expanded` | `boolean` | No | `false` | Start expanded |
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
<ToolResultCard
|
|
258
|
+
toolName="addService"
|
|
259
|
+
success={true}
|
|
260
|
+
summary="Added 'Haircut' at $45"
|
|
261
|
+
data={{ id: 42, name: 'Haircut', price: 45 }}
|
|
262
|
+
/>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### `<ChangeSummaryCard>`
|
|
268
|
+
|
|
269
|
+
End-of-conversation rollup card. Collapsible. Renders `RollupSummary.markdown` from `@bernierllc/agent-changeset`.
|
|
270
|
+
|
|
271
|
+
| Prop | Type | Required | Default | Description |
|
|
272
|
+
|------|------|----------|---------|-------------|
|
|
273
|
+
| `summary` | `RollupSummary` | Yes | — | Rollup from `agent-changeset` |
|
|
274
|
+
| `defaultExpanded` | `boolean` | No | `false` | Start expanded |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Hook: `useAdminAgentChat`
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
import { useAdminAgentChat } from '@bernierllc/admin-agent-chat-ui';
|
|
282
|
+
|
|
283
|
+
const {
|
|
284
|
+
messages, // UIMessage[] — full conversation history
|
|
285
|
+
status, // AgentStatus — current state machine state
|
|
286
|
+
isOpen, // boolean — whether the panel is open
|
|
287
|
+
currentToolName, // string | null — tool executing right now
|
|
288
|
+
sendMessage, // (text: string) => Promise<void>
|
|
289
|
+
abort, // () => void — cancel in-flight request
|
|
290
|
+
toggle, // () => void — toggle open/closed
|
|
291
|
+
open, // () => void — open the panel
|
|
292
|
+
close, // () => void — close the panel
|
|
293
|
+
} = useAdminAgentChat();
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Must be called inside `<AdminAgentProvider>`. Throws `AdminAgentUIError` with code `NO_PROVIDER` otherwise.
|
|
297
|
+
|
|
298
|
+
## Types
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
type AgentStatus = 'idle' | 'thinking' | 'executing' | 'responding' | 'error';
|
|
302
|
+
|
|
303
|
+
interface UIMessage {
|
|
304
|
+
id: string;
|
|
305
|
+
role: 'user' | 'assistant';
|
|
306
|
+
content: string;
|
|
307
|
+
toolResults?: UIToolResult[];
|
|
308
|
+
changeSummary?: RollupSummary; // from @bernierllc/agent-changeset
|
|
309
|
+
timestamp: string; // ISO 8601
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
interface UIToolResult {
|
|
313
|
+
toolName: string;
|
|
314
|
+
toolCallId: string;
|
|
315
|
+
success: boolean;
|
|
316
|
+
summary: string;
|
|
317
|
+
data?: unknown;
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Errors
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
import { AdminAgentUIError, AdminAgentStreamError } from '@bernierllc/admin-agent-chat-ui';
|
|
325
|
+
|
|
326
|
+
// Base error
|
|
327
|
+
class AdminAgentUIError extends Error {
|
|
328
|
+
readonly code: string; // e.g. 'UI_ERROR', 'NO_PROVIDER'
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Stream-specific error (extends AdminAgentUIError, code = 'STREAM_ERROR')
|
|
332
|
+
class AdminAgentStreamError extends AdminAgentUIError {}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Both errors use `Error.cause` chaining for full stack traces.
|
|
336
|
+
|
|
337
|
+
## State Machine
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
idle ──sendMessage──► thinking
|
|
341
|
+
thinking ────────────► executing (on tool-call-start)
|
|
342
|
+
executing ───────────► thinking (on tool-call-result, loop continues)
|
|
343
|
+
thinking ────────────► responding (on text-delta)
|
|
344
|
+
responding ──────────► idle (on done)
|
|
345
|
+
any ─────────────────► error (on error event or non-ok response)
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## License
|
|
349
|
+
|
|
350
|
+
Copyright (c) 2025 Bernier LLC. Licensed to the client under a limited-use license.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentInput.d.ts","sourceRoot":"","sources":["../../src/components/AdminAgentInput.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,WAAwC,EACxC,QAAQ,GACT,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CA8F3C"}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
import { useAdminAgentChat } from '../hooks/useAdminAgentChat';
|
|
11
|
+
export function AdminAgentInput({ className, placeholder = 'Message the admin agent…', disabled, }) {
|
|
12
|
+
const { sendMessage, status } = useAdminAgentChat();
|
|
13
|
+
const [value, setValue] = useState('');
|
|
14
|
+
const isBusy = status === 'thinking' || status === 'executing' || status === 'responding';
|
|
15
|
+
const isDisabled = disabled === true || isBusy;
|
|
16
|
+
const handleSubmit = (e) => {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
const text = value.trim();
|
|
19
|
+
if (!text || isDisabled)
|
|
20
|
+
return;
|
|
21
|
+
setValue('');
|
|
22
|
+
void sendMessage(text);
|
|
23
|
+
};
|
|
24
|
+
const handleKeyDown = (e) => {
|
|
25
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
const text = value.trim();
|
|
28
|
+
if (!text || isDisabled)
|
|
29
|
+
return;
|
|
30
|
+
setValue('');
|
|
31
|
+
void sendMessage(text);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const formStyle = {
|
|
35
|
+
display: 'flex',
|
|
36
|
+
alignItems: 'flex-end',
|
|
37
|
+
padding: '10px 16px',
|
|
38
|
+
borderTop: '1px solid #e5e7eb',
|
|
39
|
+
background: '#fff',
|
|
40
|
+
gap: '8px',
|
|
41
|
+
};
|
|
42
|
+
const textareaStyle = {
|
|
43
|
+
flex: 1,
|
|
44
|
+
padding: '8px 12px',
|
|
45
|
+
border: '1px solid #d1d5db',
|
|
46
|
+
borderRadius: '8px',
|
|
47
|
+
resize: 'none',
|
|
48
|
+
fontFamily: 'inherit',
|
|
49
|
+
fontSize: '14px',
|
|
50
|
+
lineHeight: 1.5,
|
|
51
|
+
color: '#111827',
|
|
52
|
+
background: isDisabled ? '#f9fafb' : '#fff',
|
|
53
|
+
minHeight: '40px',
|
|
54
|
+
maxHeight: '120px',
|
|
55
|
+
outline: 'none',
|
|
56
|
+
};
|
|
57
|
+
const buttonStyle = {
|
|
58
|
+
padding: '8px 14px',
|
|
59
|
+
background: isDisabled ? '#a5b4fc' : '#4f46e5',
|
|
60
|
+
color: '#fff',
|
|
61
|
+
border: 'none',
|
|
62
|
+
borderRadius: '8px',
|
|
63
|
+
cursor: isDisabled ? 'not-allowed' : 'pointer',
|
|
64
|
+
fontWeight: 600,
|
|
65
|
+
fontSize: '14px',
|
|
66
|
+
lineHeight: 1,
|
|
67
|
+
flexShrink: 0,
|
|
68
|
+
height: '40px',
|
|
69
|
+
};
|
|
70
|
+
return (_jsxs("form", { style: formStyle, className: className, onSubmit: handleSubmit, "data-testid": "admin-agent-input-form", children: [_jsx("textarea", { style: textareaStyle, value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isDisabled, rows: 1, "aria-label": "Message input", "data-testid": "admin-agent-textarea" }), _jsx("button", { type: "submit", style: buttonStyle, disabled: isDisabled || !value.trim(), "aria-label": "Send message", "data-testid": "admin-agent-send-button", children: "Send" })] }));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=AdminAgentInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentInput.js","sourceRoot":"","sources":["../../src/components/AdminAgentInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentPanel.d.ts","sourceRoot":"","sources":["../../src/components/AdminAgentPanel.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,KAAW,GACZ,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAsClD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAdminAgentChat } from '../hooks/useAdminAgentChat';
|
|
3
|
+
import { AdminAgentInput } from './AdminAgentInput';
|
|
4
|
+
import { AdminAgentPanelHeader } from './AdminAgentPanelHeader';
|
|
5
|
+
import { AgentStatusBar } from './AgentStatusBar';
|
|
6
|
+
import { MessageList } from './MessageList';
|
|
7
|
+
export function AdminAgentPanel({ className, width = 380, }) {
|
|
8
|
+
const { messages, status, isOpen, currentToolName } = useAdminAgentChat();
|
|
9
|
+
if (!isOpen)
|
|
10
|
+
return null;
|
|
11
|
+
const panelStyle = {
|
|
12
|
+
position: 'fixed',
|
|
13
|
+
top: 0,
|
|
14
|
+
right: 0,
|
|
15
|
+
bottom: 0,
|
|
16
|
+
width: typeof width === 'number' ? `${width}px` : width,
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'column',
|
|
19
|
+
background: '#fff',
|
|
20
|
+
boxShadow: '-4px 0 24px rgba(0,0,0,0.12)',
|
|
21
|
+
zIndex: 999,
|
|
22
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
23
|
+
};
|
|
24
|
+
return (_jsxs("div", { style: panelStyle, className: className, role: "dialog", "aria-label": "Admin Agent Chat", "aria-modal": "true", "data-testid": "admin-agent-panel", children: [_jsx(AdminAgentPanelHeader, {}), _jsx(MessageList, { messages: messages }), _jsx(AgentStatusBar, { status: status, executingTool: currentToolName ?? undefined }), _jsx(AdminAgentInput, {})] }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AdminAgentPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentPanel.js","sourceRoot":"","sources":["../../src/components/AdminAgentPanel.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,UAAU,eAAe,CAAC,EAC9B,SAAS,EACT,KAAK,GAAG,GAAG,GACU;IACrB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAE1E,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,UAAU,GAAwB;QACtC,QAAQ,EAAE,OAAO;QACjB,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK;QACvD,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,8BAA8B;QACzC,MAAM,EAAE,GAAG;QACX,UAAU,EACR,mEAAmE;KACtE,CAAC;IAEF,OAAO,CACL,eACE,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAC,QAAQ,gBACF,kBAAkB,gBAClB,MAAM,iBACL,mBAAmB,aAE/B,KAAC,qBAAqB,KAAG,EACzB,KAAC,WAAW,IAAC,QAAQ,EAAE,QAAQ,GAAI,EACnC,KAAC,cAAc,IACb,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,eAAe,IAAI,SAAS,GAC3C,EACF,KAAC,eAAe,KAAG,IACf,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentPanelHeader.d.ts","sourceRoot":"","sources":["../../src/components/AdminAgentPanelHeader.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAE3D,wBAAgB,qBAAqB,CAAC,EACpC,KAAqB,EACrB,SAAS,GACV,EAAE,0BAA0B,GAAG,KAAK,CAAC,YAAY,CAoEjD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAdminAgentChat } from '../hooks/useAdminAgentChat';
|
|
3
|
+
export function AdminAgentPanelHeader({ title = 'Admin Agent', className, }) {
|
|
4
|
+
const { close, status } = useAdminAgentChat();
|
|
5
|
+
const isActive = status !== 'idle' && status !== 'error';
|
|
6
|
+
const headerStyle = {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
padding: '14px 16px',
|
|
10
|
+
borderBottom: '1px solid #e5e7eb',
|
|
11
|
+
background: '#fff',
|
|
12
|
+
gap: '10px',
|
|
13
|
+
};
|
|
14
|
+
const titleStyle = {
|
|
15
|
+
flex: 1,
|
|
16
|
+
fontWeight: 600,
|
|
17
|
+
fontSize: '15px',
|
|
18
|
+
color: '#111827',
|
|
19
|
+
display: 'flex',
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
gap: '8px',
|
|
22
|
+
};
|
|
23
|
+
const dotStyle = {
|
|
24
|
+
width: '8px',
|
|
25
|
+
height: '8px',
|
|
26
|
+
borderRadius: '50%',
|
|
27
|
+
background: isActive ? '#10b981' : '#d1d5db',
|
|
28
|
+
flexShrink: 0,
|
|
29
|
+
};
|
|
30
|
+
const closeStyle = {
|
|
31
|
+
background: 'none',
|
|
32
|
+
border: 'none',
|
|
33
|
+
cursor: 'pointer',
|
|
34
|
+
color: '#6b7280',
|
|
35
|
+
padding: '4px',
|
|
36
|
+
lineHeight: 1,
|
|
37
|
+
borderRadius: '4px',
|
|
38
|
+
fontSize: '18px',
|
|
39
|
+
};
|
|
40
|
+
return (_jsxs("div", { style: headerStyle, className: className, "data-testid": "admin-agent-panel-header", children: [_jsxs("div", { style: titleStyle, children: [_jsx("span", { style: dotStyle, "aria-label": isActive ? 'Active' : 'Idle', role: "img" }), title] }), _jsx("button", { type: "button", onClick: close, style: closeStyle, "aria-label": "Close panel", "data-testid": "close-panel-button", children: "\u2715" })] }));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=AdminAgentPanelHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentPanelHeader.js","sourceRoot":"","sources":["../../src/components/AdminAgentPanelHeader.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG/D,MAAM,UAAU,qBAAqB,CAAC,EACpC,KAAK,GAAG,aAAa,EACrB,SAAS,GACkB;IAC3B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAE9C,MAAM,QAAQ,GAAG,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,CAAC;IAEzD,MAAM,WAAW,GAAwB;QACvC,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,mBAAmB;QACjC,UAAU,EAAE,MAAM;QAClB,GAAG,EAAE,MAAM;KACZ,CAAC;IAEF,MAAM,UAAU,GAAwB;QACtC,IAAI,EAAE,CAAC;QACP,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,GAAG,EAAE,KAAK;KACX,CAAC;IAEF,MAAM,QAAQ,GAAwB;QACpC,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;QACb,YAAY,EAAE,KAAK;QACnB,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC5C,UAAU,EAAE,CAAC;KACd,CAAC;IAEF,MAAM,UAAU,GAAwB;QACtC,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,KAAK;QACnB,QAAQ,EAAE,MAAM;KACjB,CAAC;IAEF,OAAO,CACL,eACE,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,SAAS,iBACR,0BAA0B,aAEtC,eAAK,KAAK,EAAE,UAAU,aACpB,eACE,KAAK,EAAE,QAAQ,gBACH,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EACxC,IAAI,EAAC,KAAK,GACV,EACD,KAAK,IACF,EACN,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,UAAU,gBACN,aAAa,iBACZ,oBAAoB,uBAGzB,IACL,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminAgentProvider.d.ts","sourceRoot":"","sources":["../../src/components/AdminAgentProvider.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAG7D,OAAO,KAAK,EACV,uBAAuB,EAMxB,MAAM,UAAU,CAAC;AAgBlB,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,OAAO,EACP,QAAQ,EACR,OAAO,GACR,EAAE,uBAAuB,GAAG,KAAK,CAAC,YAAY,CAqP9C"}
|