@kb-labs/studio-app 0.7.0 → 2.9.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/dist/index.html +1 -0
- package/dist/main.80b70197.css +2 -0
- package/dist/main.80b70197.css.map +1 -0
- package/dist/main.ad42ef4a.js +522 -0
- package/dist/main.ad42ef4a.js.map +1 -0
- package/dist/mf-manifest.json +241 -0
- package/dist/mf-stats.json +271 -0
- package/package.json +56 -39
- package/server.js +68 -0
- package/.env.example +0 -10
- package/UI-KIT-COMPONENTS.md +0 -783
- package/UI-KIT-PLAN.md +0 -326
- package/eslint-rules/no-direct-antd-import.js +0 -151
- package/eslint.config.ts +0 -27
- package/index.html +0 -17
- package/postcss.config.js +0 -7
- package/public/favicon.ico +0 -0
- package/rspack.config.mjs +0 -118
- package/src/App.tsx +0 -46
- package/src/components/devtools/devtools-log-feed.module.css +0 -165
- package/src/components/devtools/devtools-log-feed.tsx +0 -300
- package/src/components/devtools/devtools-panel.module.css +0 -121
- package/src/components/devtools/devtools-panel.tsx +0 -115
- package/src/components/empty-state.tsx +0 -28
- package/src/components/error-boundary.tsx +0 -210
- package/src/components/health-banner.module.css +0 -103
- package/src/components/health-banner.tsx +0 -134
- package/src/components/health-indicator.tsx +0 -12
- package/src/components/page-header.tsx +0 -49
- package/src/components/page-transition.tsx +0 -24
- package/src/components/role-switcher.tsx +0 -148
- package/src/components/run-badge.tsx +0 -13
- package/src/components/ui/icons.tsx +0 -509
- package/src/components/ui/index.ts +0 -25
- package/src/components/ui/kb-config-provider.tsx +0 -130
- package/src/components/ui/kb-header.module.css +0 -51
- package/src/components/ui/kb-header.tsx +0 -112
- package/src/components/ui/kb-notification-bell.module.css +0 -103
- package/src/components/ui/kb-notification-bell.tsx +0 -199
- package/src/components/ui/kb-page-layout.tsx +0 -66
- package/src/components/ui/kb-quick-search.module.css +0 -86
- package/src/components/ui/kb-quick-search.tsx +0 -196
- package/src/components/ui/kb-sidebar.module.css +0 -47
- package/src/components/ui/kb-sidebar.tsx +0 -196
- package/src/components/ui/kb-stat-card.module.css +0 -21
- package/src/components/ui/kb-stat-card.tsx +0 -22
- package/src/components/ui/kb-stat-grid.tsx +0 -22
- package/src/components/ui/kb-status-bar.module.css +0 -49
- package/src/components/ui/kb-status-bar.tsx +0 -145
- package/src/components/ui/kb-system-health-indicator.tsx +0 -229
- package/src/components/ui/kb-theme-toggle.tsx +0 -42
- package/src/components/ui/theme-adapter.ts +0 -812
- package/src/components/ui/theme-transition-overlay.tsx +0 -70
- package/src/components/ui/utils.ts +0 -6
- package/src/components/widget-error-boundary.tsx +0 -172
- package/src/config/env.ts +0 -5
- package/src/config/feature-flags.ts +0 -482
- package/src/config/studio.config.schema.ts +0 -88
- package/src/config/studio.config.ts +0 -84
- package/src/env.d.ts +0 -23
- package/src/hooks/use-command-palette.ts +0 -6
- package/src/hooks/use-devtools-store.ts +0 -25
- package/src/hooks/use-feature-flags.ts +0 -101
- package/src/index.css +0 -10
- package/src/layouts/dashboard-grid.tsx +0 -122
- package/src/layouts/index.ts +0 -12
- package/src/layouts/two-pane.tsx +0 -134
- package/src/main.tsx +0 -15
- package/src/modules/analytics/components/analytics-daily-stats-chart.tsx +0 -257
- package/src/modules/analytics/components/analytics-date-range-picker.tsx +0 -121
- package/src/modules/analytics/pages/analytics-cache-page.tsx +0 -285
- package/src/modules/analytics/pages/analytics-embeddings-page.tsx +0 -274
- package/src/modules/analytics/pages/analytics-events-page.tsx +0 -425
- package/src/modules/analytics/pages/analytics-llm-page.tsx +0 -434
- package/src/modules/analytics/pages/analytics-overview-page.tsx +0 -336
- package/src/modules/analytics/pages/analytics-page.tsx +0 -20
- package/src/modules/analytics/pages/analytics-storage-page.tsx +0 -344
- package/src/modules/analytics/pages/analytics-vectorstore-page.tsx +0 -279
- package/src/modules/analytics/routes/index.tsx +0 -133
- package/src/modules/analytics/utils/formatters.test.ts +0 -148
- package/src/modules/analytics/utils/formatters.ts +0 -100
- package/src/modules/auth/pages/login-page.module.css +0 -113
- package/src/modules/auth/pages/login-page.tsx +0 -80
- package/src/modules/auth/routes/index.tsx +0 -24
- package/src/modules/dashboard/components/ActivityTimelineWidget.tsx +0 -199
- package/src/modules/dashboard/components/AiInsightsWidget.tsx +0 -358
- package/src/modules/dashboard/components/AnimatedMetricCard.css +0 -88
- package/src/modules/dashboard/components/AnimatedMetricCard.tsx +0 -125
- package/src/modules/dashboard/components/HeroMetricCard.css +0 -114
- package/src/modules/dashboard/components/HeroMetricCard.tsx +0 -152
- package/src/modules/dashboard/components/HeroMetricsWidget.tsx +0 -146
- package/src/modules/dashboard/components/SystemResourcesWidget.tsx +0 -197
- package/src/modules/dashboard/components/dashboard-empty.tsx +0 -22
- package/src/modules/dashboard/components/dashboard-kpis-widget.tsx +0 -59
- package/src/modules/dashboard/components/dashboard-kpis.tsx +0 -13
- package/src/modules/dashboard/components/dashboard-latency-percentiles-widget.tsx +0 -85
- package/src/modules/dashboard/components/dashboard-metrics-widget.tsx +0 -78
- package/src/modules/dashboard/components/dashboard-plugins-widget.tsx +0 -67
- package/src/modules/dashboard/components/dashboard-requests-widget.tsx +0 -62
- package/src/modules/dashboard/layouts/dashboard-layout.tsx +0 -16
- package/src/modules/dashboard/pages/ai-insights-page.tsx +0 -563
- package/src/modules/dashboard/pages/dashboard-animations.css +0 -317
- package/src/modules/dashboard/pages/dashboard-page.tsx +0 -13
- package/src/modules/dashboard/routes/index.tsx +0 -70
- package/src/modules/observability/pages/devkit-page.tsx +0 -263
- package/src/modules/observability/pages/incident-detail-page.tsx +0 -571
- package/src/modules/observability/pages/incidents-page.tsx +0 -370
- package/src/modules/observability/pages/log-detail-page.tsx +0 -508
- package/src/modules/observability/pages/logs-page.tsx +0 -1129
- package/src/modules/observability/pages/prometheus-metrics-page.tsx +0 -486
- package/src/modules/observability/pages/state-broker-page.tsx +0 -229
- package/src/modules/observability/pages/system-events-page.tsx +0 -255
- package/src/modules/observability/routes/index.tsx +0 -133
- package/src/modules/plugins/components/marketplace-card.tsx +0 -153
- package/src/modules/plugins/components/plugin-ai-assistant-modal.tsx +0 -374
- package/src/modules/plugins/components/plugin-card.tsx +0 -136
- package/src/modules/plugins/components/plugin-detail/capabilities-summary.tsx +0 -101
- package/src/modules/plugins/components/plugin-detail/cli-commands-table.tsx +0 -101
- package/src/modules/plugins/components/plugin-detail/index.ts +0 -7
- package/src/modules/plugins/components/plugin-detail/jobs-table.tsx +0 -64
- package/src/modules/plugins/components/plugin-detail/permissions/env-permissions.tsx +0 -30
- package/src/modules/plugins/components/plugin-detail/permissions/filesystem-permissions.tsx +0 -68
- package/src/modules/plugins/components/plugin-detail/permissions/index.ts +0 -6
- package/src/modules/plugins/components/plugin-detail/permissions/network-permissions.tsx +0 -43
- package/src/modules/plugins/components/plugin-detail/permissions/platform-services.tsx +0 -242
- package/src/modules/plugins/components/plugin-detail/permissions/resource-quotas.tsx +0 -96
- package/src/modules/plugins/components/plugin-detail/permissions/shell-permissions.tsx +0 -55
- package/src/modules/plugins/components/plugin-detail/permissions-view.tsx +0 -47
- package/src/modules/plugins/components/plugin-detail/plugin-header.tsx +0 -169
- package/src/modules/plugins/components/plugin-detail/rest-routes-table.tsx +0 -159
- package/src/modules/plugins/components/plugin-detail/workflows-table.tsx +0 -40
- package/src/modules/plugins/components/plugin-grid.tsx +0 -20
- package/src/modules/plugins/components/plugin-table.tsx +0 -178
- package/src/modules/plugins/pages/marketplace-page.tsx +0 -200
- package/src/modules/plugins/pages/plugin-detail-page.tsx +0 -1145
- package/src/modules/plugins/routes/index.tsx +0 -48
- package/src/modules/plugins/utils/index.ts +0 -1
- package/src/modules/plugins/utils/schema-helpers.ts +0 -21
- package/src/modules/settings/components/api-routes-viewer.tsx +0 -415
- package/src/modules/settings/components/appearance-settings.tsx +0 -200
- package/src/modules/settings/components/configuration-settings.tsx +0 -321
- package/src/modules/settings/components/data-privacy-settings.tsx +0 -111
- package/src/modules/settings/components/experimental-settings.tsx +0 -243
- package/src/modules/settings/components/navigation-settings.tsx +0 -198
- package/src/modules/settings/components/notifications-settings.tsx +0 -40
- package/src/modules/settings/pages/settings-page.tsx +0 -298
- package/src/modules/settings/routes/index.tsx +0 -47
- package/src/pages/README-assistant.md +0 -91
- package/src/pages/login-page.tsx +0 -177
- package/src/pages/not-found-page.tsx +0 -85
- package/src/providers/auth-provider.tsx +0 -40
- package/src/providers/command-palette-provider.tsx +0 -193
- package/src/providers/data-sources-provider.tsx +0 -27
- package/src/providers/devtools-provider.tsx +0 -72
- package/src/providers/navigation-items-provider.tsx +0 -38
- package/src/providers/registry-v2-provider.tsx +0 -93
- package/src/providers/settings-provider.tsx +0 -158
- package/src/router.tsx +0 -302
- package/src/routes/helpers.tsx +0 -25
- package/src/routes/plugin-page-v2.tsx +0 -52
- package/src/routes/types.ts +0 -18
- package/src/styles/antd-overrides.css +0 -211
- package/src/styles/base.css +0 -190
- package/src/styles/settings.css +0 -75
- package/src/styles/variables.css +0 -94
- package/src/utils/analytics.ts +0 -183
- package/src/utils/apply-navigation-categories.ts +0 -83
- package/src/utils/commands.ts +0 -252
- package/src/utils/export.ts +0 -174
- package/src/utils/format-date.ts +0 -166
- package/src/utils/logger.ts +0 -110
- package/tailwind.config.ts +0 -13
- package/tsconfig.json +0 -13
- package/vitest-setup.ts +0 -1
- /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
|
-
}
|