@kb-labs/studio-app 0.6.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,121 +0,0 @@
1
- import { useState } from 'react';
2
- import { UIRangePicker, UISelect, UISpace } from '@kb-labs/studio-ui-kit';
3
- import { CalendarOutlined } from '@ant-design/icons';
4
- import dayjs, { type Dayjs } from 'dayjs';
5
-
6
- /**
7
- * Predefined date range presets
8
- */
9
- const DATE_PRESETS = [
10
- { label: 'Last 7 days', value: 7 as number | 'custom' },
11
- { label: 'Last 30 days', value: 30 as number | 'custom' },
12
- { label: 'Last 90 days', value: 90 as number | 'custom' },
13
- { label: 'Custom range', value: 'custom' as number | 'custom' },
14
- ];
15
-
16
- export type DateRangeValue = [Dayjs, Dayjs];
17
-
18
- export interface AnalyticsDateRangePickerProps {
19
- /**
20
- * Current date range value
21
- */
22
- value: DateRangeValue;
23
-
24
- /**
25
- * Callback when date range changes
26
- */
27
- onChange: (range: DateRangeValue) => void;
28
-
29
- /**
30
- * Show preset selector (default: true)
31
- */
32
- showPresets?: boolean;
33
-
34
- /**
35
- * Date format (default: DD/MM/YYYY)
36
- */
37
- format?: string;
38
- }
39
-
40
- /**
41
- * Analytics Date Range Picker Component
42
- *
43
- * Provides a consistent date range selection UI for all analytics pages.
44
- * Features:
45
- * - Quick presets (7/30/90 days)
46
- * - Custom date range picker
47
- * - Unified styling
48
- */
49
- export function AnalyticsDateRangePicker({
50
- value,
51
- onChange,
52
- showPresets = true,
53
- format = 'DD/MM/YYYY',
54
- }: AnalyticsDateRangePickerProps) {
55
- // Determine current preset based on date range
56
- const getCurrentPreset = (): number | 'custom' => {
57
- const daysDiff = dayjs().diff(value[0], 'days');
58
- const isToday = value[1].isSame(dayjs(), 'day');
59
-
60
- if (isToday) {
61
- if (daysDiff === 7) {return 7;}
62
- if (daysDiff === 30) {return 30;}
63
- if (daysDiff === 90) {return 90;}
64
- }
65
-
66
- return 'custom';
67
- };
68
-
69
- const [selectedPreset, setSelectedPreset] = useState<number | 'custom'>(getCurrentPreset());
70
-
71
- const handlePresetChange = (preset: number | 'custom') => {
72
- setSelectedPreset(preset);
73
-
74
- if (preset !== 'custom') {
75
- const newRange: DateRangeValue = [
76
- dayjs().subtract(preset, 'days'),
77
- dayjs(),
78
- ];
79
- onChange(newRange);
80
- }
81
- };
82
-
83
- const handleDateChange = (dates: [Dayjs | null, Dayjs | null] | null) => {
84
- if (dates && dates[0] && dates[1]) {
85
- setSelectedPreset('custom');
86
- onChange([dates[0], dates[1]]);
87
- }
88
- };
89
-
90
- if (!showPresets) {
91
- return (
92
- <UIRangePicker
93
- value={value}
94
- onChange={handleDateChange}
95
- format={format}
96
- allowClear={false}
97
- suffixIcon={<CalendarOutlined />}
98
- />
99
- );
100
- }
101
-
102
- return (
103
- <UISpace size="small">
104
- <UISelect
105
- value={selectedPreset}
106
- onChange={(v) => handlePresetChange(v as number | 'custom')}
107
- options={DATE_PRESETS}
108
- style={{ width: 150 }}
109
- />
110
- {selectedPreset === 'custom' && (
111
- <UIRangePicker
112
- value={value}
113
- onChange={handleDateChange}
114
- format={format}
115
- allowClear={false}
116
- suffixIcon={<CalendarOutlined />}
117
- />
118
- )}
119
- </UISpace>
120
- );
121
- }
@@ -1,285 +0,0 @@
1
- import { useState } from 'react';
2
- import { UIRow, UICol, UIStatistic, UIAlert, UIProgress, useUITheme } from '@kb-labs/studio-ui-kit';
3
- import {
4
- ClockCircleOutlined,
5
- CheckCircleOutlined,
6
- CloseCircleOutlined,
7
- SaveOutlined,
8
- EyeOutlined,
9
- } from '@ant-design/icons';
10
- import { UIText, UIStatisticsChart, UICard, UIPage, UIPageHeader } from '@kb-labs/studio-ui-kit';
11
- import { useAdaptersCacheUsage, useAdaptersCacheDailyStats } from '@kb-labs/studio-data-client';
12
- import { useDataSources } from '../../../providers/data-sources-provider';
13
- import { AnalyticsDateRangePicker, type DateRangeValue } from '../components/analytics-date-range-picker';
14
- import dayjs from 'dayjs';
15
-
16
-
17
- /**
18
- * Analytics Cache Usage Page
19
- *
20
- * Displays cache usage statistics:
21
- * - Hit/miss rates
22
- * - Performance metrics
23
- * - Cache efficiency
24
- */
25
- export function AnalyticsCachePage() {
26
- const { token } = useUITheme();
27
- const sources = useDataSources();
28
-
29
- // Date range state (default: last 30 days)
30
- const [dateRange, setDateRange] = useState<DateRangeValue>([
31
- dayjs().subtract(30, 'days'),
32
- dayjs(),
33
- ]);
34
-
35
- const {
36
- data: stats,
37
- isLoading,
38
- error,
39
- isError,
40
- } = useAdaptersCacheUsage(sources.adapters, {
41
- from: dateRange[0].toISOString(),
42
- to: dateRange[1].toISOString(),
43
- });
44
-
45
- const {
46
- data: dailyStats,
47
- isLoading: dailyStatsLoading,
48
- } = useAdaptersCacheDailyStats(sources.adapters, {
49
- from: dateRange[0].toISOString(),
50
- to: dateRange[1].toISOString(),
51
- });
52
-
53
- // Check if analytics is not implemented
54
- const analyticsNotImplemented =
55
- isError &&
56
- error instanceof Error &&
57
- (error.message.includes('not support') || error.message.includes('not implement'));
58
-
59
- if (analyticsNotImplemented) {
60
- return (
61
- <UIPage>
62
- <UIPageHeader
63
- title="Cache Usage"
64
- description="Track cache hit rates and performance optimization"
65
- />
66
- <UIAlert
67
- message="Analytics Not Available"
68
- description="Analytics adapter does not support reading events. Configure an analytics adapter in kb.config.json that implements getEvents()."
69
- variant="info"
70
- showIcon
71
- style={{ marginTop: 16 }}
72
- />
73
- </UIPage>
74
- );
75
- }
76
-
77
- if (isError) {
78
- return (
79
- <UIPage>
80
- <UIPageHeader title="Cache Usage" description="Cache usage analytics" />
81
- <UIAlert
82
- message="Failed to Load Cache Usage"
83
- description={error?.message || 'Unknown error occurred'}
84
- variant="error"
85
- showIcon
86
- style={{ marginTop: 16 }}
87
- />
88
- </UIPage>
89
- );
90
- }
91
-
92
- const hitRateStatus = stats && stats.hitRate >= 80
93
- ? 'success'
94
- : stats && stats.hitRate >= 60
95
- ? 'normal'
96
- : 'exception';
97
-
98
- const missRate = stats ? (100 - stats.hitRate).toFixed(1) : 0;
99
-
100
- return (
101
- <UIPage width="full">
102
- <UIPageHeader
103
- title="Cache Usage Analytics"
104
- description="Track cache efficiency, hit rates, and performance optimization opportunities"
105
- actions={
106
- <AnalyticsDateRangePicker
107
- value={dateRange}
108
- onChange={setDateRange}
109
- />
110
- }
111
- />
112
-
113
- <div style={{ marginTop: 24 }}>
114
- {/* Hit Rate Overview */}
115
- <UIRow gutter={[16, 16]}>
116
- <UICol xs={24}>
117
- <UICard>
118
- <UIRow gutter={[16, 16]} align="middle">
119
- <UICol xs={24} lg={8}>
120
- <div style={{ textAlign: 'center' }}>
121
- <UIProgress
122
- type="circle"
123
- percent={Number((stats?.hitRate ?? 0).toFixed(1))}
124
- status={hitRateStatus}
125
- size={180}
126
- format={(percent) => (
127
- <div>
128
- <div style={{ fontSize: '32px', fontWeight: 'bold' }}>{percent}%</div>
129
- <div style={{ fontSize: '14px', color: token.colorTextTertiary }}>Hit Rate</div>
130
- </div>
131
- )}
132
- />
133
- </div>
134
- </UICol>
135
- <UICol xs={24} lg={16}>
136
- <UIRow gutter={[16, 16]}>
137
- <UICol xs={12}>
138
- <UIStatistic
139
- title="Total Gets"
140
- value={stats?.totalGets ?? 0}
141
- prefix={<EyeOutlined />}
142
- loading={isLoading}
143
- valueStyle={{ color: 'var(--info)' }}
144
- />
145
- </UICol>
146
- <UICol xs={12}>
147
- <UIStatistic
148
- title="Cache Hits"
149
- value={stats?.hits ?? 0}
150
- prefix={<CheckCircleOutlined />}
151
- loading={isLoading}
152
- valueStyle={{ color: 'var(--success)' }}
153
- />
154
- </UICol>
155
- <UICol xs={12}>
156
- <UIStatistic
157
- title="Cache Misses"
158
- value={stats?.misses ?? 0}
159
- prefix={<CloseCircleOutlined />}
160
- loading={isLoading}
161
- valueStyle={{ color: 'var(--error)' }}
162
- />
163
- </UICol>
164
- <UICol xs={12}>
165
- <UIStatistic
166
- title="Miss Rate"
167
- value={Number(missRate)}
168
- suffix="%"
169
- precision={1}
170
- loading={isLoading}
171
- valueStyle={{ color: 'var(--warning)' }}
172
- />
173
- </UICol>
174
- </UIRow>
175
- </UICol>
176
- </UIRow>
177
- </UICard>
178
- </UICol>
179
- </UIRow>
180
-
181
- {/* Performance Metrics */}
182
- <UIRow gutter={[16, 16]} style={{ marginTop: 16 }}>
183
- <UICol xs={24} lg={12}>
184
- <UICard title="Read Performance">
185
- <UIStatistic
186
- title="Avg Get Duration"
187
- value={stats?.avgGetDuration ?? 0}
188
- prefix={<ClockCircleOutlined />}
189
- suffix="ms"
190
- precision={2}
191
- loading={isLoading}
192
- />
193
- <div style={{ marginTop: 16 }}>
194
- <UIText color="secondary">
195
- Average time to retrieve cached values
196
- {stats && stats.avgGetDuration < 5 && (
197
- <CheckCircleOutlined style={{ color: 'var(--success)', marginLeft: 8 }} />
198
- )}
199
- </UIText>
200
- </div>
201
- </UICard>
202
- </UICol>
203
- <UICol xs={24} lg={12}>
204
- <UICard title="Write Performance">
205
- <UIStatistic
206
- title="Cache Sets"
207
- value={stats?.sets ?? 0}
208
- prefix={<SaveOutlined />}
209
- loading={isLoading}
210
- valueStyle={{ color: 'var(--link)' }}
211
- />
212
- <div style={{ marginTop: 16 }}>
213
- <UIStatistic
214
- title="Avg Set Duration"
215
- value={stats?.avgSetDuration ?? 0}
216
- prefix={<ClockCircleOutlined />}
217
- suffix="ms"
218
- precision={2}
219
- loading={isLoading}
220
- />
221
- </div>
222
- </UICard>
223
- </UICol>
224
- </UIRow>
225
-
226
- {/* Efficiency Insights */}
227
- {stats && stats.totalGets > 0 && (
228
- <UICard title="Cache Efficiency Insights" style={{ marginTop: 16 }}>
229
- <UIRow gutter={[16, 16]}>
230
- <UICol xs={24} sm={8}>
231
- <UIStatistic
232
- title="Gets per Set"
233
- value={(stats.totalGets / Math.max(stats.sets, 1)).toFixed(2)}
234
- loading={isLoading}
235
- valueStyle={{ color: 'var(--info)' }}
236
- />
237
- <UIText color="secondary" style={{ fontSize: 12 }}>
238
- Higher is better (more cache reuse)
239
- </UIText>
240
- </UICol>
241
- <UICol xs={24} sm={8}>
242
- <UIStatistic
243
- title="Performance Gain"
244
- value={stats.avgSetDuration > 0 ? (stats.avgSetDuration / Math.max(stats.avgGetDuration, 0.1)).toFixed(1) : 0}
245
- suffix="x"
246
- loading={isLoading}
247
- valueStyle={{ color: 'var(--success)' }}
248
- />
249
- <UIText color="secondary" style={{ fontSize: 12 }}>
250
- Set is ~{stats.avgSetDuration > 0 ? (stats.avgSetDuration / Math.max(stats.avgGetDuration, 0.1)).toFixed(1) : 0}x slower than get
251
- </UIText>
252
- </UICol>
253
- <UICol xs={24} sm={8}>
254
- <UIStatistic
255
- title="Cache Effectiveness"
256
- value={stats.hits > 0 ? ((stats.hits / stats.totalGets) * 100).toFixed(1) : 0}
257
- suffix="%"
258
- loading={isLoading}
259
- valueStyle={{
260
- color: stats.hitRate >= 80 ? 'var(--success)' : stats.hitRate >= 60 ? 'var(--info)' : 'var(--warning)'
261
- }}
262
- />
263
- <UIText color="secondary" style={{ fontSize: 12 }}>
264
- {stats.hitRate >= 80 ? 'Excellent' : stats.hitRate >= 60 ? 'Good' : 'Needs improvement'}
265
- </UIText>
266
- </UICol>
267
- </UIRow>
268
- </UICard>
269
- )}
270
-
271
- {/* Daily Usage Chart */}
272
- <UIStatisticsChart
273
- data={dailyStats}
274
- loading={dailyStatsLoading}
275
- title="Daily Cache Performance"
276
- metrics={[
277
- { key: 'totalHits', label: 'Hits' },
278
- { key: 'totalMisses', label: 'Misses' },
279
- { key: 'hitRate', label: 'Hit Rate (%)', format: (v) => `${v.toFixed(1)}%` },
280
- ]}
281
- />
282
- </div>
283
- </UIPage>
284
- );
285
- }
@@ -1,274 +0,0 @@
1
- import { useState } from 'react';
2
- import { UIRow, UICol, UIStatistic, UIAlert, UIProgress } from '@kb-labs/studio-ui-kit';
3
- import {
4
- ApiOutlined,
5
- DollarOutlined,
6
- FileTextOutlined,
7
- ClockCircleOutlined,
8
- WarningOutlined,
9
- TeamOutlined,
10
- GroupOutlined,
11
- } from '@ant-design/icons';
12
- import { UIText, UIStatisticsChart, UICard, UIPage, UIPageHeader } from '@kb-labs/studio-ui-kit';
13
- import { useAdaptersEmbeddingsUsage, useAdaptersEmbeddingsDailyStats } from '@kb-labs/studio-data-client';
14
- import { useDataSources } from '../../../providers/data-sources-provider';
15
- import { AnalyticsDateRangePicker, type DateRangeValue } from '../components/analytics-date-range-picker';
16
- import { formatCost } from '../utils/formatters';
17
- import dayjs from 'dayjs';
18
-
19
-
20
- /**
21
- * Analytics Embeddings Usage Page
22
- *
23
- * Displays embeddings usage statistics:
24
- * - Total requests and text volume
25
- * - Cost tracking
26
- * - Batch efficiency metrics
27
- * - Performance metrics
28
- */
29
- export function AnalyticsEmbeddingsPage() {
30
- const sources = useDataSources();
31
-
32
- // Date range state (default: last 30 days)
33
- const [dateRange, setDateRange] = useState<DateRangeValue>([
34
- dayjs().subtract(30, 'days'),
35
- dayjs(),
36
- ]);
37
-
38
- const {
39
- data: stats,
40
- isLoading,
41
- error,
42
- isError,
43
- } = useAdaptersEmbeddingsUsage(sources.adapters, {
44
- from: dateRange[0].toISOString(),
45
- to: dateRange[1].toISOString(),
46
- });
47
-
48
- const {
49
- data: dailyStats,
50
- isLoading: dailyStatsLoading,
51
- } = useAdaptersEmbeddingsDailyStats(sources.adapters, {
52
- from: dateRange[0].toISOString(),
53
- to: dateRange[1].toISOString(),
54
- });
55
-
56
- // Check if analytics is not implemented
57
- const analyticsNotImplemented =
58
- isError &&
59
- error instanceof Error &&
60
- (error.message.includes('not support') || error.message.includes('not implement'));
61
-
62
- if (analyticsNotImplemented) {
63
- return (
64
- <UIPage>
65
- <UIPageHeader
66
- title="Embeddings Usage"
67
- description="Track embeddings API usage, costs, and batch efficiency"
68
- />
69
- <UIAlert
70
- message="Analytics Not Available"
71
- description="Analytics adapter does not support reading events. Configure an analytics adapter in kb.config.json that implements getEvents()."
72
- variant="info"
73
- showIcon
74
- style={{ marginTop: 16 }}
75
- />
76
- </UIPage>
77
- );
78
- }
79
-
80
- if (isError) {
81
- return (
82
- <UIPage>
83
- <UIPageHeader title="Embeddings Usage" description="Embeddings usage analytics" />
84
- <UIAlert
85
- message="Failed to Load Embeddings Usage"
86
- description={error?.message || 'Unknown error occurred'}
87
- variant="error"
88
- showIcon
89
- style={{ marginTop: 16 }}
90
- />
91
- </UIPage>
92
- );
93
- }
94
-
95
- const batchPercentage = stats ? ((stats.batchRequests / stats.totalRequests) * 100).toFixed(1) : 0;
96
-
97
- return (
98
- <UIPage width="full">
99
- <UIPageHeader
100
- title="Embeddings Usage Analytics"
101
- description="Track embeddings API usage, costs, and batch processing efficiency"
102
- actions={
103
- <AnalyticsDateRangePicker
104
- value={dateRange}
105
- onChange={setDateRange}
106
- />
107
- }
108
- />
109
-
110
- <div style={{ marginTop: 24 }}>
111
- {/* Overview Stats */}
112
- <UIRow gutter={[16, 16]}>
113
- <UICol xs={24} sm={12} lg={6}>
114
- <UICard>
115
- <UIStatistic
116
- title="Total Requests"
117
- value={stats?.totalRequests ?? 0}
118
- prefix={<ApiOutlined />}
119
- loading={isLoading}
120
- valueStyle={{ color: 'var(--info)' }}
121
- />
122
- </UICard>
123
- </UICol>
124
- <UICol xs={24} sm={12} lg={6}>
125
- <UICard>
126
- <UIStatistic
127
- title="Text Processed"
128
- value={stats?.totalTextLength ?? 0}
129
- prefix={<FileTextOutlined />}
130
- suffix="chars"
131
- loading={isLoading}
132
- valueStyle={{ color: 'var(--success)' }}
133
- />
134
- </UICard>
135
- </UICol>
136
- <UICol xs={24} sm={12} lg={6}>
137
- <UICard>
138
- <UIStatistic
139
- title="Total Cost"
140
- value={stats?.totalCost ?? 0}
141
- prefix={<DollarOutlined />}
142
- precision={4}
143
- loading={isLoading}
144
- valueStyle={{ color: 'var(--error)' }}
145
- />
146
- </UICard>
147
- </UICol>
148
- <UICol xs={24} sm={12} lg={6}>
149
- <UICard>
150
- <UIStatistic
151
- title="Errors"
152
- value={stats?.errors ?? 0}
153
- prefix={<WarningOutlined />}
154
- loading={isLoading}
155
- valueStyle={{ color: stats && stats.errors > 0 ? 'var(--warning)' : 'var(--success)' }}
156
- />
157
- </UICard>
158
- </UICol>
159
- </UIRow>
160
-
161
- {/* Batch Efficiency */}
162
- <UIRow gutter={[16, 16]} style={{ marginTop: 16 }}>
163
- <UICol xs={24} lg={12}>
164
- <UICard title="Batch Processing">
165
- <UIRow gutter={[16, 16]}>
166
- <UICol span={12}>
167
- <UIStatistic
168
- title="Single Requests"
169
- value={stats?.singleRequests ?? 0}
170
- prefix={<TeamOutlined />}
171
- loading={isLoading}
172
- />
173
- </UICol>
174
- <UICol span={12}>
175
- <UIStatistic
176
- title="Batch Requests"
177
- value={stats?.batchRequests ?? 0}
178
- prefix={<GroupOutlined />}
179
- loading={isLoading}
180
- />
181
- </UICol>
182
- </UIRow>
183
- <div style={{ marginTop: 16 }}>
184
- <UIText color="secondary">Batch Request Ratio</UIText>
185
- <UIProgress
186
- percent={Number(batchPercentage)}
187
- status={Number(batchPercentage) > 50 ? 'success' : 'normal'}
188
- format={(percent) => `${percent}%`}
189
- />
190
- </div>
191
- </UICard>
192
- </UICol>
193
- <UICol xs={24} lg={12}>
194
- <UICard title="Performance Metrics">
195
- <UIRow gutter={[16, 16]}>
196
- <UICol span={12}>
197
- <UIStatistic
198
- title="Avg Duration"
199
- value={stats?.avgDurationMs ?? 0}
200
- prefix={<ClockCircleOutlined />}
201
- suffix="ms"
202
- precision={0}
203
- loading={isLoading}
204
- />
205
- </UICol>
206
- <UICol span={12}>
207
- <UIStatistic
208
- title="Avg Batch Size"
209
- value={stats?.avgBatchSize ?? 0}
210
- precision={1}
211
- loading={isLoading}
212
- valueStyle={{ color: 'var(--link)' }}
213
- />
214
- </UICol>
215
- </UIRow>
216
- </UICard>
217
- </UICol>
218
- </UIRow>
219
-
220
- {/* Cost Analysis */}
221
- {stats && stats.totalRequests > 0 && (
222
- <UICard title="Cost Analysis" style={{ marginTop: 16 }}>
223
- <UIRow gutter={[16, 16]}>
224
- <UICol xs={24} sm={8}>
225
- <UIStatistic
226
- title="Cost per Request"
227
- value={(stats.totalCost / stats.totalRequests).toFixed(6)}
228
- prefix="$"
229
- loading={isLoading}
230
- />
231
- </UICol>
232
- <UICol xs={24} sm={8}>
233
- <UIStatistic
234
- title="Cost per 1K Characters"
235
- value={((stats.totalCost / stats.totalTextLength) * 1000).toFixed(6)}
236
- prefix="$"
237
- loading={isLoading}
238
- />
239
- </UICol>
240
- <UICol xs={24} sm={8}>
241
- <UIStatistic
242
- title="Avg Text Length"
243
- value={Math.round(stats.totalTextLength / stats.totalRequests)}
244
- suffix="chars"
245
- loading={isLoading}
246
- />
247
- </UICol>
248
- </UIRow>
249
- </UICard>
250
- )}
251
-
252
- {/* Daily Usage Chart */}
253
- <UIStatisticsChart
254
- data={dailyStats}
255
- loading={dailyStatsLoading}
256
- title="Daily Embeddings Trend"
257
- metrics={[
258
- { key: 'count', label: 'Requests' },
259
- {
260
- key: 'totalTokens',
261
- label: 'Tokens (K)',
262
- transform: (v) => Math.floor(v / 1000),
263
- },
264
- {
265
- key: 'totalCost',
266
- label: 'Cost ($)',
267
- format: formatCost,
268
- },
269
- ]}
270
- />
271
- </div>
272
- </UIPage>
273
- );
274
- }