@contractspec/lib.example-shared-ui 1.11.0 → 1.12.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/.turbo/turbo-build.log +86 -11
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +14 -0
- package/dist/EvolutionDashboard.d.ts +11 -0
- package/dist/EvolutionDashboard.d.ts.map +1 -0
- package/dist/EvolutionDashboard.js +804 -0
- package/dist/EvolutionSidebar.d.ts +19 -0
- package/dist/EvolutionSidebar.d.ts.map +1 -0
- package/dist/EvolutionSidebar.js +532 -0
- package/dist/LocalDataIndicator.d.ts +2 -0
- package/dist/LocalDataIndicator.d.ts.map +1 -0
- package/dist/LocalDataIndicator.js +63 -0
- package/dist/MarkdownView.d.ts +20 -0
- package/dist/MarkdownView.d.ts.map +1 -0
- package/dist/MarkdownView.js +304 -0
- package/dist/OverlayContextProvider.d.ts +79 -0
- package/dist/OverlayContextProvider.d.ts.map +1 -0
- package/dist/OverlayContextProvider.js +203 -0
- package/dist/PersonalizationInsights.d.ts +14 -0
- package/dist/PersonalizationInsights.d.ts.map +1 -0
- package/dist/PersonalizationInsights.js +456 -0
- package/dist/SaveToStudioButton.d.ts +8 -0
- package/dist/SaveToStudioButton.d.ts.map +1 -0
- package/dist/SaveToStudioButton.js +74 -0
- package/dist/SpecEditorPanel.d.ts +23 -0
- package/dist/SpecEditorPanel.d.ts.map +1 -0
- package/dist/SpecEditorPanel.js +720 -0
- package/dist/TemplateShell.d.ts +13 -0
- package/dist/TemplateShell.d.ts.map +1 -0
- package/dist/TemplateShell.js +190 -0
- package/dist/browser/EvolutionDashboard.js +803 -0
- package/dist/browser/EvolutionSidebar.js +531 -0
- package/dist/browser/LocalDataIndicator.js +62 -0
- package/dist/browser/MarkdownView.js +303 -0
- package/dist/browser/OverlayContextProvider.js +202 -0
- package/dist/browser/PersonalizationInsights.js +455 -0
- package/dist/browser/SaveToStudioButton.js +73 -0
- package/dist/browser/SpecEditorPanel.js +719 -0
- package/dist/browser/TemplateShell.js +189 -0
- package/dist/browser/hooks/index.js +1516 -0
- package/dist/browser/hooks/useBehaviorTracking.js +157 -0
- package/dist/browser/hooks/useEvolution.js +260 -0
- package/dist/browser/hooks/useRegistryTemplates.js +31 -0
- package/dist/browser/hooks/useSpecContent.js +579 -0
- package/dist/browser/hooks/useWorkflowComposer.js +493 -0
- package/dist/browser/index.js +3497 -0
- package/dist/browser/lib/component-registry.js +42 -0
- package/dist/browser/lib/runtime-context.js +15 -0
- package/dist/browser/lib/types.js +0 -0
- package/dist/browser/overlay-types.js +0 -0
- package/dist/browser/utils/fetchPresentationData.js +15 -0
- package/dist/browser/utils/generateSpecFromTemplate.js +423 -0
- package/dist/browser/utils/index.js +437 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +1517 -0
- package/dist/hooks/useBehaviorTracking.d.ts +56 -0
- package/dist/hooks/useBehaviorTracking.d.ts.map +1 -0
- package/dist/hooks/useBehaviorTracking.js +158 -0
- package/dist/hooks/useEvolution.d.ts +111 -0
- package/dist/hooks/useEvolution.d.ts.map +1 -0
- package/dist/hooks/useEvolution.js +261 -0
- package/dist/hooks/useRegistryTemplates.d.ts +10 -0
- package/dist/hooks/useRegistryTemplates.d.ts.map +1 -0
- package/dist/hooks/useRegistryTemplates.js +32 -0
- package/dist/hooks/useSpecContent.d.ts +41 -0
- package/dist/hooks/useSpecContent.d.ts.map +1 -0
- package/dist/hooks/useSpecContent.js +580 -0
- package/dist/hooks/useWorkflowComposer.d.ts +94 -0
- package/dist/hooks/useWorkflowComposer.d.ts.map +1 -0
- package/dist/hooks/useWorkflowComposer.js +494 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3498 -0
- package/dist/lib/component-registry.d.ts +18 -0
- package/dist/lib/component-registry.d.ts.map +1 -0
- package/dist/lib/component-registry.js +43 -0
- package/dist/lib/runtime-context.d.ts +29 -0
- package/dist/lib/runtime-context.d.ts.map +1 -0
- package/dist/lib/runtime-context.js +16 -0
- package/dist/lib/types.d.ts +69 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/node/EvolutionDashboard.js +803 -0
- package/dist/node/EvolutionSidebar.js +531 -0
- package/dist/node/LocalDataIndicator.js +62 -0
- package/dist/node/MarkdownView.js +303 -0
- package/dist/node/OverlayContextProvider.js +202 -0
- package/dist/node/PersonalizationInsights.js +455 -0
- package/dist/node/SaveToStudioButton.js +73 -0
- package/dist/node/SpecEditorPanel.js +719 -0
- package/dist/node/TemplateShell.js +189 -0
- package/dist/node/hooks/index.js +1516 -0
- package/dist/node/hooks/useBehaviorTracking.js +157 -0
- package/dist/node/hooks/useEvolution.js +260 -0
- package/dist/node/hooks/useRegistryTemplates.js +31 -0
- package/dist/node/hooks/useSpecContent.js +579 -0
- package/dist/node/hooks/useWorkflowComposer.js +493 -0
- package/dist/node/index.js +3497 -0
- package/dist/node/lib/component-registry.js +42 -0
- package/dist/node/lib/runtime-context.js +15 -0
- package/dist/node/lib/types.js +0 -0
- package/dist/node/overlay-types.js +0 -0
- package/dist/node/utils/fetchPresentationData.js +15 -0
- package/dist/node/utils/generateSpecFromTemplate.js +423 -0
- package/dist/node/utils/index.js +437 -0
- package/dist/overlay-types.d.ts +41 -0
- package/dist/overlay-types.d.ts.map +1 -0
- package/dist/overlay-types.js +1 -0
- package/dist/utils/fetchPresentationData.d.ts +34 -0
- package/dist/utils/fetchPresentationData.d.ts.map +1 -0
- package/dist/utils/fetchPresentationData.js +16 -0
- package/dist/utils/generateSpecFromTemplate.d.ts +7 -0
- package/dist/utils/generateSpecFromTemplate.d.ts.map +1 -0
- package/dist/utils/generateSpecFromTemplate.js +424 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +438 -0
- package/package.json +219 -14
- package/.turbo/turbo-build$colon$bundle.log +0 -9
- package/dist/index.mjs +0 -3121
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TemplateId } from './lib/types';
|
|
2
|
+
export interface EvolutionSidebarProps {
|
|
3
|
+
templateId: TemplateId;
|
|
4
|
+
/** Whether sidebar is expanded */
|
|
5
|
+
expanded?: boolean;
|
|
6
|
+
/** Toggle expanded state */
|
|
7
|
+
onToggle?: () => void;
|
|
8
|
+
/** Callback for logging actions */
|
|
9
|
+
onLog?: (message: string) => void;
|
|
10
|
+
/** Navigate to full evolution mode */
|
|
11
|
+
onOpenEvolution?: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Compact sidebar for Evolution Engine.
|
|
15
|
+
* Shows top anomalies, pending suggestions, and quick actions.
|
|
16
|
+
* Collapsible by default.
|
|
17
|
+
*/
|
|
18
|
+
export declare function EvolutionSidebar({ templateId, expanded, onToggle, onLog, onOpenEvolution, }: EvolutionSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=EvolutionSidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EvolutionSidebar.d.ts","sourceRoot":"","sources":["../src/EvolutionSidebar.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,UAAU,CAAC;IACvB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,mCAAmC;IACnC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,sCAAsC;IACtC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,QAAgB,EAChB,QAAQ,EACR,KAAK,EACL,eAAe,GAChB,EAAE,qBAAqB,2CA0MvB"}
|
|
@@ -0,0 +1,532 @@
|
|
|
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/EvolutionSidebar.tsx
|
|
261
|
+
import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
262
|
+
import { Button } from "@contractspec/lib.design-system";
|
|
263
|
+
import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
|
|
264
|
+
import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
|
|
265
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
266
|
+
"use client";
|
|
267
|
+
function EvolutionSidebar({
|
|
268
|
+
templateId,
|
|
269
|
+
expanded = false,
|
|
270
|
+
onToggle,
|
|
271
|
+
onLog,
|
|
272
|
+
onOpenEvolution
|
|
273
|
+
}) {
|
|
274
|
+
const {
|
|
275
|
+
anomalies,
|
|
276
|
+
suggestions,
|
|
277
|
+
loading,
|
|
278
|
+
approveSuggestion,
|
|
279
|
+
rejectSuggestion,
|
|
280
|
+
operationCount
|
|
281
|
+
} = useEvolution(templateId);
|
|
282
|
+
const pendingSuggestions = useMemo2(() => suggestions.filter((s) => s.status === "pending"), [suggestions]);
|
|
283
|
+
const topAnomalies = useMemo2(() => anomalies.sort((a, b) => {
|
|
284
|
+
const severityOrder = { high: 0, medium: 1, low: 2 };
|
|
285
|
+
return severityOrder[a.severity] - severityOrder[b.severity];
|
|
286
|
+
}).slice(0, 3), [anomalies]);
|
|
287
|
+
const handleApprove = useCallback2((id) => {
|
|
288
|
+
approveSuggestion(id);
|
|
289
|
+
onLog?.(`Approved suggestion ${id.slice(0, 8)}`);
|
|
290
|
+
}, [approveSuggestion, onLog]);
|
|
291
|
+
const handleReject = useCallback2((id) => {
|
|
292
|
+
rejectSuggestion(id);
|
|
293
|
+
onLog?.(`Rejected suggestion ${id.slice(0, 8)}`);
|
|
294
|
+
}, [rejectSuggestion, onLog]);
|
|
295
|
+
if (!expanded) {
|
|
296
|
+
return /* @__PURE__ */ jsxDEV("button", {
|
|
297
|
+
onClick: onToggle,
|
|
298
|
+
className: "flex items-center gap-2 rounded-lg border border-violet-500/30 bg-violet-500/10 px-3 py-2 text-sm transition hover:bg-violet-500/20",
|
|
299
|
+
type: "button",
|
|
300
|
+
children: [
|
|
301
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
302
|
+
children: "\uD83E\uDD16"
|
|
303
|
+
}, undefined, false, undefined, this),
|
|
304
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
305
|
+
children: "Evolution"
|
|
306
|
+
}, undefined, false, undefined, this),
|
|
307
|
+
pendingSuggestions.length > 0 && /* @__PURE__ */ jsxDEV(Badge, {
|
|
308
|
+
variant: "secondary",
|
|
309
|
+
className: "border-amber-500/30 bg-amber-500/20 text-amber-400",
|
|
310
|
+
children: pendingSuggestions.length
|
|
311
|
+
}, undefined, false, undefined, this),
|
|
312
|
+
anomalies.length > 0 && pendingSuggestions.length === 0 && /* @__PURE__ */ jsxDEV(Badge, {
|
|
313
|
+
variant: "destructive",
|
|
314
|
+
children: anomalies.length
|
|
315
|
+
}, undefined, false, undefined, this)
|
|
316
|
+
]
|
|
317
|
+
}, undefined, true, undefined, this);
|
|
318
|
+
}
|
|
319
|
+
return /* @__PURE__ */ jsxDEV(Card, {
|
|
320
|
+
className: "w-80 overflow-hidden",
|
|
321
|
+
children: [
|
|
322
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
323
|
+
className: "flex items-center justify-between border-b border-violet-500/20 bg-violet-500/5 px-3 py-2",
|
|
324
|
+
children: [
|
|
325
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
326
|
+
className: "flex items-center gap-2",
|
|
327
|
+
children: [
|
|
328
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
329
|
+
children: "\uD83E\uDD16"
|
|
330
|
+
}, undefined, false, undefined, this),
|
|
331
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
332
|
+
className: "text-sm font-semibold",
|
|
333
|
+
children: "Evolution"
|
|
334
|
+
}, undefined, false, undefined, this)
|
|
335
|
+
]
|
|
336
|
+
}, undefined, true, undefined, this),
|
|
337
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
338
|
+
className: "flex items-center gap-1",
|
|
339
|
+
children: [
|
|
340
|
+
onOpenEvolution && /* @__PURE__ */ jsxDEV(Button, {
|
|
341
|
+
variant: "ghost",
|
|
342
|
+
size: "sm",
|
|
343
|
+
onPress: onOpenEvolution,
|
|
344
|
+
children: "Expand"
|
|
345
|
+
}, undefined, false, undefined, this),
|
|
346
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
347
|
+
onClick: onToggle,
|
|
348
|
+
className: "text-muted-foreground hover:text-foreground p-1",
|
|
349
|
+
type: "button",
|
|
350
|
+
title: "Collapse",
|
|
351
|
+
children: "\u2715"
|
|
352
|
+
}, undefined, false, undefined, this)
|
|
353
|
+
]
|
|
354
|
+
}, undefined, true, undefined, this)
|
|
355
|
+
]
|
|
356
|
+
}, undefined, true, undefined, this),
|
|
357
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
358
|
+
className: "max-h-96 overflow-y-auto p-3",
|
|
359
|
+
children: [
|
|
360
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
361
|
+
className: "mb-3 flex items-center justify-between text-xs",
|
|
362
|
+
children: [
|
|
363
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
364
|
+
className: "text-muted-foreground",
|
|
365
|
+
children: [
|
|
366
|
+
operationCount,
|
|
367
|
+
" ops tracked"
|
|
368
|
+
]
|
|
369
|
+
}, undefined, true, undefined, this),
|
|
370
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
371
|
+
className: "flex items-center gap-2",
|
|
372
|
+
children: [
|
|
373
|
+
anomalies.length > 0 && /* @__PURE__ */ jsxDEV(Badge, {
|
|
374
|
+
variant: "destructive",
|
|
375
|
+
children: [
|
|
376
|
+
anomalies.length,
|
|
377
|
+
" anomalies"
|
|
378
|
+
]
|
|
379
|
+
}, undefined, true, undefined, this),
|
|
380
|
+
pendingSuggestions.length > 0 && /* @__PURE__ */ jsxDEV(Badge, {
|
|
381
|
+
variant: "secondary",
|
|
382
|
+
className: "border-amber-500/30 bg-amber-500/20 text-amber-400",
|
|
383
|
+
children: [
|
|
384
|
+
pendingSuggestions.length,
|
|
385
|
+
" pending"
|
|
386
|
+
]
|
|
387
|
+
}, undefined, true, undefined, this)
|
|
388
|
+
]
|
|
389
|
+
}, undefined, true, undefined, this)
|
|
390
|
+
]
|
|
391
|
+
}, undefined, true, undefined, this),
|
|
392
|
+
loading && /* @__PURE__ */ jsxDEV("div", {
|
|
393
|
+
className: "text-muted-foreground py-4 text-center text-sm",
|
|
394
|
+
children: "Generating suggestions..."
|
|
395
|
+
}, undefined, false, undefined, this),
|
|
396
|
+
topAnomalies.length > 0 && /* @__PURE__ */ jsxDEV("div", {
|
|
397
|
+
className: "mb-4",
|
|
398
|
+
children: [
|
|
399
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
400
|
+
className: "mb-2 text-xs font-semibold text-violet-400 uppercase",
|
|
401
|
+
children: "Top Issues"
|
|
402
|
+
}, undefined, false, undefined, this),
|
|
403
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
404
|
+
className: "space-y-2",
|
|
405
|
+
children: topAnomalies.map((anomaly, index) => /* @__PURE__ */ jsxDEV("div", {
|
|
406
|
+
className: "rounded border border-amber-500/20 bg-amber-500/5 p-2 text-xs",
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
409
|
+
className: "flex items-center gap-2",
|
|
410
|
+
children: [
|
|
411
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
412
|
+
children: anomaly.severity === "high" ? "\uD83D\uDD34" : anomaly.severity === "medium" ? "\uD83D\uDFE0" : "\uD83D\uDFE1"
|
|
413
|
+
}, undefined, false, undefined, this),
|
|
414
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
415
|
+
className: "truncate font-medium",
|
|
416
|
+
children: anomaly.operation.name
|
|
417
|
+
}, undefined, false, undefined, this)
|
|
418
|
+
]
|
|
419
|
+
}, undefined, true, undefined, this),
|
|
420
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
421
|
+
className: "text-muted-foreground mt-1 truncate",
|
|
422
|
+
children: anomaly.description
|
|
423
|
+
}, undefined, false, undefined, this)
|
|
424
|
+
]
|
|
425
|
+
}, `${anomaly.operation.name}-${index}`, true, undefined, this))
|
|
426
|
+
}, undefined, false, undefined, this)
|
|
427
|
+
]
|
|
428
|
+
}, undefined, true, undefined, this),
|
|
429
|
+
pendingSuggestions.length > 0 && /* @__PURE__ */ jsxDEV("div", {
|
|
430
|
+
children: [
|
|
431
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
432
|
+
className: "mb-2 text-xs font-semibold text-violet-400 uppercase",
|
|
433
|
+
children: "Pending Suggestions"
|
|
434
|
+
}, undefined, false, undefined, this),
|
|
435
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
436
|
+
className: "space-y-2",
|
|
437
|
+
children: [
|
|
438
|
+
pendingSuggestions.slice(0, 3).map((suggestion) => /* @__PURE__ */ jsxDEV(CompactSuggestionCard, {
|
|
439
|
+
suggestion,
|
|
440
|
+
onApprove: handleApprove,
|
|
441
|
+
onReject: handleReject
|
|
442
|
+
}, suggestion.id, false, undefined, this)),
|
|
443
|
+
pendingSuggestions.length > 3 && /* @__PURE__ */ jsxDEV("p", {
|
|
444
|
+
className: "text-muted-foreground text-center text-xs",
|
|
445
|
+
children: [
|
|
446
|
+
"+",
|
|
447
|
+
pendingSuggestions.length - 3,
|
|
448
|
+
" more suggestions"
|
|
449
|
+
]
|
|
450
|
+
}, undefined, true, undefined, this)
|
|
451
|
+
]
|
|
452
|
+
}, undefined, true, undefined, this)
|
|
453
|
+
]
|
|
454
|
+
}, undefined, true, undefined, this),
|
|
455
|
+
anomalies.length === 0 && pendingSuggestions.length === 0 && !loading && /* @__PURE__ */ jsxDEV("div", {
|
|
456
|
+
className: "text-muted-foreground py-4 text-center text-xs",
|
|
457
|
+
children: "No issues detected. Keep coding!"
|
|
458
|
+
}, undefined, false, undefined, this)
|
|
459
|
+
]
|
|
460
|
+
}, undefined, true, undefined, this),
|
|
461
|
+
onOpenEvolution && /* @__PURE__ */ jsxDEV("div", {
|
|
462
|
+
className: "border-t border-violet-500/20 p-2",
|
|
463
|
+
children: /* @__PURE__ */ jsxDEV(Button, {
|
|
464
|
+
variant: "ghost",
|
|
465
|
+
size: "sm",
|
|
466
|
+
className: "w-full",
|
|
467
|
+
onPress: onOpenEvolution,
|
|
468
|
+
children: "Open Evolution Dashboard \u2192"
|
|
469
|
+
}, undefined, false, undefined, this)
|
|
470
|
+
}, undefined, false, undefined, this)
|
|
471
|
+
]
|
|
472
|
+
}, undefined, true, undefined, this);
|
|
473
|
+
}
|
|
474
|
+
function CompactSuggestionCard({
|
|
475
|
+
suggestion,
|
|
476
|
+
onApprove,
|
|
477
|
+
onReject
|
|
478
|
+
}) {
|
|
479
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
480
|
+
className: "rounded border border-violet-500/20 bg-violet-500/5 p-2",
|
|
481
|
+
children: [
|
|
482
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
483
|
+
className: "flex items-start justify-between gap-2",
|
|
484
|
+
children: /* @__PURE__ */ jsxDEV("div", {
|
|
485
|
+
className: "min-w-0 flex-1",
|
|
486
|
+
children: [
|
|
487
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
488
|
+
className: "truncate text-xs font-medium",
|
|
489
|
+
children: suggestion.proposal.summary
|
|
490
|
+
}, undefined, false, undefined, this),
|
|
491
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
492
|
+
className: "mt-1 flex items-center gap-2 text-xs",
|
|
493
|
+
children: [
|
|
494
|
+
/* @__PURE__ */ jsxDEV(Badge, {
|
|
495
|
+
variant: "secondary",
|
|
496
|
+
children: suggestion.priority
|
|
497
|
+
}, undefined, false, undefined, this),
|
|
498
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
499
|
+
className: "text-muted-foreground",
|
|
500
|
+
children: [
|
|
501
|
+
(suggestion.confidence * 100).toFixed(0),
|
|
502
|
+
"%"
|
|
503
|
+
]
|
|
504
|
+
}, undefined, true, undefined, this)
|
|
505
|
+
]
|
|
506
|
+
}, undefined, true, undefined, this)
|
|
507
|
+
]
|
|
508
|
+
}, undefined, true, undefined, this)
|
|
509
|
+
}, undefined, false, undefined, this),
|
|
510
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
511
|
+
className: "mt-2 flex justify-end gap-1",
|
|
512
|
+
children: [
|
|
513
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
514
|
+
onClick: () => onReject(suggestion.id),
|
|
515
|
+
className: "rounded px-2 py-0.5 text-xs text-red-400 hover:bg-red-400/10",
|
|
516
|
+
type: "button",
|
|
517
|
+
children: "Reject"
|
|
518
|
+
}, undefined, false, undefined, this),
|
|
519
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
520
|
+
onClick: () => onApprove(suggestion.id),
|
|
521
|
+
className: "rounded bg-violet-500/20 px-2 py-0.5 text-xs text-violet-400 hover:bg-violet-500/30",
|
|
522
|
+
type: "button",
|
|
523
|
+
children: "Approve"
|
|
524
|
+
}, undefined, false, undefined, this)
|
|
525
|
+
]
|
|
526
|
+
}, undefined, true, undefined, this)
|
|
527
|
+
]
|
|
528
|
+
}, undefined, true, undefined, this);
|
|
529
|
+
}
|
|
530
|
+
export {
|
|
531
|
+
EvolutionSidebar
|
|
532
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalDataIndicator.d.ts","sourceRoot":"","sources":["../src/LocalDataIndicator.tsx"],"names":[],"mappings":"AAOA,wBAAgB,kBAAkB,4CA+BjC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/lib/runtime-context.tsx
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
"use client";
|
|
5
|
+
var TemplateRuntimeContext = createContext(null);
|
|
6
|
+
function useTemplateRuntime() {
|
|
7
|
+
const context = useContext(TemplateRuntimeContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error("useTemplateRuntime must be used within a TemplateRuntimeProvider");
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/LocalDataIndicator.tsx
|
|
15
|
+
import { RefreshCw, Shield } from "lucide-react";
|
|
16
|
+
import { useState } from "react";
|
|
17
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
18
|
+
"use client";
|
|
19
|
+
function LocalDataIndicator() {
|
|
20
|
+
const { projectId, templateId, template, installer } = useTemplateRuntime();
|
|
21
|
+
const [isResetting, setIsResetting] = useState(false);
|
|
22
|
+
const handleReset = async () => {
|
|
23
|
+
setIsResetting(true);
|
|
24
|
+
try {
|
|
25
|
+
await installer.install(templateId, { projectId });
|
|
26
|
+
} finally {
|
|
27
|
+
setIsResetting(false);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
31
|
+
className: "border-border bg-muted/40 text-muted-foreground inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs",
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsxDEV(Shield, {
|
|
34
|
+
className: "h-3.5 w-3.5 text-violet-400"
|
|
35
|
+
}, undefined, false, undefined, this),
|
|
36
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
37
|
+
children: [
|
|
38
|
+
"Local runtime \xB7",
|
|
39
|
+
" ",
|
|
40
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
41
|
+
className: "text-foreground font-semibold",
|
|
42
|
+
children: template.name
|
|
43
|
+
}, undefined, false, undefined, this)
|
|
44
|
+
]
|
|
45
|
+
}, undefined, true, undefined, this),
|
|
46
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
47
|
+
type: "button",
|
|
48
|
+
className: "border-border text-muted-foreground hover:text-foreground inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-semibold",
|
|
49
|
+
onClick: handleReset,
|
|
50
|
+
disabled: isResetting,
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsxDEV(RefreshCw, {
|
|
53
|
+
className: "h-3 w-3"
|
|
54
|
+
}, undefined, false, undefined, this),
|
|
55
|
+
isResetting ? "Resetting\u2026" : "Reset data"
|
|
56
|
+
]
|
|
57
|
+
}, undefined, true, undefined, this)
|
|
58
|
+
]
|
|
59
|
+
}, undefined, true, undefined, this);
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
LocalDataIndicator
|
|
63
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TemplateId } from './lib/types';
|
|
2
|
+
export interface MarkdownViewProps {
|
|
3
|
+
/** Optional override, otherwise comes from context */
|
|
4
|
+
templateId?: TemplateId;
|
|
5
|
+
presentationId?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* MarkdownView renders template presentations as markdown using TransformEngine.
|
|
10
|
+
* It allows switching between available presentations for the template.
|
|
11
|
+
*/
|
|
12
|
+
export declare function MarkdownView({ templateId: propTemplateId, presentationId, className, }: MarkdownViewProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
/**
|
|
14
|
+
* Simple markdown renderer using pre-formatted display
|
|
15
|
+
* For production, consider using react-markdown or similar
|
|
16
|
+
*/
|
|
17
|
+
export declare function MarkdownRenderer({ content }: {
|
|
18
|
+
content: string;
|
|
19
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=MarkdownView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownView.d.ts","sourceRoot":"","sources":["../src/MarkdownView.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EAAE,cAAc,EAC1B,cAAc,EACd,SAAS,GACV,EAAE,iBAAiB,2CA2JnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,2CAmGhE"}
|