@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
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
- ## ⚠️ IMPORTANT NOTICE ⚠️
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
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ ## Overview
6
6
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
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
- ## Purpose
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
- This package exists to:
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
- ## What is OIDC Trusted Publishing?
16
+ ```bash
17
+ npm install @bernierllc/admin-agent-chat-ui react react-dom
18
+ ```
17
19
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
20
+ ## Quick Start
19
21
 
20
- ## Setup Instructions
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
- To properly configure OIDC trusted publishing for this package:
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
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
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
- ## DO NOT USE THIS PACKAGE
43
+ ## Headless Usage
30
44
 
31
- This package is a placeholder for OIDC configuration only. It:
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
- ## More Information
47
+ ```tsx
48
+ import { AdminAgentProvider, useAdminAgentChat } from '@bernierllc/admin-agent-chat-ui';
38
49
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
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
- **Maintained for OIDC setup purposes only**
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,4 @@
1
+ import React from 'react';
2
+ import type { AdminAgentInputProps } from '../types';
3
+ export declare function AdminAgentInput({ className, placeholder, disabled, }: AdminAgentInputProps): React.ReactElement;
4
+ //# sourceMappingURL=AdminAgentInput.d.ts.map
@@ -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":";AAAA;;;;;;EAME;AAEF,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG/D,MAAM,UAAU,eAAe,CAAC,EAC9B,SAAS,EACT,WAAW,GAAG,0BAA0B,EACxC,QAAQ,GACa;IACrB,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAC;IACpD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC,MAAM,MAAM,GACV,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,YAAY,CAAC;IAC7E,MAAM,UAAU,GAAG,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC;IAE/C,MAAM,YAAY,GAAG,CAAC,CAAkB,EAAQ,EAAE;QAChD,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,IAAI,UAAU;YAAE,OAAO;QAChC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,CAA2C,EAAQ,EAAE;QAC1E,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,IAAI,UAAU;gBAAE,OAAO;YAChC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACb,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAwB;QACrC,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,mBAAmB;QAC9B,UAAU,EAAE,MAAM;QAClB,GAAG,EAAE,KAAK;KACX,CAAC;IAEF,MAAM,aAAa,GAAwB;QACzC,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,mBAAmB;QAC3B,YAAY,EAAE,KAAK;QACnB,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;QAC3C,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,MAAM;KAChB,CAAC;IAEF,MAAM,WAAW,GAAwB;QACvC,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC9C,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,KAAK;QACnB,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAC9C,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;QACb,MAAM,EAAE,MAAM;KACf,CAAC;IAEF,OAAO,CACL,gBACE,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,YAAY,iBACV,wBAAwB,aAEpC,mBACE,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,SAAS,EAAE,aAAa,EACxB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,CAAC,gBACI,eAAe,iBACd,sBAAsB,GAClC,EACF,iBACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,gBAC1B,cAAc,iBACb,yBAAyB,qBAG9B,IACJ,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { AdminAgentPanelProps } from '../types';
3
+ export declare function AdminAgentPanel({ className, width, }: AdminAgentPanelProps): React.ReactElement | null;
4
+ //# sourceMappingURL=AdminAgentPanel.d.ts.map
@@ -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,4 @@
1
+ import React from 'react';
2
+ import type { AdminAgentPanelHeaderProps } from '../types';
3
+ export declare function AdminAgentPanelHeader({ title, className, }: AdminAgentPanelHeaderProps): React.ReactElement;
4
+ //# sourceMappingURL=AdminAgentPanelHeader.d.ts.map
@@ -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,4 @@
1
+ import React from 'react';
2
+ import type { AdminAgentProviderProps } from '../types';
3
+ export declare function AdminAgentProvider({ url, headers, children, fetchFn, }: AdminAgentProviderProps): React.ReactElement;
4
+ //# sourceMappingURL=AdminAgentProvider.d.ts.map
@@ -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"}