@kb-labs/studio-app 0.7.0 → 2.8.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 (175) hide show
  1. package/dist/index.html +1 -0
  2. package/dist/main.1d68e922.js +522 -0
  3. package/dist/main.1d68e922.js.map +1 -0
  4. package/dist/main.80b70197.css +2 -0
  5. package/dist/main.80b70197.css.map +1 -0
  6. package/dist/mf-manifest.json +241 -0
  7. package/dist/mf-stats.json +271 -0
  8. package/package.json +56 -39
  9. package/server.js +68 -0
  10. package/.env.example +0 -10
  11. package/UI-KIT-COMPONENTS.md +0 -783
  12. package/UI-KIT-PLAN.md +0 -326
  13. package/eslint-rules/no-direct-antd-import.js +0 -151
  14. package/eslint.config.ts +0 -27
  15. package/index.html +0 -17
  16. package/postcss.config.js +0 -7
  17. package/public/favicon.ico +0 -0
  18. package/rspack.config.mjs +0 -118
  19. package/src/App.tsx +0 -46
  20. package/src/components/devtools/devtools-log-feed.module.css +0 -165
  21. package/src/components/devtools/devtools-log-feed.tsx +0 -300
  22. package/src/components/devtools/devtools-panel.module.css +0 -121
  23. package/src/components/devtools/devtools-panel.tsx +0 -115
  24. package/src/components/empty-state.tsx +0 -28
  25. package/src/components/error-boundary.tsx +0 -210
  26. package/src/components/health-banner.module.css +0 -103
  27. package/src/components/health-banner.tsx +0 -134
  28. package/src/components/health-indicator.tsx +0 -12
  29. package/src/components/page-header.tsx +0 -49
  30. package/src/components/page-transition.tsx +0 -24
  31. package/src/components/role-switcher.tsx +0 -148
  32. package/src/components/run-badge.tsx +0 -13
  33. package/src/components/ui/icons.tsx +0 -509
  34. package/src/components/ui/index.ts +0 -25
  35. package/src/components/ui/kb-config-provider.tsx +0 -130
  36. package/src/components/ui/kb-header.module.css +0 -51
  37. package/src/components/ui/kb-header.tsx +0 -112
  38. package/src/components/ui/kb-notification-bell.module.css +0 -103
  39. package/src/components/ui/kb-notification-bell.tsx +0 -199
  40. package/src/components/ui/kb-page-layout.tsx +0 -66
  41. package/src/components/ui/kb-quick-search.module.css +0 -86
  42. package/src/components/ui/kb-quick-search.tsx +0 -196
  43. package/src/components/ui/kb-sidebar.module.css +0 -47
  44. package/src/components/ui/kb-sidebar.tsx +0 -196
  45. package/src/components/ui/kb-stat-card.module.css +0 -21
  46. package/src/components/ui/kb-stat-card.tsx +0 -22
  47. package/src/components/ui/kb-stat-grid.tsx +0 -22
  48. package/src/components/ui/kb-status-bar.module.css +0 -49
  49. package/src/components/ui/kb-status-bar.tsx +0 -145
  50. package/src/components/ui/kb-system-health-indicator.tsx +0 -229
  51. package/src/components/ui/kb-theme-toggle.tsx +0 -42
  52. package/src/components/ui/theme-adapter.ts +0 -812
  53. package/src/components/ui/theme-transition-overlay.tsx +0 -70
  54. package/src/components/ui/utils.ts +0 -6
  55. package/src/components/widget-error-boundary.tsx +0 -172
  56. package/src/config/env.ts +0 -5
  57. package/src/config/feature-flags.ts +0 -482
  58. package/src/config/studio.config.schema.ts +0 -88
  59. package/src/config/studio.config.ts +0 -84
  60. package/src/env.d.ts +0 -23
  61. package/src/hooks/use-command-palette.ts +0 -6
  62. package/src/hooks/use-devtools-store.ts +0 -25
  63. package/src/hooks/use-feature-flags.ts +0 -101
  64. package/src/index.css +0 -10
  65. package/src/layouts/dashboard-grid.tsx +0 -122
  66. package/src/layouts/index.ts +0 -12
  67. package/src/layouts/two-pane.tsx +0 -134
  68. package/src/main.tsx +0 -15
  69. package/src/modules/analytics/components/analytics-daily-stats-chart.tsx +0 -257
  70. package/src/modules/analytics/components/analytics-date-range-picker.tsx +0 -121
  71. package/src/modules/analytics/pages/analytics-cache-page.tsx +0 -285
  72. package/src/modules/analytics/pages/analytics-embeddings-page.tsx +0 -274
  73. package/src/modules/analytics/pages/analytics-events-page.tsx +0 -425
  74. package/src/modules/analytics/pages/analytics-llm-page.tsx +0 -434
  75. package/src/modules/analytics/pages/analytics-overview-page.tsx +0 -336
  76. package/src/modules/analytics/pages/analytics-page.tsx +0 -20
  77. package/src/modules/analytics/pages/analytics-storage-page.tsx +0 -344
  78. package/src/modules/analytics/pages/analytics-vectorstore-page.tsx +0 -279
  79. package/src/modules/analytics/routes/index.tsx +0 -133
  80. package/src/modules/analytics/utils/formatters.test.ts +0 -148
  81. package/src/modules/analytics/utils/formatters.ts +0 -100
  82. package/src/modules/auth/pages/login-page.module.css +0 -113
  83. package/src/modules/auth/pages/login-page.tsx +0 -80
  84. package/src/modules/auth/routes/index.tsx +0 -24
  85. package/src/modules/dashboard/components/ActivityTimelineWidget.tsx +0 -199
  86. package/src/modules/dashboard/components/AiInsightsWidget.tsx +0 -358
  87. package/src/modules/dashboard/components/AnimatedMetricCard.css +0 -88
  88. package/src/modules/dashboard/components/AnimatedMetricCard.tsx +0 -125
  89. package/src/modules/dashboard/components/HeroMetricCard.css +0 -114
  90. package/src/modules/dashboard/components/HeroMetricCard.tsx +0 -152
  91. package/src/modules/dashboard/components/HeroMetricsWidget.tsx +0 -146
  92. package/src/modules/dashboard/components/SystemResourcesWidget.tsx +0 -197
  93. package/src/modules/dashboard/components/dashboard-empty.tsx +0 -22
  94. package/src/modules/dashboard/components/dashboard-kpis-widget.tsx +0 -59
  95. package/src/modules/dashboard/components/dashboard-kpis.tsx +0 -13
  96. package/src/modules/dashboard/components/dashboard-latency-percentiles-widget.tsx +0 -85
  97. package/src/modules/dashboard/components/dashboard-metrics-widget.tsx +0 -78
  98. package/src/modules/dashboard/components/dashboard-plugins-widget.tsx +0 -67
  99. package/src/modules/dashboard/components/dashboard-requests-widget.tsx +0 -62
  100. package/src/modules/dashboard/layouts/dashboard-layout.tsx +0 -16
  101. package/src/modules/dashboard/pages/ai-insights-page.tsx +0 -563
  102. package/src/modules/dashboard/pages/dashboard-animations.css +0 -317
  103. package/src/modules/dashboard/pages/dashboard-page.tsx +0 -13
  104. package/src/modules/dashboard/routes/index.tsx +0 -70
  105. package/src/modules/observability/pages/devkit-page.tsx +0 -263
  106. package/src/modules/observability/pages/incident-detail-page.tsx +0 -571
  107. package/src/modules/observability/pages/incidents-page.tsx +0 -370
  108. package/src/modules/observability/pages/log-detail-page.tsx +0 -508
  109. package/src/modules/observability/pages/logs-page.tsx +0 -1129
  110. package/src/modules/observability/pages/prometheus-metrics-page.tsx +0 -486
  111. package/src/modules/observability/pages/state-broker-page.tsx +0 -229
  112. package/src/modules/observability/pages/system-events-page.tsx +0 -255
  113. package/src/modules/observability/routes/index.tsx +0 -133
  114. package/src/modules/plugins/components/marketplace-card.tsx +0 -153
  115. package/src/modules/plugins/components/plugin-ai-assistant-modal.tsx +0 -374
  116. package/src/modules/plugins/components/plugin-card.tsx +0 -136
  117. package/src/modules/plugins/components/plugin-detail/capabilities-summary.tsx +0 -101
  118. package/src/modules/plugins/components/plugin-detail/cli-commands-table.tsx +0 -101
  119. package/src/modules/plugins/components/plugin-detail/index.ts +0 -7
  120. package/src/modules/plugins/components/plugin-detail/jobs-table.tsx +0 -64
  121. package/src/modules/plugins/components/plugin-detail/permissions/env-permissions.tsx +0 -30
  122. package/src/modules/plugins/components/plugin-detail/permissions/filesystem-permissions.tsx +0 -68
  123. package/src/modules/plugins/components/plugin-detail/permissions/index.ts +0 -6
  124. package/src/modules/plugins/components/plugin-detail/permissions/network-permissions.tsx +0 -43
  125. package/src/modules/plugins/components/plugin-detail/permissions/platform-services.tsx +0 -242
  126. package/src/modules/plugins/components/plugin-detail/permissions/resource-quotas.tsx +0 -96
  127. package/src/modules/plugins/components/plugin-detail/permissions/shell-permissions.tsx +0 -55
  128. package/src/modules/plugins/components/plugin-detail/permissions-view.tsx +0 -47
  129. package/src/modules/plugins/components/plugin-detail/plugin-header.tsx +0 -169
  130. package/src/modules/plugins/components/plugin-detail/rest-routes-table.tsx +0 -159
  131. package/src/modules/plugins/components/plugin-detail/workflows-table.tsx +0 -40
  132. package/src/modules/plugins/components/plugin-grid.tsx +0 -20
  133. package/src/modules/plugins/components/plugin-table.tsx +0 -178
  134. package/src/modules/plugins/pages/marketplace-page.tsx +0 -200
  135. package/src/modules/plugins/pages/plugin-detail-page.tsx +0 -1145
  136. package/src/modules/plugins/routes/index.tsx +0 -48
  137. package/src/modules/plugins/utils/index.ts +0 -1
  138. package/src/modules/plugins/utils/schema-helpers.ts +0 -21
  139. package/src/modules/settings/components/api-routes-viewer.tsx +0 -415
  140. package/src/modules/settings/components/appearance-settings.tsx +0 -200
  141. package/src/modules/settings/components/configuration-settings.tsx +0 -321
  142. package/src/modules/settings/components/data-privacy-settings.tsx +0 -111
  143. package/src/modules/settings/components/experimental-settings.tsx +0 -243
  144. package/src/modules/settings/components/navigation-settings.tsx +0 -198
  145. package/src/modules/settings/components/notifications-settings.tsx +0 -40
  146. package/src/modules/settings/pages/settings-page.tsx +0 -298
  147. package/src/modules/settings/routes/index.tsx +0 -47
  148. package/src/pages/README-assistant.md +0 -91
  149. package/src/pages/login-page.tsx +0 -177
  150. package/src/pages/not-found-page.tsx +0 -85
  151. package/src/providers/auth-provider.tsx +0 -40
  152. package/src/providers/command-palette-provider.tsx +0 -193
  153. package/src/providers/data-sources-provider.tsx +0 -27
  154. package/src/providers/devtools-provider.tsx +0 -72
  155. package/src/providers/navigation-items-provider.tsx +0 -38
  156. package/src/providers/registry-v2-provider.tsx +0 -93
  157. package/src/providers/settings-provider.tsx +0 -158
  158. package/src/router.tsx +0 -302
  159. package/src/routes/helpers.tsx +0 -25
  160. package/src/routes/plugin-page-v2.tsx +0 -52
  161. package/src/routes/types.ts +0 -18
  162. package/src/styles/antd-overrides.css +0 -211
  163. package/src/styles/base.css +0 -190
  164. package/src/styles/settings.css +0 -75
  165. package/src/styles/variables.css +0 -94
  166. package/src/utils/analytics.ts +0 -183
  167. package/src/utils/apply-navigation-categories.ts +0 -83
  168. package/src/utils/commands.ts +0 -252
  169. package/src/utils/export.ts +0 -174
  170. package/src/utils/format-date.ts +0 -166
  171. package/src/utils/logger.ts +0 -110
  172. package/tailwind.config.ts +0 -13
  173. package/tsconfig.json +0 -13
  174. package/vitest-setup.ts +0 -1
  175. /package/{public → dist}/favicon.svg +0 -0
@@ -1,563 +0,0 @@
1
- import React, { useState, useRef, useEffect, useCallback } from 'react';
2
- import {
3
- UICard,
4
- UIInputTextArea,
5
- UIButton,
6
- UITypographyText,
7
- UITypographyParagraph,
8
- UISpace,
9
- UISpaceCompact,
10
- UITag,
11
- UISpin,
12
- UIStatistic,
13
- UICheckbox,
14
- UISelect,
15
- UITooltip,
16
- UIMessage,
17
- } from '@kb-labs/studio-ui-kit';
18
- import {
19
- SendOutlined,
20
- RobotOutlined,
21
- UserOutlined,
22
- BulbOutlined,
23
- CopyOutlined,
24
- CheckOutlined,
25
- ReloadOutlined,
26
- SettingOutlined,
27
- InfoCircleOutlined,
28
- } from '@ant-design/icons';
29
- import { useDataSources } from '../../../providers/data-sources-provider';
30
- import { usePrometheusMetrics, useIncidents } from '@kb-labs/studio-data-client';
31
- import { UIMarkdownViewer } from '@kb-labs/studio-ui-kit';
32
-
33
- interface Message {
34
- id: string;
35
- role: 'user' | 'assistant';
36
- content: string;
37
- timestamp: number;
38
- context?: string[];
39
- thinking?: boolean;
40
- }
41
-
42
- interface ContextConfig {
43
- includeMetrics: boolean;
44
- includeIncidents: boolean;
45
- includeHistory: boolean;
46
- timeRange: '1h' | '6h' | '24h' | '7d';
47
- plugins: string[];
48
- }
49
-
50
- const SUGGESTED_QUESTIONS = [
51
- { text: 'Why is latency higher than usual?', category: 'Performance' },
52
- { text: 'Which plugin should I optimize first?', category: 'Optimization' },
53
- { text: 'Are there any anomalies in the last 24 hours?', category: 'Anomalies' },
54
- { text: 'What caused the recent error spike?', category: 'Errors' },
55
- { text: 'How is the system health compared to yesterday?', category: 'Health' },
56
- { text: 'What are the most resource-intensive operations?', category: 'Resources' },
57
- ];
58
-
59
- const TIME_RANGE_OPTIONS = [
60
- { value: '1h', label: 'Last 1 hour' },
61
- { value: '6h', label: 'Last 6 hours' },
62
- { value: '24h', label: 'Last 24 hours' },
63
- { value: '7d', label: 'Last 7 days' },
64
- ];
65
-
66
- /**
67
- * AI Insights Page
68
- *
69
- * Full-featured chat interface for AI-powered system analysis.
70
- * Uses real metrics, incidents, and historical data as context for LLM.
71
- */
72
- export function AIInsightsPage() {
73
- const sources = useDataSources();
74
- const { data: metrics, isLoading: metricsLoading } = usePrometheusMetrics(sources.observability);
75
- const { data: incidents } = useIncidents(sources.observability, { limit: 10 });
76
-
77
- const [messages, setMessages] = useState<Message[]>([]);
78
- const [input, setInput] = useState('');
79
- const [isLoading, setIsLoading] = useState(false);
80
- const [copiedId, setCopiedId] = useState<string | null>(null);
81
- const [showConfig, setShowConfig] = useState(false);
82
- const [contextConfig, setContextConfig] = useState<ContextConfig>({
83
- includeMetrics: true,
84
- includeIncidents: true,
85
- includeHistory: true,
86
- timeRange: '24h',
87
- plugins: [],
88
- });
89
-
90
- const messagesEndRef = useRef<HTMLDivElement>(null);
91
- const inputRef = useRef<HTMLTextAreaElement>(null);
92
-
93
- // Auto-scroll to bottom when new messages arrive
94
- useEffect(() => {
95
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
96
- }, [messages]);
97
-
98
- // Build context summary for display
99
- const contextSummary = React.useMemo(() => {
100
- if (!metrics) {return null;}
101
-
102
- const errorRate = metrics.requests?.total
103
- ? (((metrics.requests.clientErrors ?? 0) + (metrics.requests.serverErrors ?? 0)) / metrics.requests.total * 100)
104
- : 0;
105
-
106
- return {
107
- requests: metrics.requests?.total ?? 0,
108
- errorRate: errorRate.toFixed(2),
109
- p99Latency: metrics.latency?.p99?.toFixed(0) ?? 'N/A',
110
- pluginCount: metrics.perPlugin?.length ?? 0,
111
- incidentCount: incidents?.length ?? 0,
112
- };
113
- }, [metrics, incidents]);
114
-
115
- // Get available plugins for context filtering
116
- const availablePlugins = React.useMemo(() => {
117
- return metrics?.perPlugin?.map(p => p.pluginId) ?? [];
118
- }, [metrics]);
119
-
120
- // Generate AI response via backend API
121
- const generateResponse = useCallback(async (question: string): Promise<string> => {
122
- const response = await sources.observability.chatWithInsights(question, contextConfig);
123
- return response.answer;
124
- }, [sources.observability, contextConfig]);
125
-
126
- // Send message
127
- const handleSend = async () => {
128
- if (!input.trim() || isLoading) {return;}
129
-
130
- const userMessage: Message = {
131
- id: `user-${Date.now()}`,
132
- role: 'user',
133
- content: input.trim(),
134
- timestamp: Date.now(),
135
- };
136
-
137
- const loadingMessage: Message = {
138
- id: `assistant-${Date.now()}`,
139
- role: 'assistant',
140
- content: '',
141
- timestamp: Date.now(),
142
- thinking: true,
143
- context: [
144
- contextConfig.includeMetrics ? 'metrics' : '',
145
- contextConfig.includeIncidents ? 'incidents' : '',
146
- contextConfig.includeHistory ? 'history' : '',
147
- ].filter(Boolean),
148
- };
149
-
150
- setMessages(prev => [...prev, userMessage, loadingMessage]);
151
- setInput('');
152
- setIsLoading(true);
153
-
154
- try {
155
- const response = await generateResponse(userMessage.content);
156
-
157
- setMessages(prev =>
158
- prev.map(m =>
159
- m.id === loadingMessage.id
160
- ? { ...m, content: response, thinking: false }
161
- : m
162
- )
163
- );
164
- } catch (_error) {
165
- setMessages(prev =>
166
- prev.map(m =>
167
- m.id === loadingMessage.id
168
- ? { ...m, content: 'Sorry, I encountered an error analyzing your request. Please try again.', thinking: false }
169
- : m
170
- )
171
- );
172
- } finally {
173
- setIsLoading(false);
174
- }
175
- };
176
-
177
- // Copy message to clipboard
178
- const handleCopy = async (content: string, id: string) => {
179
- await navigator.clipboard.writeText(content);
180
- setCopiedId(id);
181
- UIMessage.success('Copied to clipboard');
182
- setTimeout(() => setCopiedId(null), 2000);
183
- };
184
-
185
- // Handle suggested question click
186
- const handleSuggestion = (question: string) => {
187
- setInput(question);
188
- inputRef.current?.focus();
189
- };
190
-
191
- // Clear conversation
192
- const handleClear = () => {
193
- setMessages([]);
194
- };
195
-
196
- return (
197
- <div style={{ display: 'flex', gap: 24, height: 'calc(100vh - 280px)', minHeight: 500 }}>
198
- {/* Main Chat Panel */}
199
- <UICard
200
- style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
201
- styles={{ body: { flex: 1, display: 'flex', flexDirection: 'column', padding: 0, overflow: 'hidden' } }}
202
- title={
203
- <UISpace>
204
- <RobotOutlined />
205
- <span>AI Assistant</span>
206
- {metricsLoading && <UISpin size="small" />}
207
- </UISpace>
208
- }
209
- extra={
210
- <UISpace>
211
- <UITooltip title="Clear conversation">
212
- <UIButton icon={<ReloadOutlined />} onClick={handleClear} disabled={messages.length === 0} />
213
- </UITooltip>
214
- <UITooltip title="Configure context">
215
- <UIButton
216
- icon={<SettingOutlined />}
217
- onClick={() => setShowConfig(!showConfig)}
218
- variant={showConfig ? 'primary' : 'default'}
219
- />
220
- </UITooltip>
221
- </UISpace>
222
- }
223
- >
224
- {/* Messages Area */}
225
- <div style={{ flex: 1, overflow: 'auto', padding: 16 }}>
226
- {messages.length === 0 ? (
227
- <div style={{ textAlign: 'center', padding: '48px 24px' }}>
228
- <RobotOutlined style={{ fontSize: 48, color: '#bfbfbf', marginBottom: 16 }} />
229
- <UITypographyText type="secondary" style={{ display: 'block', marginBottom: 24 }}>
230
- Ask me anything about your system's performance, errors, or health.
231
- I'll analyze real-time metrics and provide actionable insights.
232
- </UITypographyText>
233
-
234
- <div style={{ marginTop: 24 }}>
235
- <UITypographyText strong style={{ display: 'block', marginBottom: 12 }}>
236
- <BulbOutlined /> Suggested questions:
237
- </UITypographyText>
238
- <UISpace wrap style={{ justifyContent: 'center' }}>
239
- {SUGGESTED_QUESTIONS.map((q, i) => (
240
- <UITag
241
- key={i}
242
- color="blue"
243
- style={{ cursor: 'pointer', padding: '4px 12px' }}
244
- onClick={() => handleSuggestion(q.text)}
245
- >
246
- {q.text}
247
- </UITag>
248
- ))}
249
- </UISpace>
250
- </div>
251
- </div>
252
- ) : (
253
- <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
254
- {messages.map(msg => (
255
- <div
256
- key={msg.id}
257
- style={{
258
- display: 'flex',
259
- justifyContent: msg.role === 'user' ? 'flex-end' : 'flex-start',
260
- }}
261
- >
262
- <div
263
- style={{
264
- maxWidth: '80%',
265
- padding: '12px 16px',
266
- borderRadius: 12,
267
- background: msg.role === 'user' ? '#1890ff' : '#f5f5f5',
268
- color: msg.role === 'user' ? '#fff' : '#000',
269
- }}
270
- >
271
- <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
272
- {msg.role === 'assistant' && (
273
- <RobotOutlined style={{ marginTop: 4, color: '#1890ff' }} />
274
- )}
275
- <div style={{ flex: 1 }}>
276
- {msg.thinking ? (
277
- <UISpace>
278
- <UISpin size="small" />
279
- <UITypographyText type="secondary">Analyzing...</UITypographyText>
280
- </UISpace>
281
- ) : msg.role === 'assistant' ? (
282
- <UIMarkdownViewer content={msg.content} className="ai-insights-markdown" />
283
- ) : (
284
- <UITypographyParagraph
285
- style={{
286
- margin: 0,
287
- whiteSpace: 'pre-wrap',
288
- color: '#fff',
289
- }}
290
- >
291
- {msg.content}
292
- </UITypographyParagraph>
293
- )}
294
- {msg.context && msg.context.length > 0 && (
295
- <div style={{ marginTop: 8 }}>
296
- {msg.context.map(c => (
297
- <UITag key={c} color="default" style={{ fontSize: 10 }}>
298
- {c}
299
- </UITag>
300
- ))}
301
- </div>
302
- )}
303
- </div>
304
- {msg.role === 'user' && <UserOutlined style={{ marginTop: 4 }} />}
305
- </div>
306
- {msg.role === 'assistant' && !msg.thinking && (
307
- <div style={{ marginTop: 8, textAlign: 'right' }}>
308
- <UIButton
309
- variant="text"
310
- size="small"
311
- icon={copiedId === msg.id ? <CheckOutlined /> : <CopyOutlined />}
312
- onClick={() => handleCopy(msg.content, msg.id)}
313
- style={{ color: '#8c8c8c' }}
314
- >
315
- {copiedId === msg.id ? 'Copied' : 'Copy'}
316
- </UIButton>
317
- </div>
318
- )}
319
- </div>
320
- </div>
321
- ))}
322
- <div ref={messagesEndRef} />
323
- </div>
324
- )}
325
- </div>
326
-
327
- {/* Input Area */}
328
- <div style={{ padding: 16, borderTop: '1px solid #f0f0f0' }}>
329
- <UISpaceCompact style={{ width: '100%' }}>
330
- <UIInputTextArea
331
- ref={inputRef}
332
- value={input}
333
- onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setInput(e.target.value)}
334
- placeholder="Ask about your system..."
335
- autoSize={{ minRows: 1, maxRows: 4 }}
336
- onPressEnter={(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
337
- if (!e.shiftKey) {
338
- e.preventDefault();
339
- handleSend();
340
- }
341
- }}
342
- style={{ flex: 1 }}
343
- />
344
- <UIButton
345
- variant="primary"
346
- icon={<SendOutlined />}
347
- onClick={handleSend}
348
- loading={isLoading}
349
- disabled={!input.trim()}
350
- >
351
- Send
352
- </UIButton>
353
- </UISpaceCompact>
354
- <UITypographyText type="secondary" style={{ fontSize: 11, marginTop: 4, display: 'block' }}>
355
- Press Enter to send, Shift+Enter for new line
356
- </UITypographyText>
357
- </div>
358
- </UICard>
359
-
360
- {/* Context Panel */}
361
- <UICard
362
- title={
363
- <UISpace>
364
- <InfoCircleOutlined />
365
- <span>Context</span>
366
- </UISpace>
367
- }
368
- style={{ width: 320, flexShrink: 0 }}
369
- styles={{ body: { padding: 16 } }}
370
- >
371
- {/* System Summary */}
372
- {contextSummary && (
373
- <div style={{ marginBottom: 24 }}>
374
- <UITypographyText strong style={{ display: 'block', marginBottom: 12 }}>System Summary</UITypographyText>
375
- <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
376
- <UIStatistic title="Requests" value={contextSummary.requests} valueStyle={{ fontSize: 18 }} />
377
- <UIStatistic
378
- title="Error Rate"
379
- value={contextSummary.errorRate}
380
- suffix="%"
381
- valueStyle={{
382
- fontSize: 18,
383
- color: parseFloat(contextSummary.errorRate) > 5 ? '#ff4d4f' : parseFloat(contextSummary.errorRate) > 1 ? '#faad14' : '#52c41a',
384
- }}
385
- />
386
- <UIStatistic title="P99 Latency" value={contextSummary.p99Latency} suffix="ms" valueStyle={{ fontSize: 18 }} />
387
- <UIStatistic title="Incidents" value={contextSummary.incidentCount} valueStyle={{ fontSize: 18 }} />
388
- </div>
389
- </div>
390
- )}
391
-
392
- {/* Recent Incidents */}
393
- {incidents && incidents.length > 0 && (
394
- <div style={{ marginBottom: 24 }}>
395
- <UITypographyText strong style={{ display: 'block', marginBottom: 12 }}>Recent Incidents</UITypographyText>
396
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
397
- {incidents.slice(0, 5).map(incident => (
398
- <div
399
- key={incident.id}
400
- style={{
401
- padding: 8,
402
- background: '#fafafa',
403
- borderRadius: 4,
404
- borderLeft: `3px solid ${
405
- incident.severity === 'critical' ? '#ff4d4f' :
406
- incident.severity === 'warning' ? '#faad14' : '#1890ff'
407
- }`,
408
- }}
409
- >
410
- <UITypographyText style={{ fontSize: 12 }}>{incident.title}</UITypographyText>
411
- </div>
412
- ))}
413
- </div>
414
- </div>
415
- )}
416
-
417
- {/* Context Configuration */}
418
- {showConfig && (
419
- <div style={{ borderTop: '1px solid #f0f0f0', paddingTop: 16 }}>
420
- <UITypographyText strong style={{ display: 'block', marginBottom: 12 }}>Context Settings</UITypographyText>
421
-
422
- <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
423
- <UICheckbox
424
- checked={contextConfig.includeMetrics}
425
- onChange={(checked) => setContextConfig(prev => ({ ...prev, includeMetrics: checked }))}
426
- >
427
- Include current metrics
428
- </UICheckbox>
429
- <UICheckbox
430
- checked={contextConfig.includeIncidents}
431
- onChange={(checked) => setContextConfig(prev => ({ ...prev, includeIncidents: checked }))}
432
- >
433
- Include incidents
434
- </UICheckbox>
435
- <UICheckbox
436
- checked={contextConfig.includeHistory}
437
- onChange={(checked) => setContextConfig(prev => ({ ...prev, includeHistory: checked }))}
438
- >
439
- Include historical trends
440
- </UICheckbox>
441
-
442
- <div>
443
- <UITypographyText type="secondary" style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>
444
- Time Range
445
- </UITypographyText>
446
- <UISelect
447
- value={contextConfig.timeRange}
448
- onChange={value => setContextConfig(prev => ({ ...prev, timeRange: value as ContextConfig['timeRange'] }))}
449
- options={TIME_RANGE_OPTIONS}
450
- style={{ width: '100%' }}
451
- size="small"
452
- />
453
- </div>
454
-
455
- {availablePlugins.length > 0 && (
456
- <div>
457
- <UITypographyText type="secondary" style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>
458
- Focus on plugins
459
- </UITypographyText>
460
- <UISelect
461
- mode="multiple"
462
- value={contextConfig.plugins}
463
- onChange={value => setContextConfig(prev => ({ ...prev, plugins: value as string[] }))}
464
- options={availablePlugins.map(p => ({ value: p, label: p }))}
465
- style={{ width: '100%' }}
466
- size="small"
467
- placeholder="All plugins"
468
- maxTagCount={2}
469
- />
470
- </div>
471
- )}
472
- </div>
473
- </div>
474
- )}
475
-
476
- {/* Suggested Questions */}
477
- <div style={{ marginTop: 24 }}>
478
- <UITypographyText strong style={{ display: 'block', marginBottom: 12 }}>
479
- <BulbOutlined /> Quick Questions
480
- </UITypographyText>
481
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
482
- {SUGGESTED_QUESTIONS.slice(0, 4).map((q, i) => (
483
- <UIButton
484
- key={i}
485
- variant="text"
486
- size="small"
487
- style={{ textAlign: 'left', height: 'auto', padding: '4px 8px' }}
488
- onClick={() => handleSuggestion(q.text)}
489
- >
490
- <UITypographyText ellipsis style={{ fontSize: 12 }}>{q.text}</UITypographyText>
491
- </UIButton>
492
- ))}
493
- </div>
494
- </div>
495
- </UICard>
496
-
497
- {/* Custom styles for markdown in chat context */}
498
- <style>{`
499
- .ai-insights-markdown {
500
- padding: 0;
501
- background: transparent;
502
- border-radius: 0;
503
- }
504
- .ai-insights-markdown p {
505
- margin: 0 0 8px 0;
506
- }
507
- .ai-insights-markdown p:last-child {
508
- margin-bottom: 0;
509
- }
510
- .ai-insights-markdown h1,
511
- .ai-insights-markdown h2,
512
- .ai-insights-markdown h3 {
513
- margin-top: 12px;
514
- margin-bottom: 8px;
515
- font-size: 1em;
516
- font-weight: 600;
517
- border: none;
518
- padding: 0;
519
- }
520
- .ai-insights-markdown h1 {
521
- font-size: 1.1em;
522
- }
523
- .ai-insights-markdown ul,
524
- .ai-insights-markdown ol {
525
- margin: 8px 0;
526
- padding-left: 20px;
527
- }
528
- .ai-insights-markdown li {
529
- margin: 2px 0;
530
- }
531
- .ai-insights-markdown code {
532
- background: rgba(0, 0, 0, 0.06);
533
- padding: 1px 4px;
534
- border-radius: 3px;
535
- font-size: 0.85em;
536
- }
537
- .ai-insights-markdown pre {
538
- background: rgba(0, 0, 0, 0.04);
539
- padding: 8px 12px;
540
- border-radius: 6px;
541
- margin: 8px 0;
542
- }
543
- .ai-insights-markdown pre code {
544
- background: none;
545
- padding: 0;
546
- }
547
- .ai-insights-markdown table {
548
- margin: 8px 0;
549
- font-size: 0.9em;
550
- }
551
- .ai-insights-markdown th,
552
- .ai-insights-markdown td {
553
- padding: 4px 8px;
554
- }
555
- .ai-insights-markdown blockquote {
556
- margin: 8px 0;
557
- padding-left: 12px;
558
- border-left-width: 3px;
559
- }
560
- `}</style>
561
- </div>
562
- );
563
- }