@contractspec/lib.example-shared-ui 6.0.17 → 6.0.18
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/.turbo/turbo-build.log +81 -81
- package/CHANGELOG.md +17 -0
- package/dist/EvolutionDashboard.js +1 -803
- package/dist/EvolutionSidebar.js +1 -531
- package/dist/LocalDataIndicator.js +1 -68
- package/dist/MarkdownView.js +1 -213
- package/dist/OverlayContextProvider.js +1 -202
- package/dist/PersonalizationInsights.js +1 -455
- package/dist/SaveToStudioButton.js +1 -79
- package/dist/SpecDrivenTemplateShell.js +1 -203
- package/dist/SpecEditorPanel.js +17 -364
- package/dist/TemplateShell.js +1 -195
- package/dist/browser/EvolutionDashboard.js +1 -803
- package/dist/browser/EvolutionSidebar.js +1 -531
- package/dist/browser/LocalDataIndicator.js +1 -68
- package/dist/browser/MarkdownView.js +1 -213
- package/dist/browser/OverlayContextProvider.js +1 -202
- package/dist/browser/PersonalizationInsights.js +1 -455
- package/dist/browser/SaveToStudioButton.js +1 -79
- package/dist/browser/SpecDrivenTemplateShell.js +1 -203
- package/dist/browser/SpecEditorPanel.js +17 -364
- package/dist/browser/TemplateShell.js +1 -195
- package/dist/browser/bundles/ExampleTemplateBundle.js +1 -85
- package/dist/browser/bundles/index.js +1 -85
- package/dist/browser/hooks/index.js +40 -1151
- package/dist/browser/hooks/useBehaviorTracking.js +1 -157
- package/dist/browser/hooks/useEvolution.js +1 -260
- package/dist/browser/hooks/useRegistryTemplates.js +1 -31
- package/dist/browser/hooks/useSpecContent.js +17 -224
- package/dist/browser/hooks/useWorkflowComposer.js +24 -483
- package/dist/browser/index.js +40 -3122
- package/dist/browser/lib/component-registry.js +1 -48
- package/dist/browser/lib/runtime-context.js +1 -21
- package/dist/browser/markdown/formatPresentationName.js +1 -9
- package/dist/browser/markdown/useMarkdownPresentation.js +1 -65
- package/dist/browser/utils/fetchPresentationData.js +1 -15
- package/dist/browser/utils/generateSpecFromTemplate.js +16 -62
- package/dist/browser/utils/index.js +16 -76
- package/dist/bundles/ExampleTemplateBundle.js +1 -85
- package/dist/bundles/index.js +1 -85
- package/dist/hooks/index.js +40 -1151
- package/dist/hooks/useBehaviorTracking.js +1 -157
- package/dist/hooks/useEvolution.js +1 -260
- package/dist/hooks/useRegistryTemplates.js +1 -31
- package/dist/hooks/useSpecContent.js +17 -224
- package/dist/hooks/useWorkflowComposer.js +24 -483
- package/dist/index.js +40 -3122
- package/dist/lib/component-registry.js +1 -48
- package/dist/lib/runtime-context.js +1 -21
- package/dist/markdown/formatPresentationName.js +1 -9
- package/dist/markdown/useMarkdownPresentation.js +1 -65
- package/dist/node/EvolutionDashboard.js +1 -803
- package/dist/node/EvolutionSidebar.js +1 -531
- package/dist/node/LocalDataIndicator.js +1 -68
- package/dist/node/MarkdownView.js +1 -213
- package/dist/node/OverlayContextProvider.js +1 -202
- package/dist/node/PersonalizationInsights.js +1 -455
- package/dist/node/SaveToStudioButton.js +1 -79
- package/dist/node/SpecDrivenTemplateShell.js +1 -203
- package/dist/node/SpecEditorPanel.js +17 -364
- package/dist/node/TemplateShell.js +1 -195
- package/dist/node/bundles/ExampleTemplateBundle.js +1 -85
- package/dist/node/bundles/index.js +1 -85
- package/dist/node/hooks/index.js +40 -1151
- package/dist/node/hooks/useBehaviorTracking.js +1 -157
- package/dist/node/hooks/useEvolution.js +1 -260
- package/dist/node/hooks/useRegistryTemplates.js +1 -31
- package/dist/node/hooks/useSpecContent.js +17 -224
- package/dist/node/hooks/useWorkflowComposer.js +24 -483
- package/dist/node/index.js +40 -3122
- package/dist/node/lib/component-registry.js +1 -48
- package/dist/node/lib/runtime-context.js +1 -21
- package/dist/node/markdown/formatPresentationName.js +1 -9
- package/dist/node/markdown/useMarkdownPresentation.js +1 -65
- package/dist/node/utils/fetchPresentationData.js +1 -15
- package/dist/node/utils/generateSpecFromTemplate.js +16 -62
- package/dist/node/utils/index.js +16 -76
- package/dist/utils/fetchPresentationData.js +1 -15
- package/dist/utils/generateSpecFromTemplate.js +16 -62
- package/dist/utils/index.js +16 -76
- package/package.json +13 -13
- package/src/lib/component-registry.tsx +2 -1
- package/src/lib/runtime-context.tsx +1 -1
- package/src/lib/singletons.test.ts +19 -22
|
@@ -1,804 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// src/hooks/useEvolution.ts
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
"use client";
|
|
5
|
-
var EVOLUTION_STORAGE_KEY = "contractspec-evolution-data";
|
|
6
|
-
function useEvolution(templateId) {
|
|
7
|
-
const [usageStats, setUsageStats] = useState([]);
|
|
8
|
-
const [anomalies, setAnomalies] = useState([]);
|
|
9
|
-
const [suggestions, setSuggestions] = useState([]);
|
|
10
|
-
const [hints, setHints] = useState([]);
|
|
11
|
-
const [loading, setLoading] = useState(false);
|
|
12
|
-
const metricsRef = useRef([]);
|
|
13
|
-
const [operationCount, setOperationCount] = useState(0);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
try {
|
|
16
|
-
const stored = localStorage.getItem(`${EVOLUTION_STORAGE_KEY}-${templateId}`);
|
|
17
|
-
if (stored) {
|
|
18
|
-
const data = JSON.parse(stored);
|
|
19
|
-
setSuggestions(data.suggestions.map((s) => ({
|
|
20
|
-
...s,
|
|
21
|
-
createdAt: new Date(s.createdAt)
|
|
22
|
-
})));
|
|
23
|
-
}
|
|
24
|
-
} catch {}
|
|
25
|
-
}, [templateId]);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
try {
|
|
28
|
-
localStorage.setItem(`${EVOLUTION_STORAGE_KEY}-${templateId}`, JSON.stringify({ suggestions }));
|
|
29
|
-
} catch {}
|
|
30
|
-
}, [suggestions, templateId]);
|
|
31
|
-
const trackOperation = useCallback((operationName, durationMs, success, errorCode) => {
|
|
32
|
-
const sample = {
|
|
33
|
-
operation: {
|
|
34
|
-
name: operationName,
|
|
35
|
-
version: "1.0.0",
|
|
36
|
-
tenantId: "sandbox"
|
|
37
|
-
},
|
|
38
|
-
durationMs,
|
|
39
|
-
success,
|
|
40
|
-
timestamp: new Date,
|
|
41
|
-
errorCode
|
|
42
|
-
};
|
|
43
|
-
metricsRef.current.push(sample);
|
|
44
|
-
setOperationCount((prev) => prev + 1);
|
|
45
|
-
}, []);
|
|
46
|
-
const analyzeUsage = useCallback(() => {
|
|
47
|
-
const samples = metricsRef.current;
|
|
48
|
-
if (samples.length < 5)
|
|
49
|
-
return;
|
|
50
|
-
const groups = new Map;
|
|
51
|
-
for (const sample of samples) {
|
|
52
|
-
const key = `${sample.operation.name}.v${sample.operation.version}`;
|
|
53
|
-
const arr = groups.get(key) ?? [];
|
|
54
|
-
arr.push(sample);
|
|
55
|
-
groups.set(key, arr);
|
|
56
|
-
}
|
|
57
|
-
const stats = [];
|
|
58
|
-
const detectedAnomalies = [];
|
|
59
|
-
groups.forEach((opSamples) => {
|
|
60
|
-
if (opSamples.length < 3)
|
|
61
|
-
return;
|
|
62
|
-
const durations = opSamples.map((s) => s.durationMs).sort((a, b) => a - b);
|
|
63
|
-
const errors = opSamples.filter((s) => !s.success);
|
|
64
|
-
const totalCalls = opSamples.length;
|
|
65
|
-
const errorRate = errors.length / totalCalls;
|
|
66
|
-
const averageLatencyMs = durations.reduce((sum, value) => sum + value, 0) / totalCalls;
|
|
67
|
-
const timestamps = opSamples.map((s) => s.timestamp.getTime());
|
|
68
|
-
const firstSample = opSamples[0];
|
|
69
|
-
if (!firstSample)
|
|
70
|
-
return;
|
|
71
|
-
const stat = {
|
|
72
|
-
operation: firstSample.operation,
|
|
73
|
-
totalCalls,
|
|
74
|
-
successRate: 1 - errorRate,
|
|
75
|
-
errorRate,
|
|
76
|
-
averageLatencyMs,
|
|
77
|
-
p95LatencyMs: percentile(durations, 0.95),
|
|
78
|
-
p99LatencyMs: percentile(durations, 0.99),
|
|
79
|
-
maxLatencyMs: Math.max(...durations),
|
|
80
|
-
lastSeenAt: new Date(Math.max(...timestamps)),
|
|
81
|
-
windowStart: new Date(Math.min(...timestamps)),
|
|
82
|
-
windowEnd: new Date(Math.max(...timestamps)),
|
|
83
|
-
topErrors: errors.reduce((acc, s) => {
|
|
84
|
-
if (s.errorCode) {
|
|
85
|
-
acc[s.errorCode] = (acc[s.errorCode] ?? 0) + 1;
|
|
86
|
-
}
|
|
87
|
-
return acc;
|
|
88
|
-
}, {})
|
|
89
|
-
};
|
|
90
|
-
stats.push(stat);
|
|
91
|
-
if (errorRate > 0.1) {
|
|
92
|
-
detectedAnomalies.push({
|
|
93
|
-
operation: stat.operation,
|
|
94
|
-
severity: errorRate > 0.3 ? "high" : errorRate > 0.2 ? "medium" : "low",
|
|
95
|
-
metric: "error-rate",
|
|
96
|
-
description: `Error rate ${(errorRate * 100).toFixed(1)}% exceeds threshold`,
|
|
97
|
-
detectedAt: new Date,
|
|
98
|
-
threshold: 0.1,
|
|
99
|
-
observedValue: errorRate
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
if (stat.p99LatencyMs > 500) {
|
|
103
|
-
detectedAnomalies.push({
|
|
104
|
-
operation: stat.operation,
|
|
105
|
-
severity: stat.p99LatencyMs > 1000 ? "high" : stat.p99LatencyMs > 750 ? "medium" : "low",
|
|
106
|
-
metric: "latency",
|
|
107
|
-
description: `P99 latency ${stat.p99LatencyMs.toFixed(0)}ms exceeds threshold`,
|
|
108
|
-
detectedAt: new Date,
|
|
109
|
-
threshold: 500,
|
|
110
|
-
observedValue: stat.p99LatencyMs
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
setUsageStats(stats);
|
|
115
|
-
setAnomalies(detectedAnomalies);
|
|
116
|
-
const newHints = detectedAnomalies.map((anomaly) => ({
|
|
117
|
-
operation: anomaly.operation,
|
|
118
|
-
category: anomaly.metric === "latency" ? "performance" : "error-handling",
|
|
119
|
-
summary: anomaly.metric === "latency" ? "Latency regression detected" : "Error spike detected",
|
|
120
|
-
justification: anomaly.description,
|
|
121
|
-
recommendedActions: anomaly.metric === "latency" ? [
|
|
122
|
-
"Add caching layer",
|
|
123
|
-
"Optimize database queries",
|
|
124
|
-
"Consider pagination"
|
|
125
|
-
] : [
|
|
126
|
-
"Add retry logic",
|
|
127
|
-
"Improve error handling",
|
|
128
|
-
"Add circuit breaker"
|
|
129
|
-
]
|
|
130
|
-
}));
|
|
131
|
-
setHints(newHints);
|
|
132
|
-
}, []);
|
|
133
|
-
const generateSuggestions = useCallback(async () => {
|
|
134
|
-
if (anomalies.length === 0)
|
|
135
|
-
return;
|
|
136
|
-
setLoading(true);
|
|
137
|
-
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
138
|
-
const newSuggestions = anomalies.map((anomaly) => ({
|
|
139
|
-
id: `suggestion-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
140
|
-
intent: {
|
|
141
|
-
id: `intent-${anomaly.operation.name}`,
|
|
142
|
-
type: anomaly.metric === "latency" ? "latency-regression" : anomaly.metric === "error-rate" ? "error-spike" : "throughput-drop",
|
|
143
|
-
description: anomaly.description,
|
|
144
|
-
operation: anomaly.operation,
|
|
145
|
-
confidence: {
|
|
146
|
-
score: anomaly.severity === "high" ? 0.9 : anomaly.severity === "medium" ? 0.7 : 0.5,
|
|
147
|
-
sampleSize: usageStats.find((s) => s.operation.name === anomaly.operation.name)?.totalCalls ?? 0
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
target: anomaly.operation,
|
|
151
|
-
proposal: {
|
|
152
|
-
summary: generateSuggestionSummary(anomaly),
|
|
153
|
-
rationale: generateSuggestionRationale(anomaly),
|
|
154
|
-
changeType: anomaly.metric === "error-rate" ? "policy-update" : "revision",
|
|
155
|
-
recommendedActions: generateRecommendedActions(anomaly)
|
|
156
|
-
},
|
|
157
|
-
confidence: anomaly.severity === "high" ? 0.85 : anomaly.severity === "medium" ? 0.7 : 0.55,
|
|
158
|
-
createdAt: new Date,
|
|
159
|
-
createdBy: "ai-evolution-agent",
|
|
160
|
-
status: "pending",
|
|
161
|
-
priority: anomaly.severity
|
|
162
|
-
}));
|
|
163
|
-
setSuggestions((prev) => [...prev, ...newSuggestions]);
|
|
164
|
-
setLoading(false);
|
|
165
|
-
}, [anomalies, usageStats]);
|
|
166
|
-
const approveSuggestion = useCallback((id, _notes) => {
|
|
167
|
-
setSuggestions((prev) => prev.map((s) => s.id === id ? { ...s, status: "approved" } : s));
|
|
168
|
-
}, []);
|
|
169
|
-
const rejectSuggestion = useCallback((id, _notes) => {
|
|
170
|
-
setSuggestions((prev) => prev.map((s) => s.id === id ? { ...s, status: "rejected" } : s));
|
|
171
|
-
}, []);
|
|
172
|
-
const clear = useCallback(() => {
|
|
173
|
-
metricsRef.current = [];
|
|
174
|
-
setOperationCount(0);
|
|
175
|
-
setUsageStats([]);
|
|
176
|
-
setAnomalies([]);
|
|
177
|
-
setSuggestions([]);
|
|
178
|
-
setHints([]);
|
|
179
|
-
localStorage.removeItem(`${EVOLUTION_STORAGE_KEY}-${templateId}`);
|
|
180
|
-
}, [templateId]);
|
|
181
|
-
return useMemo(() => ({
|
|
182
|
-
usageStats,
|
|
183
|
-
anomalies,
|
|
184
|
-
suggestions,
|
|
185
|
-
hints,
|
|
186
|
-
loading,
|
|
187
|
-
trackOperation,
|
|
188
|
-
analyzeUsage,
|
|
189
|
-
generateSuggestions,
|
|
190
|
-
approveSuggestion,
|
|
191
|
-
rejectSuggestion,
|
|
192
|
-
clear,
|
|
193
|
-
operationCount
|
|
194
|
-
}), [
|
|
195
|
-
usageStats,
|
|
196
|
-
anomalies,
|
|
197
|
-
suggestions,
|
|
198
|
-
hints,
|
|
199
|
-
loading,
|
|
200
|
-
trackOperation,
|
|
201
|
-
analyzeUsage,
|
|
202
|
-
generateSuggestions,
|
|
203
|
-
approveSuggestion,
|
|
204
|
-
rejectSuggestion,
|
|
205
|
-
clear,
|
|
206
|
-
operationCount
|
|
207
|
-
]);
|
|
208
|
-
}
|
|
209
|
-
function percentile(values, p) {
|
|
210
|
-
if (!values.length)
|
|
211
|
-
return 0;
|
|
212
|
-
if (values.length === 1)
|
|
213
|
-
return values[0] ?? 0;
|
|
214
|
-
const idx = Math.min(values.length - 1, Math.floor(p * values.length));
|
|
215
|
-
return values[idx] ?? 0;
|
|
216
|
-
}
|
|
217
|
-
function generateSuggestionSummary(anomaly) {
|
|
218
|
-
if (anomaly.metric === "latency") {
|
|
219
|
-
return `Add caching and pagination to ${anomaly.operation.name} to reduce latency`;
|
|
220
|
-
}
|
|
221
|
-
if (anomaly.metric === "error-rate") {
|
|
222
|
-
return `Add retry policy and circuit breaker to ${anomaly.operation.name}`;
|
|
223
|
-
}
|
|
224
|
-
return `Optimize ${anomaly.operation.name} for improved throughput`;
|
|
225
|
-
}
|
|
226
|
-
function generateSuggestionRationale(anomaly) {
|
|
227
|
-
if (anomaly.metric === "latency") {
|
|
228
|
-
return `The operation ${anomaly.operation.name} is experiencing P99 latency of ${anomaly.observedValue?.toFixed(0)}ms, which is above the recommended threshold of ${anomaly.threshold}ms. This can impact user experience and downstream operations.`;
|
|
229
|
-
}
|
|
230
|
-
if (anomaly.metric === "error-rate") {
|
|
231
|
-
return `The error rate for ${anomaly.operation.name} is ${((anomaly.observedValue ?? 0) * 100).toFixed(1)}%, indicating potential issues with input validation, external dependencies, or resource limits.`;
|
|
232
|
-
}
|
|
233
|
-
return `Throughput for ${anomaly.operation.name} has dropped significantly, suggesting potential bottlenecks or reduced demand that should be investigated.`;
|
|
234
|
-
}
|
|
235
|
-
function generateRecommendedActions(anomaly) {
|
|
236
|
-
if (anomaly.metric === "latency") {
|
|
237
|
-
return [
|
|
238
|
-
"Add response caching for frequently accessed data",
|
|
239
|
-
"Implement pagination for large result sets",
|
|
240
|
-
"Optimize database queries with proper indexing",
|
|
241
|
-
"Consider adding a GraphQL DataLoader for batching"
|
|
242
|
-
];
|
|
243
|
-
}
|
|
244
|
-
if (anomaly.metric === "error-rate") {
|
|
245
|
-
return [
|
|
246
|
-
"Add input validation at the contract level",
|
|
247
|
-
"Implement retry policy with exponential backoff",
|
|
248
|
-
"Add circuit breaker for external dependencies",
|
|
249
|
-
"Enhance error logging for better debugging"
|
|
250
|
-
];
|
|
251
|
-
}
|
|
252
|
-
return [
|
|
253
|
-
"Review resource allocation and scaling policies",
|
|
254
|
-
"Check for upstream routing or load balancer issues",
|
|
255
|
-
"Validate feature flag configurations",
|
|
256
|
-
"Monitor dependency health metrics"
|
|
257
|
-
];
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// src/EvolutionDashboard.tsx
|
|
261
|
-
import { Button, LoaderBlock } from "@contractspec/lib.design-system";
|
|
262
|
-
import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
|
|
263
|
-
import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
|
|
264
|
-
import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
265
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
266
|
-
"use client";
|
|
267
|
-
function EvolutionDashboard({
|
|
268
|
-
templateId,
|
|
269
|
-
onLog
|
|
270
|
-
}) {
|
|
271
|
-
const {
|
|
272
|
-
usageStats,
|
|
273
|
-
anomalies,
|
|
274
|
-
suggestions,
|
|
275
|
-
hints,
|
|
276
|
-
loading,
|
|
277
|
-
trackOperation,
|
|
278
|
-
analyzeUsage,
|
|
279
|
-
generateSuggestions,
|
|
280
|
-
approveSuggestion,
|
|
281
|
-
rejectSuggestion,
|
|
282
|
-
clear,
|
|
283
|
-
operationCount
|
|
284
|
-
} = useEvolution(templateId);
|
|
285
|
-
const handleSimulateOperations = useCallback2(() => {
|
|
286
|
-
const operations = [
|
|
287
|
-
{ name: `${templateId}.list`, duration: 150, success: true },
|
|
288
|
-
{ name: `${templateId}.list`, duration: 180, success: true },
|
|
289
|
-
{ name: `${templateId}.create`, duration: 350, success: true },
|
|
290
|
-
{
|
|
291
|
-
name: `${templateId}.create`,
|
|
292
|
-
duration: 420,
|
|
293
|
-
success: false,
|
|
294
|
-
error: "VALIDATION_ERROR"
|
|
295
|
-
},
|
|
296
|
-
{ name: `${templateId}.list`, duration: 200, success: true },
|
|
297
|
-
{ name: `${templateId}.get`, duration: 80, success: true },
|
|
298
|
-
{ name: `${templateId}.update`, duration: 280, success: true },
|
|
299
|
-
{ name: `${templateId}.list`, duration: 950, success: true },
|
|
300
|
-
{
|
|
301
|
-
name: `${templateId}.delete`,
|
|
302
|
-
duration: 150,
|
|
303
|
-
success: false,
|
|
304
|
-
error: "NOT_FOUND"
|
|
305
|
-
},
|
|
306
|
-
{ name: `${templateId}.create`, duration: 380, success: true }
|
|
307
|
-
];
|
|
308
|
-
for (const op of operations) {
|
|
309
|
-
trackOperation(op.name, op.duration, op.success, op.error);
|
|
310
|
-
}
|
|
311
|
-
onLog?.(`Simulated ${operations.length} operations`);
|
|
312
|
-
setTimeout(() => {
|
|
313
|
-
analyzeUsage();
|
|
314
|
-
onLog?.("Analysis complete");
|
|
315
|
-
}, 100);
|
|
316
|
-
}, [templateId, trackOperation, analyzeUsage, onLog]);
|
|
317
|
-
const handleGenerateSuggestions = useCallback2(async () => {
|
|
318
|
-
await generateSuggestions();
|
|
319
|
-
onLog?.("AI suggestions generated");
|
|
320
|
-
}, [generateSuggestions, onLog]);
|
|
321
|
-
const handleApproveSuggestion = useCallback2((id) => {
|
|
322
|
-
approveSuggestion(id);
|
|
323
|
-
onLog?.(`Suggestion ${id.slice(0, 8)} approved`);
|
|
324
|
-
}, [approveSuggestion, onLog]);
|
|
325
|
-
const handleRejectSuggestion = useCallback2((id) => {
|
|
326
|
-
rejectSuggestion(id);
|
|
327
|
-
onLog?.(`Suggestion ${id.slice(0, 8)} rejected`);
|
|
328
|
-
}, [rejectSuggestion, onLog]);
|
|
329
|
-
const handleClear = useCallback2(() => {
|
|
330
|
-
clear();
|
|
331
|
-
onLog?.("Evolution data cleared");
|
|
332
|
-
}, [clear, onLog]);
|
|
333
|
-
const pendingSuggestions = useMemo2(() => suggestions.filter((s) => s.status === "pending"), [suggestions]);
|
|
334
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
335
|
-
className: "space-y-6",
|
|
336
|
-
children: [
|
|
337
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
338
|
-
className: "flex items-center justify-between",
|
|
339
|
-
children: [
|
|
340
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
341
|
-
children: [
|
|
342
|
-
/* @__PURE__ */ jsxDEV("h2", {
|
|
343
|
-
className: "font-semibold text-xl",
|
|
344
|
-
children: "AI Evolution Engine"
|
|
345
|
-
}, undefined, false, undefined, this),
|
|
346
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
347
|
-
className: "text-muted-foreground text-sm",
|
|
348
|
-
children: "Analyze usage patterns and get AI-powered suggestions"
|
|
349
|
-
}, undefined, false, undefined, this)
|
|
350
|
-
]
|
|
351
|
-
}, undefined, true, undefined, this),
|
|
352
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
353
|
-
className: "flex items-center gap-2",
|
|
354
|
-
children: [
|
|
355
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
356
|
-
variant: "secondary",
|
|
357
|
-
children: [
|
|
358
|
-
operationCount,
|
|
359
|
-
" ops tracked"
|
|
360
|
-
]
|
|
361
|
-
}, undefined, true, undefined, this),
|
|
362
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
363
|
-
variant: "ghost",
|
|
364
|
-
size: "sm",
|
|
365
|
-
onPress: handleClear,
|
|
366
|
-
children: "Clear"
|
|
367
|
-
}, undefined, false, undefined, this)
|
|
368
|
-
]
|
|
369
|
-
}, undefined, true, undefined, this)
|
|
370
|
-
]
|
|
371
|
-
}, undefined, true, undefined, this),
|
|
372
|
-
/* @__PURE__ */ jsxDEV(Card, {
|
|
373
|
-
className: "p-4",
|
|
374
|
-
children: [
|
|
375
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
376
|
-
className: "flex flex-wrap items-center gap-3",
|
|
377
|
-
children: [
|
|
378
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
379
|
-
variant: "default",
|
|
380
|
-
size: "sm",
|
|
381
|
-
onPress: handleSimulateOperations,
|
|
382
|
-
children: "Simulate Operations"
|
|
383
|
-
}, undefined, false, undefined, this),
|
|
384
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
385
|
-
variant: "outline",
|
|
386
|
-
size: "sm",
|
|
387
|
-
onPress: analyzeUsage,
|
|
388
|
-
disabled: operationCount < 5,
|
|
389
|
-
children: "Analyze Usage"
|
|
390
|
-
}, undefined, false, undefined, this),
|
|
391
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
392
|
-
variant: "outline",
|
|
393
|
-
size: "sm",
|
|
394
|
-
onPress: handleGenerateSuggestions,
|
|
395
|
-
disabled: anomalies.length === 0 || loading,
|
|
396
|
-
children: loading ? "Generating..." : "Generate AI Suggestions"
|
|
397
|
-
}, undefined, false, undefined, this)
|
|
398
|
-
]
|
|
399
|
-
}, undefined, true, undefined, this),
|
|
400
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
401
|
-
className: "mt-2 text-muted-foreground text-xs",
|
|
402
|
-
children: "Simulate sandbox operations, analyze patterns, and generate AI improvement suggestions."
|
|
403
|
-
}, undefined, false, undefined, this)
|
|
404
|
-
]
|
|
405
|
-
}, undefined, true, undefined, this),
|
|
406
|
-
loading && /* @__PURE__ */ jsxDEV(LoaderBlock, {
|
|
407
|
-
label: "Generating AI suggestions..."
|
|
408
|
-
}, undefined, false, undefined, this),
|
|
409
|
-
usageStats.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
|
|
410
|
-
className: "p-4",
|
|
411
|
-
children: [
|
|
412
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
413
|
-
className: "mb-3 font-semibold",
|
|
414
|
-
children: "Usage Statistics"
|
|
415
|
-
}, undefined, false, undefined, this),
|
|
416
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
417
|
-
className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3",
|
|
418
|
-
children: usageStats.map((stat) => /* @__PURE__ */ jsxDEV(UsageStatCard, {
|
|
419
|
-
stat
|
|
420
|
-
}, stat.operation.name, false, undefined, this))
|
|
421
|
-
}, undefined, false, undefined, this)
|
|
422
|
-
]
|
|
423
|
-
}, undefined, true, undefined, this),
|
|
424
|
-
anomalies.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
|
|
425
|
-
className: "p-4",
|
|
426
|
-
children: [
|
|
427
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
428
|
-
className: "mb-3 flex items-center justify-between",
|
|
429
|
-
children: [
|
|
430
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
431
|
-
className: "font-semibold",
|
|
432
|
-
children: "Detected Anomalies"
|
|
433
|
-
}, undefined, false, undefined, this),
|
|
434
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
435
|
-
variant: "secondary",
|
|
436
|
-
className: "border-amber-500/30 bg-amber-500/20 text-amber-400",
|
|
437
|
-
children: [
|
|
438
|
-
anomalies.length,
|
|
439
|
-
" issues"
|
|
440
|
-
]
|
|
441
|
-
}, undefined, true, undefined, this)
|
|
442
|
-
]
|
|
443
|
-
}, undefined, true, undefined, this),
|
|
444
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
445
|
-
className: "space-y-2",
|
|
446
|
-
children: anomalies.map((anomaly, index) => /* @__PURE__ */ jsxDEV(AnomalyCard, {
|
|
447
|
-
anomaly
|
|
448
|
-
}, `${anomaly.operation.name}-${index}`, false, undefined, this))
|
|
449
|
-
}, undefined, false, undefined, this)
|
|
450
|
-
]
|
|
451
|
-
}, undefined, true, undefined, this),
|
|
452
|
-
suggestions.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
|
|
453
|
-
className: "p-4",
|
|
454
|
-
children: [
|
|
455
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
456
|
-
className: "mb-3 flex items-center justify-between",
|
|
457
|
-
children: [
|
|
458
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
459
|
-
className: "font-semibold",
|
|
460
|
-
children: "AI Suggestions"
|
|
461
|
-
}, undefined, false, undefined, this),
|
|
462
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
463
|
-
className: "flex items-center gap-2",
|
|
464
|
-
children: pendingSuggestions.length > 0 && /* @__PURE__ */ jsxDEV(Badge, {
|
|
465
|
-
variant: "secondary",
|
|
466
|
-
className: "border-amber-500/30 bg-amber-500/20 text-amber-400",
|
|
467
|
-
children: [
|
|
468
|
-
pendingSuggestions.length,
|
|
469
|
-
" pending"
|
|
470
|
-
]
|
|
471
|
-
}, undefined, true, undefined, this)
|
|
472
|
-
}, undefined, false, undefined, this)
|
|
473
|
-
]
|
|
474
|
-
}, undefined, true, undefined, this),
|
|
475
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
476
|
-
className: "space-y-3",
|
|
477
|
-
children: suggestions.map((suggestion) => /* @__PURE__ */ jsxDEV(SuggestionCard, {
|
|
478
|
-
suggestion,
|
|
479
|
-
onApprove: handleApproveSuggestion,
|
|
480
|
-
onReject: handleRejectSuggestion
|
|
481
|
-
}, suggestion.id, false, undefined, this))
|
|
482
|
-
}, undefined, false, undefined, this)
|
|
483
|
-
]
|
|
484
|
-
}, undefined, true, undefined, this),
|
|
485
|
-
hints.length > 0 && /* @__PURE__ */ jsxDEV(Card, {
|
|
486
|
-
className: "p-4",
|
|
487
|
-
children: [
|
|
488
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
489
|
-
className: "mb-3 font-semibold",
|
|
490
|
-
children: "Optimization Hints"
|
|
491
|
-
}, undefined, false, undefined, this),
|
|
492
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
493
|
-
className: "space-y-2",
|
|
494
|
-
children: hints.map((hint, index) => /* @__PURE__ */ jsxDEV(HintCard, {
|
|
495
|
-
hint
|
|
496
|
-
}, `${hint.operation.name}-${index}`, false, undefined, this))
|
|
497
|
-
}, undefined, false, undefined, this)
|
|
498
|
-
]
|
|
499
|
-
}, undefined, true, undefined, this),
|
|
500
|
-
usageStats.length === 0 && anomalies.length === 0 && suggestions.length === 0 && /* @__PURE__ */ jsxDEV(Card, {
|
|
501
|
-
className: "p-8 text-center",
|
|
502
|
-
children: /* @__PURE__ */ jsxDEV("p", {
|
|
503
|
-
className: "text-muted-foreground",
|
|
504
|
-
children: 'Click "Simulate Operations" to generate sample data for analysis.'
|
|
505
|
-
}, undefined, false, undefined, this)
|
|
506
|
-
}, undefined, false, undefined, this)
|
|
507
|
-
]
|
|
508
|
-
}, undefined, true, undefined, this);
|
|
509
|
-
}
|
|
510
|
-
function UsageStatCard({ stat }) {
|
|
511
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
512
|
-
className: "rounded-lg border border-violet-500/20 bg-violet-500/5 p-3",
|
|
513
|
-
children: [
|
|
514
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
515
|
-
className: "mb-2 flex items-center justify-between",
|
|
516
|
-
children: [
|
|
517
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
518
|
-
className: "font-medium font-mono text-sm",
|
|
519
|
-
children: stat.operation.name
|
|
520
|
-
}, undefined, false, undefined, this),
|
|
521
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
522
|
-
variant: stat.errorRate > 0.1 ? "destructive" : "default",
|
|
523
|
-
className: stat.errorRate > 0.1 ? "" : "border-green-500/30 bg-green-500/20 text-green-400",
|
|
524
|
-
children: [
|
|
525
|
-
((1 - stat.errorRate) * 100).toFixed(0),
|
|
526
|
-
"% success"
|
|
527
|
-
]
|
|
528
|
-
}, undefined, true, undefined, this)
|
|
529
|
-
]
|
|
530
|
-
}, undefined, true, undefined, this),
|
|
531
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
532
|
-
className: "grid grid-cols-2 gap-2 text-xs",
|
|
533
|
-
children: [
|
|
534
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
535
|
-
children: [
|
|
536
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
537
|
-
className: "text-muted-foreground",
|
|
538
|
-
children: "Total Calls:"
|
|
539
|
-
}, undefined, false, undefined, this),
|
|
540
|
-
" ",
|
|
541
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
542
|
-
className: "font-medium",
|
|
543
|
-
children: stat.totalCalls
|
|
544
|
-
}, undefined, false, undefined, this)
|
|
545
|
-
]
|
|
546
|
-
}, undefined, true, undefined, this),
|
|
547
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
548
|
-
children: [
|
|
549
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
550
|
-
className: "text-muted-foreground",
|
|
551
|
-
children: "Avg Latency:"
|
|
552
|
-
}, undefined, false, undefined, this),
|
|
553
|
-
" ",
|
|
554
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
555
|
-
className: "font-medium",
|
|
556
|
-
children: [
|
|
557
|
-
stat.averageLatencyMs.toFixed(0),
|
|
558
|
-
"ms"
|
|
559
|
-
]
|
|
560
|
-
}, undefined, true, undefined, this)
|
|
561
|
-
]
|
|
562
|
-
}, undefined, true, undefined, this),
|
|
563
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
564
|
-
children: [
|
|
565
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
566
|
-
className: "text-muted-foreground",
|
|
567
|
-
children: "P95:"
|
|
568
|
-
}, undefined, false, undefined, this),
|
|
569
|
-
" ",
|
|
570
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
571
|
-
className: "font-medium",
|
|
572
|
-
children: [
|
|
573
|
-
stat.p95LatencyMs.toFixed(0),
|
|
574
|
-
"ms"
|
|
575
|
-
]
|
|
576
|
-
}, undefined, true, undefined, this)
|
|
577
|
-
]
|
|
578
|
-
}, undefined, true, undefined, this),
|
|
579
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
580
|
-
children: [
|
|
581
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
582
|
-
className: "text-muted-foreground",
|
|
583
|
-
children: "P99:"
|
|
584
|
-
}, undefined, false, undefined, this),
|
|
585
|
-
" ",
|
|
586
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
587
|
-
className: "font-medium",
|
|
588
|
-
children: [
|
|
589
|
-
stat.p99LatencyMs.toFixed(0),
|
|
590
|
-
"ms"
|
|
591
|
-
]
|
|
592
|
-
}, undefined, true, undefined, this)
|
|
593
|
-
]
|
|
594
|
-
}, undefined, true, undefined, this)
|
|
595
|
-
]
|
|
596
|
-
}, undefined, true, undefined, this)
|
|
597
|
-
]
|
|
598
|
-
}, undefined, true, undefined, this);
|
|
599
|
-
}
|
|
600
|
-
function AnomalyCard({ anomaly }) {
|
|
601
|
-
const severityColors = {
|
|
602
|
-
low: "text-amber-400",
|
|
603
|
-
medium: "text-orange-400",
|
|
604
|
-
high: "text-red-400"
|
|
605
|
-
};
|
|
606
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
607
|
-
className: "flex items-center justify-between rounded-lg border border-amber-500/30 bg-amber-500/5 p-3",
|
|
608
|
-
children: [
|
|
609
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
610
|
-
className: "flex items-center gap-3",
|
|
611
|
-
children: [
|
|
612
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
613
|
-
className: `text-lg ${severityColors[anomaly.severity]}`,
|
|
614
|
-
title: `${anomaly.severity} severity`,
|
|
615
|
-
children: anomaly.severity === "high" ? "\uD83D\uDD34" : anomaly.severity === "medium" ? "\uD83D\uDFE0" : "\uD83D\uDFE1"
|
|
616
|
-
}, undefined, false, undefined, this),
|
|
617
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
618
|
-
children: [
|
|
619
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
620
|
-
className: "font-medium text-sm",
|
|
621
|
-
children: anomaly.description
|
|
622
|
-
}, undefined, false, undefined, this),
|
|
623
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
624
|
-
className: "text-muted-foreground text-xs",
|
|
625
|
-
children: [
|
|
626
|
-
anomaly.operation.name,
|
|
627
|
-
" \u2022 ",
|
|
628
|
-
anomaly.metric
|
|
629
|
-
]
|
|
630
|
-
}, undefined, true, undefined, this)
|
|
631
|
-
]
|
|
632
|
-
}, undefined, true, undefined, this)
|
|
633
|
-
]
|
|
634
|
-
}, undefined, true, undefined, this),
|
|
635
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
636
|
-
variant: anomaly.severity === "high" ? "destructive" : "secondary",
|
|
637
|
-
className: anomaly.severity === "medium" ? "border-amber-500/30 bg-amber-500/20 text-amber-400" : "",
|
|
638
|
-
children: anomaly.severity
|
|
639
|
-
}, undefined, false, undefined, this)
|
|
640
|
-
]
|
|
641
|
-
}, undefined, true, undefined, this);
|
|
642
|
-
}
|
|
643
|
-
function SuggestionCard({
|
|
644
|
-
suggestion,
|
|
645
|
-
onApprove,
|
|
646
|
-
onReject
|
|
647
|
-
}) {
|
|
648
|
-
const getStatusStyles = (status) => {
|
|
649
|
-
switch (status) {
|
|
650
|
-
case "pending":
|
|
651
|
-
return {
|
|
652
|
-
variant: "secondary",
|
|
653
|
-
className: "bg-amber-500/20 text-amber-400 border-amber-500/30"
|
|
654
|
-
};
|
|
655
|
-
case "approved":
|
|
656
|
-
return {
|
|
657
|
-
variant: "default",
|
|
658
|
-
className: "bg-green-500/20 text-green-400 border-green-500/30"
|
|
659
|
-
};
|
|
660
|
-
case "rejected":
|
|
661
|
-
return { variant: "destructive", className: "" };
|
|
662
|
-
default:
|
|
663
|
-
return { variant: "secondary", className: "" };
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
const statusStyle = getStatusStyles(suggestion.status);
|
|
667
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
668
|
-
className: "rounded-lg border border-violet-500/30 bg-violet-500/5 p-4",
|
|
669
|
-
children: [
|
|
670
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
671
|
-
className: "mb-2 flex items-start justify-between",
|
|
672
|
-
children: [
|
|
673
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
674
|
-
className: "flex-1",
|
|
675
|
-
children: [
|
|
676
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
677
|
-
className: "flex items-center gap-2",
|
|
678
|
-
children: [
|
|
679
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
680
|
-
className: "text-lg",
|
|
681
|
-
children: suggestion.intent.type === "latency-regression" ? "\u26A1" : suggestion.intent.type === "error-spike" ? "\uD83D\uDD25" : "\uD83D\uDCC9"
|
|
682
|
-
}, undefined, false, undefined, this),
|
|
683
|
-
/* @__PURE__ */ jsxDEV("h4", {
|
|
684
|
-
className: "font-medium",
|
|
685
|
-
children: suggestion.proposal.summary
|
|
686
|
-
}, undefined, false, undefined, this)
|
|
687
|
-
]
|
|
688
|
-
}, undefined, true, undefined, this),
|
|
689
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
690
|
-
className: "mt-1 text-muted-foreground text-sm",
|
|
691
|
-
children: suggestion.proposal.rationale
|
|
692
|
-
}, undefined, false, undefined, this)
|
|
693
|
-
]
|
|
694
|
-
}, undefined, true, undefined, this),
|
|
695
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
696
|
-
variant: statusStyle.variant,
|
|
697
|
-
className: statusStyle.className,
|
|
698
|
-
children: suggestion.status
|
|
699
|
-
}, undefined, false, undefined, this)
|
|
700
|
-
]
|
|
701
|
-
}, undefined, true, undefined, this),
|
|
702
|
-
suggestion.proposal.recommendedActions && suggestion.proposal.recommendedActions.length > 0 && /* @__PURE__ */ jsxDEV("div", {
|
|
703
|
-
className: "mt-3",
|
|
704
|
-
children: [
|
|
705
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
706
|
-
className: "mb-1 font-semibold text-violet-400 text-xs uppercase",
|
|
707
|
-
children: "Recommended Actions"
|
|
708
|
-
}, undefined, false, undefined, this),
|
|
709
|
-
/* @__PURE__ */ jsxDEV("ul", {
|
|
710
|
-
className: "list-inside list-disc space-y-1 text-xs",
|
|
711
|
-
children: suggestion.proposal.recommendedActions.slice(0, 3).map((action, i) => /* @__PURE__ */ jsxDEV("li", {
|
|
712
|
-
children: action
|
|
713
|
-
}, i, false, undefined, this))
|
|
714
|
-
}, undefined, false, undefined, this)
|
|
715
|
-
]
|
|
716
|
-
}, undefined, true, undefined, this),
|
|
717
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
718
|
-
className: "mt-3 flex items-center justify-between",
|
|
719
|
-
children: [
|
|
720
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
721
|
-
className: "flex items-center gap-2 text-xs",
|
|
722
|
-
children: [
|
|
723
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
724
|
-
className: "text-muted-foreground",
|
|
725
|
-
children: [
|
|
726
|
-
"Confidence: ",
|
|
727
|
-
(suggestion.confidence * 100).toFixed(0),
|
|
728
|
-
"%"
|
|
729
|
-
]
|
|
730
|
-
}, undefined, true, undefined, this),
|
|
731
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
732
|
-
className: "text-muted-foreground",
|
|
733
|
-
children: "\u2022"
|
|
734
|
-
}, undefined, false, undefined, this),
|
|
735
|
-
/* @__PURE__ */ jsxDEV(Badge, {
|
|
736
|
-
variant: "secondary",
|
|
737
|
-
children: suggestion.priority
|
|
738
|
-
}, undefined, false, undefined, this)
|
|
739
|
-
]
|
|
740
|
-
}, undefined, true, undefined, this),
|
|
741
|
-
suggestion.status === "pending" && /* @__PURE__ */ jsxDEV("div", {
|
|
742
|
-
className: "flex items-center gap-2",
|
|
743
|
-
children: [
|
|
744
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
745
|
-
variant: "outline",
|
|
746
|
-
size: "sm",
|
|
747
|
-
onPress: () => onReject(suggestion.id),
|
|
748
|
-
children: "Reject"
|
|
749
|
-
}, undefined, false, undefined, this),
|
|
750
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
751
|
-
variant: "default",
|
|
752
|
-
size: "sm",
|
|
753
|
-
onPress: () => onApprove(suggestion.id),
|
|
754
|
-
children: "Approve"
|
|
755
|
-
}, undefined, false, undefined, this)
|
|
756
|
-
]
|
|
757
|
-
}, undefined, true, undefined, this)
|
|
758
|
-
]
|
|
759
|
-
}, undefined, true, undefined, this)
|
|
760
|
-
]
|
|
761
|
-
}, undefined, true, undefined, this);
|
|
762
|
-
}
|
|
763
|
-
function HintCard({ hint }) {
|
|
764
|
-
const categoryIcons = {
|
|
765
|
-
schema: "\uD83D\uDCD0",
|
|
766
|
-
policy: "\uD83D\uDD12",
|
|
767
|
-
performance: "\u26A1",
|
|
768
|
-
"error-handling": "\uD83D\uDEE1\uFE0F"
|
|
769
|
-
};
|
|
770
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
771
|
-
className: "rounded-lg border border-blue-500/20 bg-blue-500/5 p-3",
|
|
772
|
-
children: /* @__PURE__ */ jsxDEV("div", {
|
|
773
|
-
className: "flex items-start gap-3",
|
|
774
|
-
children: [
|
|
775
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
776
|
-
className: "text-lg",
|
|
777
|
-
children: categoryIcons[hint.category]
|
|
778
|
-
}, undefined, false, undefined, this),
|
|
779
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
780
|
-
className: "flex-1",
|
|
781
|
-
children: [
|
|
782
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
783
|
-
className: "font-medium",
|
|
784
|
-
children: hint.summary
|
|
785
|
-
}, undefined, false, undefined, this),
|
|
786
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
787
|
-
className: "mt-1 text-muted-foreground text-xs",
|
|
788
|
-
children: hint.justification
|
|
789
|
-
}, undefined, false, undefined, this),
|
|
790
|
-
hint.recommendedActions.length > 0 && /* @__PURE__ */ jsxDEV("ul", {
|
|
791
|
-
className: "mt-2 list-inside list-disc text-xs",
|
|
792
|
-
children: hint.recommendedActions.slice(0, 2).map((action, i) => /* @__PURE__ */ jsxDEV("li", {
|
|
793
|
-
children: action
|
|
794
|
-
}, i, false, undefined, this))
|
|
795
|
-
}, undefined, false, undefined, this)
|
|
796
|
-
]
|
|
797
|
-
}, undefined, true, undefined, this)
|
|
798
|
-
]
|
|
799
|
-
}, undefined, true, undefined, this)
|
|
800
|
-
}, undefined, false, undefined, this);
|
|
801
|
-
}
|
|
802
|
-
export {
|
|
803
|
-
EvolutionDashboard
|
|
804
|
-
};
|
|
2
|
+
import{useCallback as U,useEffect as i,useMemo as n,useRef as o,useState as E}from"react";var r="contractspec-evolution-data";function g(q){let[Q,K]=E([]),[X,V]=E([]),[Y,G]=E([]),[A,_]=E([]),[O,R]=E(!1),f=o([]),[k,h]=E(0);i(()=>{try{let P=localStorage.getItem(`${r}-${q}`);if(P){let J=JSON.parse(P);G(J.suggestions.map(($)=>({...$,createdAt:new Date($.createdAt)})))}}catch{}},[q]),i(()=>{try{localStorage.setItem(`${r}-${q}`,JSON.stringify({suggestions:Y}))}catch{}},[Y,q]);let I=U((P,J,$,Z)=>{let d={operation:{name:P,version:"1.0.0",tenantId:"sandbox"},durationMs:J,success:$,timestamp:new Date,errorCode:Z};f.current.push(d),h((W)=>W+1)},[]),S=U(()=>{let P=f.current;if(P.length<5)return;let J=new Map;for(let W of P){let z=`${W.operation.name}.v${W.operation.version}`,C=J.get(z)??[];C.push(W),J.set(z,C)}let $=[],Z=[];J.forEach((W)=>{if(W.length<3)return;let z=W.map((w)=>w.durationMs).sort((w,N)=>w-N),C=W.filter((w)=>!w.success),y=W.length,M=C.length/y,l=z.reduce((w,N)=>w+N,0)/y,p=W.map((w)=>w.timestamp.getTime()),u=W[0];if(!u)return;let H={operation:u.operation,totalCalls:y,successRate:1-M,errorRate:M,averageLatencyMs:l,p95LatencyMs:m(z,0.95),p99LatencyMs:m(z,0.99),maxLatencyMs:Math.max(...z),lastSeenAt:new Date(Math.max(...p)),windowStart:new Date(Math.min(...p)),windowEnd:new Date(Math.max(...p)),topErrors:C.reduce((w,N)=>{if(N.errorCode)w[N.errorCode]=(w[N.errorCode]??0)+1;return w},{})};if($.push(H),M>0.1)Z.push({operation:H.operation,severity:M>0.3?"high":M>0.2?"medium":"low",metric:"error-rate",description:`Error rate ${(M*100).toFixed(1)}% exceeds threshold`,detectedAt:new Date,threshold:0.1,observedValue:M});if(H.p99LatencyMs>500)Z.push({operation:H.operation,severity:H.p99LatencyMs>1000?"high":H.p99LatencyMs>750?"medium":"low",metric:"latency",description:`P99 latency ${H.p99LatencyMs.toFixed(0)}ms exceeds threshold`,detectedAt:new Date,threshold:500,observedValue:H.p99LatencyMs})}),K($),V(Z);let d=Z.map((W)=>({operation:W.operation,category:W.metric==="latency"?"performance":"error-handling",summary:W.metric==="latency"?"Latency regression detected":"Error spike detected",justification:W.description,recommendedActions:W.metric==="latency"?["Add caching layer","Optimize database queries","Consider pagination"]:["Add retry logic","Improve error handling","Add circuit breaker"]}));_(d)},[]),c=U(async()=>{if(X.length===0)return;R(!0),await new Promise((J)=>setTimeout(J,800));let P=X.map((J)=>({id:`suggestion-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,intent:{id:`intent-${J.operation.name}`,type:J.metric==="latency"?"latency-regression":J.metric==="error-rate"?"error-spike":"throughput-drop",description:J.description,operation:J.operation,confidence:{score:J.severity==="high"?0.9:J.severity==="medium"?0.7:0.5,sampleSize:Q.find(($)=>$.operation.name===J.operation.name)?.totalCalls??0}},target:J.operation,proposal:{summary:t(J),rationale:e(J),changeType:J.metric==="error-rate"?"policy-update":"revision",recommendedActions:s(J)},confidence:J.severity==="high"?0.85:J.severity==="medium"?0.7:0.55,createdAt:new Date,createdBy:"ai-evolution-agent",status:"pending",priority:J.severity}));G((J)=>[...J,...P]),R(!1)},[X,Q]),x=U((P,J)=>{G(($)=>$.map((Z)=>Z.id===P?{...Z,status:"approved"}:Z))},[]),j=U((P,J)=>{G(($)=>$.map((Z)=>Z.id===P?{...Z,status:"rejected"}:Z))},[]),L=U(()=>{f.current=[],h(0),K([]),V([]),G([]),_([]),localStorage.removeItem(`${r}-${q}`)},[q]);return n(()=>({usageStats:Q,anomalies:X,suggestions:Y,hints:A,loading:O,trackOperation:I,analyzeUsage:S,generateSuggestions:c,approveSuggestion:x,rejectSuggestion:j,clear:L,operationCount:k}),[Q,X,Y,A,O,I,S,c,x,j,L,k])}function m(q,Q){if(!q.length)return 0;if(q.length===1)return q[0]??0;let K=Math.min(q.length-1,Math.floor(Q*q.length));return q[K]??0}function t(q){if(q.metric==="latency")return`Add caching and pagination to ${q.operation.name} to reduce latency`;if(q.metric==="error-rate")return`Add retry policy and circuit breaker to ${q.operation.name}`;return`Optimize ${q.operation.name} for improved throughput`}function e(q){if(q.metric==="latency")return`The operation ${q.operation.name} is experiencing P99 latency of ${q.observedValue?.toFixed(0)}ms, which is above the recommended threshold of ${q.threshold}ms. This can impact user experience and downstream operations.`;if(q.metric==="error-rate")return`The error rate for ${q.operation.name} is ${((q.observedValue??0)*100).toFixed(1)}%, indicating potential issues with input validation, external dependencies, or resource limits.`;return`Throughput for ${q.operation.name} has dropped significantly, suggesting potential bottlenecks or reduced demand that should be investigated.`}function s(q){if(q.metric==="latency")return["Add response caching for frequently accessed data","Implement pagination for large result sets","Optimize database queries with proper indexing","Consider adding a GraphQL DataLoader for batching"];if(q.metric==="error-rate")return["Add input validation at the contract level","Implement retry policy with exponential backoff","Add circuit breaker for external dependencies","Enhance error logging for better debugging"];return["Review resource allocation and scaling policies","Check for upstream routing or load balancer issues","Validate feature flag configurations","Monitor dependency health metrics"]}import{Button as b,LoaderBlock as a}from"@contractspec/lib.design-system";import{Badge as T}from"@contractspec/lib.ui-kit-web/ui/badge";import{Card as B}from"@contractspec/lib.ui-kit-web/ui/card";import{useCallback as v,useMemo as qq}from"react";import{jsx as D,jsxs as F}from"react/jsx-runtime";function Vq({templateId:q,onLog:Q}){let{usageStats:K,anomalies:X,suggestions:V,hints:Y,loading:G,trackOperation:A,analyzeUsage:_,generateSuggestions:O,approveSuggestion:R,rejectSuggestion:f,clear:k,operationCount:h}=g(q),I=v(()=>{let P=[{name:`${q}.list`,duration:150,success:!0},{name:`${q}.list`,duration:180,success:!0},{name:`${q}.create`,duration:350,success:!0},{name:`${q}.create`,duration:420,success:!1,error:"VALIDATION_ERROR"},{name:`${q}.list`,duration:200,success:!0},{name:`${q}.get`,duration:80,success:!0},{name:`${q}.update`,duration:280,success:!0},{name:`${q}.list`,duration:950,success:!0},{name:`${q}.delete`,duration:150,success:!1,error:"NOT_FOUND"},{name:`${q}.create`,duration:380,success:!0}];for(let J of P)A(J.name,J.duration,J.success,J.error);Q?.(`Simulated ${P.length} operations`),setTimeout(()=>{_(),Q?.("Analysis complete")},100)},[q,A,_,Q]),S=v(async()=>{await O(),Q?.("AI suggestions generated")},[O,Q]),c=v((P)=>{R(P),Q?.(`Suggestion ${P.slice(0,8)} approved`)},[R,Q]),x=v((P)=>{f(P),Q?.(`Suggestion ${P.slice(0,8)} rejected`)},[f,Q]),j=v(()=>{k(),Q?.("Evolution data cleared")},[k,Q]),L=qq(()=>V.filter((P)=>P.status==="pending"),[V]);return F("div",{className:"space-y-6",children:[F("div",{className:"flex items-center justify-between",children:[F("div",{children:[D("h2",{className:"font-semibold text-xl",children:"AI Evolution Engine"}),D("p",{className:"text-muted-foreground text-sm",children:"Analyze usage patterns and get AI-powered suggestions"})]}),F("div",{className:"flex items-center gap-2",children:[F(T,{variant:"secondary",children:[h," ops tracked"]}),D(b,{variant:"ghost",size:"sm",onPress:j,children:"Clear"})]})]}),F(B,{className:"p-4",children:[F("div",{className:"flex flex-wrap items-center gap-3",children:[D(b,{variant:"default",size:"sm",onPress:I,children:"Simulate Operations"}),D(b,{variant:"outline",size:"sm",onPress:_,disabled:h<5,children:"Analyze Usage"}),D(b,{variant:"outline",size:"sm",onPress:S,disabled:X.length===0||G,children:G?"Generating...":"Generate AI Suggestions"})]}),D("p",{className:"mt-2 text-muted-foreground text-xs",children:"Simulate sandbox operations, analyze patterns, and generate AI improvement suggestions."})]}),G&&D(a,{label:"Generating AI suggestions..."}),K.length>0&&F(B,{className:"p-4",children:[D("h3",{className:"mb-3 font-semibold",children:"Usage Statistics"}),D("div",{className:"grid gap-3 md:grid-cols-2 lg:grid-cols-3",children:K.map((P)=>D(Dq,{stat:P},P.operation.name))})]}),X.length>0&&F(B,{className:"p-4",children:[F("div",{className:"mb-3 flex items-center justify-between",children:[D("h3",{className:"font-semibold",children:"Detected Anomalies"}),F(T,{variant:"secondary",className:"border-amber-500/30 bg-amber-500/20 text-amber-400",children:[X.length," issues"]})]}),D("div",{className:"space-y-2",children:X.map((P,J)=>D(Fq,{anomaly:P},`${P.operation.name}-${J}`))})]}),V.length>0&&F(B,{className:"p-4",children:[F("div",{className:"mb-3 flex items-center justify-between",children:[D("h3",{className:"font-semibold",children:"AI Suggestions"}),D("div",{className:"flex items-center gap-2",children:L.length>0&&F(T,{variant:"secondary",className:"border-amber-500/30 bg-amber-500/20 text-amber-400",children:[L.length," pending"]})})]}),D("div",{className:"space-y-3",children:V.map((P)=>D(Jq,{suggestion:P,onApprove:c,onReject:x},P.id))})]}),Y.length>0&&F(B,{className:"p-4",children:[D("h3",{className:"mb-3 font-semibold",children:"Optimization Hints"}),D("div",{className:"space-y-2",children:Y.map((P,J)=>D(Pq,{hint:P},`${P.operation.name}-${J}`))})]}),K.length===0&&X.length===0&&V.length===0&&D(B,{className:"p-8 text-center",children:D("p",{className:"text-muted-foreground",children:'Click "Simulate Operations" to generate sample data for analysis.'})})]})}function Dq({stat:q}){return F("div",{className:"rounded-lg border border-violet-500/20 bg-violet-500/5 p-3",children:[F("div",{className:"mb-2 flex items-center justify-between",children:[D("span",{className:"font-medium font-mono text-sm",children:q.operation.name}),F(T,{variant:q.errorRate>0.1?"destructive":"default",className:q.errorRate>0.1?"":"border-green-500/30 bg-green-500/20 text-green-400",children:[((1-q.errorRate)*100).toFixed(0),"% success"]})]}),F("div",{className:"grid grid-cols-2 gap-2 text-xs",children:[F("div",{children:[D("span",{className:"text-muted-foreground",children:"Total Calls:"})," ",D("span",{className:"font-medium",children:q.totalCalls})]}),F("div",{children:[D("span",{className:"text-muted-foreground",children:"Avg Latency:"})," ",F("span",{className:"font-medium",children:[q.averageLatencyMs.toFixed(0),"ms"]})]}),F("div",{children:[D("span",{className:"text-muted-foreground",children:"P95:"})," ",F("span",{className:"font-medium",children:[q.p95LatencyMs.toFixed(0),"ms"]})]}),F("div",{children:[D("span",{className:"text-muted-foreground",children:"P99:"})," ",F("span",{className:"font-medium",children:[q.p99LatencyMs.toFixed(0),"ms"]})]})]})]})}function Fq({anomaly:q}){return F("div",{className:"flex items-center justify-between rounded-lg border border-amber-500/30 bg-amber-500/5 p-3",children:[F("div",{className:"flex items-center gap-3",children:[D("span",{className:`text-lg ${{low:"text-amber-400",medium:"text-orange-400",high:"text-red-400"}[q.severity]}`,title:`${q.severity} severity`,children:q.severity==="high"?"\uD83D\uDD34":q.severity==="medium"?"\uD83D\uDFE0":"\uD83D\uDFE1"}),F("div",{children:[D("p",{className:"font-medium text-sm",children:q.description}),F("p",{className:"text-muted-foreground text-xs",children:[q.operation.name," \u2022 ",q.metric]})]})]}),D(T,{variant:q.severity==="high"?"destructive":"secondary",className:q.severity==="medium"?"border-amber-500/30 bg-amber-500/20 text-amber-400":"",children:q.severity})]})}function Jq({suggestion:q,onApprove:Q,onReject:K}){let V=((Y)=>{switch(Y){case"pending":return{variant:"secondary",className:"bg-amber-500/20 text-amber-400 border-amber-500/30"};case"approved":return{variant:"default",className:"bg-green-500/20 text-green-400 border-green-500/30"};case"rejected":return{variant:"destructive",className:""};default:return{variant:"secondary",className:""}}})(q.status);return F("div",{className:"rounded-lg border border-violet-500/30 bg-violet-500/5 p-4",children:[F("div",{className:"mb-2 flex items-start justify-between",children:[F("div",{className:"flex-1",children:[F("div",{className:"flex items-center gap-2",children:[D("span",{className:"text-lg",children:q.intent.type==="latency-regression"?"\u26A1":q.intent.type==="error-spike"?"\uD83D\uDD25":"\uD83D\uDCC9"}),D("h4",{className:"font-medium",children:q.proposal.summary})]}),D("p",{className:"mt-1 text-muted-foreground text-sm",children:q.proposal.rationale})]}),D(T,{variant:V.variant,className:V.className,children:q.status})]}),q.proposal.recommendedActions&&q.proposal.recommendedActions.length>0&&F("div",{className:"mt-3",children:[D("p",{className:"mb-1 font-semibold text-violet-400 text-xs uppercase",children:"Recommended Actions"}),D("ul",{className:"list-inside list-disc space-y-1 text-xs",children:q.proposal.recommendedActions.slice(0,3).map((Y,G)=>D("li",{children:Y},G))})]}),F("div",{className:"mt-3 flex items-center justify-between",children:[F("div",{className:"flex items-center gap-2 text-xs",children:[F("span",{className:"text-muted-foreground",children:["Confidence: ",(q.confidence*100).toFixed(0),"%"]}),D("span",{className:"text-muted-foreground",children:"\u2022"}),D(T,{variant:"secondary",children:q.priority})]}),q.status==="pending"&&F("div",{className:"flex items-center gap-2",children:[D(b,{variant:"outline",size:"sm",onPress:()=>K(q.id),children:"Reject"}),D(b,{variant:"default",size:"sm",onPress:()=>Q(q.id),children:"Approve"})]})]})]})}function Pq({hint:q}){return D("div",{className:"rounded-lg border border-blue-500/20 bg-blue-500/5 p-3",children:F("div",{className:"flex items-start gap-3",children:[D("span",{className:"text-lg",children:{schema:"\uD83D\uDCD0",policy:"\uD83D\uDD12",performance:"\u26A1","error-handling":"\uD83D\uDEE1\uFE0F"}[q.category]}),F("div",{className:"flex-1",children:[D("p",{className:"font-medium",children:q.summary}),D("p",{className:"mt-1 text-muted-foreground text-xs",children:q.justification}),q.recommendedActions.length>0&&D("ul",{className:"mt-2 list-inside list-disc text-xs",children:q.recommendedActions.slice(0,2).map((K,X)=>D("li",{children:K},X))})]})]})})}export{Vq as EvolutionDashboard};
|