@kb-labs/studio-app 0.6.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 (168) hide show
  1. package/.env.example +10 -0
  2. package/README.md +74 -0
  3. package/UI-KIT-COMPONENTS.md +783 -0
  4. package/UI-KIT-PLAN.md +326 -0
  5. package/eslint-rules/no-direct-antd-import.js +151 -0
  6. package/eslint.config.ts +27 -0
  7. package/index.html +17 -0
  8. package/package.json +72 -0
  9. package/postcss.config.js +7 -0
  10. package/public/favicon.ico +0 -0
  11. package/public/favicon.svg +7 -0
  12. package/rspack.config.mjs +118 -0
  13. package/src/App.tsx +46 -0
  14. package/src/components/devtools/devtools-log-feed.module.css +165 -0
  15. package/src/components/devtools/devtools-log-feed.tsx +300 -0
  16. package/src/components/devtools/devtools-panel.module.css +121 -0
  17. package/src/components/devtools/devtools-panel.tsx +115 -0
  18. package/src/components/empty-state.tsx +28 -0
  19. package/src/components/error-boundary.tsx +210 -0
  20. package/src/components/health-banner.module.css +103 -0
  21. package/src/components/health-banner.tsx +134 -0
  22. package/src/components/health-indicator.tsx +12 -0
  23. package/src/components/page-header.tsx +49 -0
  24. package/src/components/page-transition.tsx +24 -0
  25. package/src/components/role-switcher.tsx +148 -0
  26. package/src/components/run-badge.tsx +13 -0
  27. package/src/components/ui/icons.tsx +509 -0
  28. package/src/components/ui/index.ts +25 -0
  29. package/src/components/ui/kb-config-provider.tsx +130 -0
  30. package/src/components/ui/kb-header.module.css +51 -0
  31. package/src/components/ui/kb-header.tsx +112 -0
  32. package/src/components/ui/kb-notification-bell.module.css +103 -0
  33. package/src/components/ui/kb-notification-bell.tsx +199 -0
  34. package/src/components/ui/kb-page-layout.tsx +66 -0
  35. package/src/components/ui/kb-quick-search.module.css +86 -0
  36. package/src/components/ui/kb-quick-search.tsx +196 -0
  37. package/src/components/ui/kb-sidebar.module.css +47 -0
  38. package/src/components/ui/kb-sidebar.tsx +196 -0
  39. package/src/components/ui/kb-stat-card.module.css +21 -0
  40. package/src/components/ui/kb-stat-card.tsx +22 -0
  41. package/src/components/ui/kb-stat-grid.tsx +22 -0
  42. package/src/components/ui/kb-status-bar.module.css +49 -0
  43. package/src/components/ui/kb-status-bar.tsx +145 -0
  44. package/src/components/ui/kb-system-health-indicator.tsx +229 -0
  45. package/src/components/ui/kb-theme-toggle.tsx +42 -0
  46. package/src/components/ui/theme-adapter.ts +812 -0
  47. package/src/components/ui/theme-transition-overlay.tsx +70 -0
  48. package/src/components/ui/utils.ts +6 -0
  49. package/src/components/widget-error-boundary.tsx +172 -0
  50. package/src/config/env.ts +5 -0
  51. package/src/config/feature-flags.ts +482 -0
  52. package/src/config/studio.config.schema.ts +88 -0
  53. package/src/config/studio.config.ts +84 -0
  54. package/src/env.d.ts +23 -0
  55. package/src/hooks/use-command-palette.ts +6 -0
  56. package/src/hooks/use-devtools-store.ts +25 -0
  57. package/src/hooks/use-feature-flags.ts +101 -0
  58. package/src/index.css +10 -0
  59. package/src/layouts/dashboard-grid.tsx +122 -0
  60. package/src/layouts/index.ts +12 -0
  61. package/src/layouts/two-pane.tsx +134 -0
  62. package/src/main.tsx +15 -0
  63. package/src/modules/analytics/components/analytics-daily-stats-chart.tsx +257 -0
  64. package/src/modules/analytics/components/analytics-date-range-picker.tsx +121 -0
  65. package/src/modules/analytics/pages/analytics-cache-page.tsx +285 -0
  66. package/src/modules/analytics/pages/analytics-embeddings-page.tsx +274 -0
  67. package/src/modules/analytics/pages/analytics-events-page.tsx +425 -0
  68. package/src/modules/analytics/pages/analytics-llm-page.tsx +434 -0
  69. package/src/modules/analytics/pages/analytics-overview-page.tsx +336 -0
  70. package/src/modules/analytics/pages/analytics-page.tsx +20 -0
  71. package/src/modules/analytics/pages/analytics-storage-page.tsx +344 -0
  72. package/src/modules/analytics/pages/analytics-vectorstore-page.tsx +279 -0
  73. package/src/modules/analytics/routes/index.tsx +133 -0
  74. package/src/modules/analytics/utils/formatters.test.ts +148 -0
  75. package/src/modules/analytics/utils/formatters.ts +100 -0
  76. package/src/modules/auth/pages/login-page.module.css +113 -0
  77. package/src/modules/auth/pages/login-page.tsx +80 -0
  78. package/src/modules/auth/routes/index.tsx +24 -0
  79. package/src/modules/dashboard/components/ActivityTimelineWidget.tsx +199 -0
  80. package/src/modules/dashboard/components/AiInsightsWidget.tsx +358 -0
  81. package/src/modules/dashboard/components/AnimatedMetricCard.css +88 -0
  82. package/src/modules/dashboard/components/AnimatedMetricCard.tsx +125 -0
  83. package/src/modules/dashboard/components/HeroMetricCard.css +114 -0
  84. package/src/modules/dashboard/components/HeroMetricCard.tsx +152 -0
  85. package/src/modules/dashboard/components/HeroMetricsWidget.tsx +146 -0
  86. package/src/modules/dashboard/components/SystemResourcesWidget.tsx +197 -0
  87. package/src/modules/dashboard/components/dashboard-empty.tsx +22 -0
  88. package/src/modules/dashboard/components/dashboard-kpis-widget.tsx +59 -0
  89. package/src/modules/dashboard/components/dashboard-kpis.tsx +13 -0
  90. package/src/modules/dashboard/components/dashboard-latency-percentiles-widget.tsx +85 -0
  91. package/src/modules/dashboard/components/dashboard-metrics-widget.tsx +78 -0
  92. package/src/modules/dashboard/components/dashboard-plugins-widget.tsx +67 -0
  93. package/src/modules/dashboard/components/dashboard-requests-widget.tsx +62 -0
  94. package/src/modules/dashboard/layouts/dashboard-layout.tsx +16 -0
  95. package/src/modules/dashboard/pages/ai-insights-page.tsx +563 -0
  96. package/src/modules/dashboard/pages/dashboard-animations.css +317 -0
  97. package/src/modules/dashboard/pages/dashboard-page.tsx +13 -0
  98. package/src/modules/dashboard/routes/index.tsx +70 -0
  99. package/src/modules/observability/pages/devkit-page.tsx +263 -0
  100. package/src/modules/observability/pages/incident-detail-page.tsx +571 -0
  101. package/src/modules/observability/pages/incidents-page.tsx +370 -0
  102. package/src/modules/observability/pages/log-detail-page.tsx +508 -0
  103. package/src/modules/observability/pages/logs-page.tsx +1129 -0
  104. package/src/modules/observability/pages/prometheus-metrics-page.tsx +486 -0
  105. package/src/modules/observability/pages/state-broker-page.tsx +229 -0
  106. package/src/modules/observability/pages/system-events-page.tsx +255 -0
  107. package/src/modules/observability/routes/index.tsx +133 -0
  108. package/src/modules/plugins/components/marketplace-card.tsx +153 -0
  109. package/src/modules/plugins/components/plugin-ai-assistant-modal.tsx +374 -0
  110. package/src/modules/plugins/components/plugin-card.tsx +136 -0
  111. package/src/modules/plugins/components/plugin-detail/capabilities-summary.tsx +101 -0
  112. package/src/modules/plugins/components/plugin-detail/cli-commands-table.tsx +101 -0
  113. package/src/modules/plugins/components/plugin-detail/index.ts +7 -0
  114. package/src/modules/plugins/components/plugin-detail/jobs-table.tsx +64 -0
  115. package/src/modules/plugins/components/plugin-detail/permissions/env-permissions.tsx +30 -0
  116. package/src/modules/plugins/components/plugin-detail/permissions/filesystem-permissions.tsx +68 -0
  117. package/src/modules/plugins/components/plugin-detail/permissions/index.ts +6 -0
  118. package/src/modules/plugins/components/plugin-detail/permissions/network-permissions.tsx +43 -0
  119. package/src/modules/plugins/components/plugin-detail/permissions/platform-services.tsx +242 -0
  120. package/src/modules/plugins/components/plugin-detail/permissions/resource-quotas.tsx +96 -0
  121. package/src/modules/plugins/components/plugin-detail/permissions/shell-permissions.tsx +55 -0
  122. package/src/modules/plugins/components/plugin-detail/permissions-view.tsx +47 -0
  123. package/src/modules/plugins/components/plugin-detail/plugin-header.tsx +169 -0
  124. package/src/modules/plugins/components/plugin-detail/rest-routes-table.tsx +159 -0
  125. package/src/modules/plugins/components/plugin-detail/workflows-table.tsx +40 -0
  126. package/src/modules/plugins/components/plugin-grid.tsx +20 -0
  127. package/src/modules/plugins/components/plugin-table.tsx +178 -0
  128. package/src/modules/plugins/pages/marketplace-page.tsx +200 -0
  129. package/src/modules/plugins/pages/plugin-detail-page.tsx +1145 -0
  130. package/src/modules/plugins/routes/index.tsx +48 -0
  131. package/src/modules/plugins/utils/index.ts +1 -0
  132. package/src/modules/plugins/utils/schema-helpers.ts +21 -0
  133. package/src/modules/settings/components/api-routes-viewer.tsx +415 -0
  134. package/src/modules/settings/components/appearance-settings.tsx +200 -0
  135. package/src/modules/settings/components/configuration-settings.tsx +321 -0
  136. package/src/modules/settings/components/data-privacy-settings.tsx +111 -0
  137. package/src/modules/settings/components/experimental-settings.tsx +243 -0
  138. package/src/modules/settings/components/navigation-settings.tsx +198 -0
  139. package/src/modules/settings/components/notifications-settings.tsx +40 -0
  140. package/src/modules/settings/pages/settings-page.tsx +298 -0
  141. package/src/modules/settings/routes/index.tsx +47 -0
  142. package/src/pages/README-assistant.md +91 -0
  143. package/src/pages/login-page.tsx +177 -0
  144. package/src/pages/not-found-page.tsx +85 -0
  145. package/src/providers/auth-provider.tsx +40 -0
  146. package/src/providers/command-palette-provider.tsx +193 -0
  147. package/src/providers/data-sources-provider.tsx +27 -0
  148. package/src/providers/devtools-provider.tsx +72 -0
  149. package/src/providers/navigation-items-provider.tsx +38 -0
  150. package/src/providers/registry-v2-provider.tsx +93 -0
  151. package/src/providers/settings-provider.tsx +158 -0
  152. package/src/router.tsx +302 -0
  153. package/src/routes/helpers.tsx +25 -0
  154. package/src/routes/plugin-page-v2.tsx +52 -0
  155. package/src/routes/types.ts +18 -0
  156. package/src/styles/antd-overrides.css +211 -0
  157. package/src/styles/base.css +190 -0
  158. package/src/styles/settings.css +75 -0
  159. package/src/styles/variables.css +94 -0
  160. package/src/utils/analytics.ts +183 -0
  161. package/src/utils/apply-navigation-categories.ts +83 -0
  162. package/src/utils/commands.ts +252 -0
  163. package/src/utils/export.ts +174 -0
  164. package/src/utils/format-date.ts +166 -0
  165. package/src/utils/logger.ts +110 -0
  166. package/tailwind.config.ts +13 -0
  167. package/tsconfig.json +13 -0
  168. package/vitest-setup.ts +1 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @module @kb-labs/studio-app/utils/format-date
3
+ * Date formatting utilities for Studio UI
4
+ */
5
+
6
+ export interface FormatTimestampOptions {
7
+ /**
8
+ * Locale to use for formatting (defaults to browser locale)
9
+ */
10
+ locale?: string;
11
+ /**
12
+ * Whether to include time (default: true)
13
+ */
14
+ includeTime?: boolean;
15
+ /**
16
+ * Whether to use 24-hour format (default: true)
17
+ */
18
+ hour24?: boolean;
19
+ }
20
+
21
+ /**
22
+ * Format ISO timestamp to human-readable string using browser's locale
23
+ *
24
+ * @param isoString - ISO 8601 timestamp string (e.g., "2025-12-21T21:05:36.544Z")
25
+ * @param options - Formatting options
26
+ * @returns Formatted date string (e.g., "12/21/2025, 21:05:36" for en-US locale)
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * formatTimestamp("2025-12-21T21:05:36.544Z")
31
+ * // => "12/21/2025, 21:05:36" (en-US)
32
+ * // => "21.12.2025, 21:05:36" (de-DE)
33
+ * // => "2025/12/21 21:05:36" (ja-JP)
34
+ *
35
+ * formatTimestamp("2025-12-21T21:05:36.544Z", { includeTime: false })
36
+ * // => "12/21/2025"
37
+ *
38
+ * formatTimestamp(null)
39
+ * // => "N/A"
40
+ * ```
41
+ */
42
+ export function formatTimestamp(
43
+ isoString: string | null | undefined,
44
+ options?: FormatTimestampOptions
45
+ ): string {
46
+ if (!isoString) {
47
+ return 'N/A';
48
+ }
49
+
50
+ try {
51
+ const date = new Date(isoString);
52
+
53
+ // Check if date is valid
54
+ if (Number.isNaN(date.getTime())) {
55
+ return isoString;
56
+ }
57
+
58
+ const { locale, includeTime = true, hour24 = true } = options ?? {};
59
+
60
+ const formatOptions: Intl.DateTimeFormatOptions = {
61
+ year: 'numeric',
62
+ month: '2-digit',
63
+ day: '2-digit',
64
+ };
65
+
66
+ if (includeTime) {
67
+ formatOptions.hour = '2-digit';
68
+ formatOptions.minute = '2-digit';
69
+ formatOptions.second = '2-digit';
70
+ formatOptions.hour12 = !hour24;
71
+ }
72
+
73
+ return date.toLocaleString(locale, formatOptions);
74
+ } catch {
75
+ return isoString;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Format duration in milliseconds to human-readable string
81
+ *
82
+ * @param ms - Duration in milliseconds
83
+ * @returns Formatted duration (e.g., "5m 30s", "1h 20m", "45s")
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * formatDuration(45000) // => "45s"
88
+ * formatDuration(330000) // => "5m 30s"
89
+ * formatDuration(4800000) // => "1h 20m"
90
+ * formatDuration(null) // => "N/A"
91
+ * ```
92
+ */
93
+ export function formatDuration(ms: number | null | undefined): string {
94
+ if (ms == null || !Number.isFinite(ms)) {
95
+ return 'N/A';
96
+ }
97
+
98
+ const seconds = Math.floor(ms / 1000);
99
+ const minutes = Math.floor(seconds / 60);
100
+ const hours = Math.floor(minutes / 60);
101
+
102
+ if (hours > 0) {
103
+ const remainingMinutes = minutes % 60;
104
+ return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
105
+ }
106
+
107
+ if (minutes > 0) {
108
+ const remainingSeconds = seconds % 60;
109
+ return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
110
+ }
111
+
112
+ return `${seconds}s`;
113
+ }
114
+
115
+ /**
116
+ * Format relative time (e.g., "2 hours ago", "in 5 minutes")
117
+ *
118
+ * @param isoString - ISO 8601 timestamp string
119
+ * @param locale - Locale to use (defaults to browser locale)
120
+ * @returns Relative time string
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * formatRelativeTime("2025-12-21T19:05:36.544Z") // 2 hours ago
125
+ * // => "2 hours ago" (en-US)
126
+ * // => "vor 2 Stunden" (de-DE)
127
+ * ```
128
+ */
129
+ export function formatRelativeTime(
130
+ isoString: string | null | undefined,
131
+ locale?: string
132
+ ): string {
133
+ if (!isoString) {
134
+ return 'N/A';
135
+ }
136
+
137
+ try {
138
+ const date = new Date(isoString);
139
+ if (Number.isNaN(date.getTime())) {
140
+ return isoString;
141
+ }
142
+
143
+ const now = Date.now();
144
+ const diff = date.getTime() - now;
145
+ const absDiff = Math.abs(diff);
146
+
147
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
148
+
149
+ if (absDiff < 60_000) {
150
+ // < 1 minute
151
+ return rtf.format(Math.floor(diff / 1000), 'second');
152
+ }
153
+ if (absDiff < 3600_000) {
154
+ // < 1 hour
155
+ return rtf.format(Math.floor(diff / 60_000), 'minute');
156
+ }
157
+ if (absDiff < 86400_000) {
158
+ // < 1 day
159
+ return rtf.format(Math.floor(diff / 3600_000), 'hour');
160
+ }
161
+ // >= 1 day
162
+ return rtf.format(Math.floor(diff / 86400_000), 'day');
163
+ } catch {
164
+ return isoString;
165
+ }
166
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @module Studio Logger
3
+ * Browser-compatible logger for Studio application
4
+ *
5
+ * For production, consider integrating with @kb-labs/core-sys/logging if browser support is added.
6
+ */
7
+
8
+ type Fields = Record<string, unknown>;
9
+
10
+ export interface StudioLogger {
11
+ debug(message: string, fields?: Fields): void;
12
+ info(message: string, fields?: Fields): void;
13
+ warn(message: string, fields?: Fields): void;
14
+ error(message: string, fields?: Fields | Error): void;
15
+ }
16
+
17
+ const sessionTraceId = resolveTraceId();
18
+ const sessionReqId = resolveReqId();
19
+
20
+ /**
21
+ * Create Studio logger with scope and context
22
+ *
23
+ * The structured format is maintained for consistency with the new logging system.
24
+ */
25
+ export function createStudioLogger(scope: string, context: Fields = {}): StudioLogger {
26
+ const baseFields: Fields = {
27
+ scope,
28
+ layer: 'studio',
29
+ ...context,
30
+ };
31
+
32
+ return {
33
+ debug(message, fields) {
34
+ emit('debug', scope, message, baseFields, fields);
35
+ },
36
+ info(message, fields) {
37
+ emit('info', scope, message, baseFields, fields);
38
+ },
39
+ warn(message, fields) {
40
+ emit('warn', scope, message, baseFields, fields);
41
+ },
42
+ error(message, fields) {
43
+ if (fields instanceof Error) {
44
+ emit('error', scope, message, baseFields, {
45
+ error: {
46
+ name: fields.name,
47
+ message: fields.message,
48
+ stack: fields.stack,
49
+ },
50
+ });
51
+ return;
52
+ }
53
+ emit('error', scope, message, baseFields, fields);
54
+ },
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Emit structured log to console
60
+ * Maintains compatibility with new logging system format
61
+ */
62
+ function emit(
63
+ level: 'debug' | 'info' | 'warn' | 'error',
64
+ scope: string,
65
+ message: string,
66
+ base: Fields,
67
+ extra?: Fields
68
+ ) {
69
+ const combinedFields = { ...base, ...(extra ?? {}) };
70
+ const { traceId: fieldTraceId, reqId: fieldReqId, layer, ...rest } = combinedFields;
71
+
72
+ // Structured payload matching LogRecord format from @kb-labs/core-sys/logging
73
+ const payload = {
74
+ time: new Date().toISOString(),
75
+ level,
76
+ category: `studio:${scope}`,
77
+ msg: message,
78
+ traceId: (fieldTraceId as string | undefined) ?? sessionTraceId,
79
+ reqId: (fieldReqId as string | undefined) ?? sessionReqId,
80
+ meta: {
81
+ layer: typeof layer === 'string' ? layer : 'studio',
82
+ scope,
83
+ ...rest,
84
+ },
85
+ };
86
+
87
+ const serialized = JSON.stringify(payload);
88
+
89
+ // Use appropriate console method
90
+ if (level === 'error') {
91
+ console.error(serialized);
92
+ } else if (level === 'warn') {
93
+ console.warn(serialized);
94
+ } else if (level === 'info') {
95
+ } else {
96
+ console.debug(serialized);
97
+ }
98
+ }
99
+
100
+ function resolveTraceId(): string {
101
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
102
+ return crypto.randomUUID();
103
+ }
104
+ return `studio-trace-${Math.random().toString(36).slice(2)}`;
105
+ }
106
+
107
+ function resolveReqId(): string {
108
+ return `studio-req-${Math.random().toString(36).slice(2)}`;
109
+ }
110
+
@@ -0,0 +1,13 @@
1
+ import type { Config } from 'tailwindcss';
2
+
3
+ const config: Config = {
4
+ content: ['./index.html', './src/**/*.{ts,tsx}'],
5
+ darkMode: 'class',
6
+ theme: {
7
+ extend: {},
8
+ },
9
+ plugins: [],
10
+ };
11
+
12
+ export default config;
13
+
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "noEmit": true,
6
+ "paths": {
7
+ "@/*": ["./src/*"],
8
+ "@kb-labs/studio-ui-core": ["../../packages/studio-ui-core/src"],
9
+ "@kb-labs/studio-data-client": ["../../packages/studio-data-client/src"]
10
+ }
11
+ },
12
+ "include": ["src", "vite.config.ts"]
13
+ }
@@ -0,0 +1 @@
1
+ // Vitest setup for studio app