@runloop/rl-cli 1.7.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -5
- package/dist/cli.js +0 -0
- package/dist/commands/blueprint/delete.js +21 -0
- package/dist/commands/blueprint/list.js +226 -174
- package/dist/commands/blueprint/prune.js +13 -28
- package/dist/commands/devbox/create.js +41 -0
- package/dist/commands/devbox/list.js +125 -109
- package/dist/commands/devbox/tunnel.js +4 -19
- package/dist/commands/gateway-config/create.js +44 -0
- package/dist/commands/gateway-config/delete.js +21 -0
- package/dist/commands/gateway-config/get.js +15 -0
- package/dist/commands/gateway-config/list.js +493 -0
- package/dist/commands/gateway-config/update.js +60 -0
- package/dist/commands/menu.js +2 -1
- package/dist/commands/secret/list.js +379 -4
- package/dist/commands/snapshot/list.js +11 -2
- package/dist/commands/snapshot/prune.js +265 -0
- package/dist/components/BenchmarkMenu.js +108 -0
- package/dist/components/DetailedInfoView.js +20 -0
- package/dist/components/DevboxActionsMenu.js +9 -61
- package/dist/components/DevboxCreatePage.js +531 -14
- package/dist/components/DevboxDetailPage.js +27 -22
- package/dist/components/GatewayConfigCreatePage.js +265 -0
- package/dist/components/LogsViewer.js +6 -40
- package/dist/components/MainMenu.js +63 -22
- package/dist/components/ResourceDetailPage.js +143 -160
- package/dist/components/ResourceListView.js +3 -33
- package/dist/components/ResourcePicker.js +220 -0
- package/dist/components/SecretCreatePage.js +183 -0
- package/dist/components/SettingsMenu.js +95 -0
- package/dist/components/StateHistory.js +1 -20
- package/dist/components/StatusBadge.js +80 -0
- package/dist/components/StreamingLogsViewer.js +8 -42
- package/dist/components/form/FormTextInput.js +4 -2
- package/dist/components/resourceDetailTypes.js +18 -0
- package/dist/hooks/useInputHandler.js +103 -0
- package/dist/router/Router.js +99 -2
- package/dist/screens/BenchmarkDetailScreen.js +163 -0
- package/dist/screens/BenchmarkJobCreateScreen.js +524 -0
- package/dist/screens/BenchmarkJobDetailScreen.js +614 -0
- package/dist/screens/BenchmarkJobListScreen.js +479 -0
- package/dist/screens/BenchmarkListScreen.js +266 -0
- package/dist/screens/BenchmarkMenuScreen.js +29 -0
- package/dist/screens/BenchmarkRunDetailScreen.js +425 -0
- package/dist/screens/BenchmarkRunListScreen.js +275 -0
- package/dist/screens/BlueprintDetailScreen.js +5 -1
- package/dist/screens/DevboxCreateScreen.js +2 -2
- package/dist/screens/GatewayConfigDetailScreen.js +236 -0
- package/dist/screens/GatewayConfigListScreen.js +7 -0
- package/dist/screens/MenuScreen.js +5 -2
- package/dist/screens/ScenarioRunDetailScreen.js +226 -0
- package/dist/screens/ScenarioRunListScreen.js +245 -0
- package/dist/screens/SecretCreateScreen.js +7 -0
- package/dist/screens/SecretDetailScreen.js +198 -0
- package/dist/screens/SecretListScreen.js +7 -0
- package/dist/screens/SettingsMenuScreen.js +26 -0
- package/dist/screens/SnapshotDetailScreen.js +6 -0
- package/dist/services/agentService.js +42 -0
- package/dist/services/benchmarkJobService.js +122 -0
- package/dist/services/benchmarkService.js +120 -0
- package/dist/services/gatewayConfigService.js +114 -0
- package/dist/services/scenarioService.js +34 -0
- package/dist/store/benchmarkJobStore.js +66 -0
- package/dist/store/benchmarkStore.js +183 -0
- package/dist/store/betaFeatureStore.js +47 -0
- package/dist/store/gatewayConfigStore.js +83 -0
- package/dist/store/index.js +1 -0
- package/dist/utils/browser.js +22 -0
- package/dist/utils/clipboard.js +41 -0
- package/dist/utils/commands.js +80 -0
- package/dist/utils/config.js +8 -0
- package/dist/utils/time.js +121 -0
- package/package.json +42 -43
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* BenchmarkRunDetailScreen - Detail page for benchmark runs
|
|
4
|
+
* Uses the generic ResourceDetailPage component
|
|
5
|
+
*/
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { Box, Text } from "ink";
|
|
8
|
+
import figures from "figures";
|
|
9
|
+
import { useNavigation } from "../store/navigationStore.js";
|
|
10
|
+
import { useBenchmarkStore, } from "../store/benchmarkStore.js";
|
|
11
|
+
import { ResourceDetailPage, formatTimestamp, } from "../components/ResourceDetailPage.js";
|
|
12
|
+
import { getBenchmarkRun, listScenarioRuns, } from "../services/benchmarkService.js";
|
|
13
|
+
import { SpinnerComponent } from "../components/Spinner.js";
|
|
14
|
+
import { ErrorMessage } from "../components/ErrorMessage.js";
|
|
15
|
+
import { Breadcrumb } from "../components/Breadcrumb.js";
|
|
16
|
+
import { getStatusDisplay } from "../components/StatusBadge.js";
|
|
17
|
+
import { Table, createTextColumn, createComponentColumn, } from "../components/Table.js";
|
|
18
|
+
import { colors } from "../utils/theme.js";
|
|
19
|
+
export function BenchmarkRunDetailScreen({ benchmarkRunId, }) {
|
|
20
|
+
const { goBack, navigate } = useNavigation();
|
|
21
|
+
const benchmarkRuns = useBenchmarkStore((state) => state.benchmarkRuns);
|
|
22
|
+
const [loading, setLoading] = React.useState(false);
|
|
23
|
+
const [error, setError] = React.useState(null);
|
|
24
|
+
const [fetchedRun, setFetchedRun] = React.useState(null);
|
|
25
|
+
const [scenarioRuns, setScenarioRuns] = React.useState([]);
|
|
26
|
+
const [scenarioRunsLoading, setScenarioRunsLoading] = React.useState(false);
|
|
27
|
+
// Find run in store first
|
|
28
|
+
const runFromStore = benchmarkRuns.find((r) => r.id === benchmarkRunId);
|
|
29
|
+
// Polling function
|
|
30
|
+
const pollRun = React.useCallback(async () => {
|
|
31
|
+
if (!benchmarkRunId)
|
|
32
|
+
return null;
|
|
33
|
+
// Also refresh scenario runs when polling
|
|
34
|
+
listScenarioRuns({
|
|
35
|
+
limit: 10,
|
|
36
|
+
benchmarkRunId,
|
|
37
|
+
})
|
|
38
|
+
.then((result) => {
|
|
39
|
+
setScenarioRuns(result.scenarioRuns);
|
|
40
|
+
})
|
|
41
|
+
.catch(() => {
|
|
42
|
+
// Silently fail for scenario runs
|
|
43
|
+
});
|
|
44
|
+
return getBenchmarkRun(benchmarkRunId);
|
|
45
|
+
}, [benchmarkRunId]);
|
|
46
|
+
// Fetch run from API if not in store
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
if (benchmarkRunId && !loading && !fetchedRun) {
|
|
49
|
+
setLoading(true);
|
|
50
|
+
setError(null);
|
|
51
|
+
getBenchmarkRun(benchmarkRunId)
|
|
52
|
+
.then((run) => {
|
|
53
|
+
setFetchedRun(run);
|
|
54
|
+
setLoading(false);
|
|
55
|
+
})
|
|
56
|
+
.catch((err) => {
|
|
57
|
+
setError(err);
|
|
58
|
+
setLoading(false);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}, [benchmarkRunId, loading, fetchedRun]);
|
|
62
|
+
// Fetch scenario runs for this benchmark run
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (benchmarkRunId && !scenarioRunsLoading && scenarioRuns.length === 0) {
|
|
65
|
+
setScenarioRunsLoading(true);
|
|
66
|
+
listScenarioRuns({
|
|
67
|
+
limit: 10, // Show up to 10 scenarios
|
|
68
|
+
benchmarkRunId,
|
|
69
|
+
})
|
|
70
|
+
.then((result) => {
|
|
71
|
+
setScenarioRuns(result.scenarioRuns);
|
|
72
|
+
setScenarioRunsLoading(false);
|
|
73
|
+
})
|
|
74
|
+
.catch(() => {
|
|
75
|
+
// Silently fail for scenario runs - not critical
|
|
76
|
+
setScenarioRunsLoading(false);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}, [benchmarkRunId, scenarioRunsLoading, scenarioRuns.length]);
|
|
80
|
+
// Use fetched run for full details, fall back to store for basic display
|
|
81
|
+
const run = fetchedRun || runFromStore;
|
|
82
|
+
// Auto-refresh scenario runs every 5 seconds if benchmark run is running
|
|
83
|
+
React.useEffect(() => {
|
|
84
|
+
if (!benchmarkRunId || !run)
|
|
85
|
+
return;
|
|
86
|
+
// Only refresh if run is still running
|
|
87
|
+
if (run.state !== "running")
|
|
88
|
+
return;
|
|
89
|
+
const interval = setInterval(() => {
|
|
90
|
+
listScenarioRuns({
|
|
91
|
+
limit: 10,
|
|
92
|
+
benchmarkRunId,
|
|
93
|
+
})
|
|
94
|
+
.then((result) => {
|
|
95
|
+
setScenarioRuns(result.scenarioRuns);
|
|
96
|
+
})
|
|
97
|
+
.catch(() => {
|
|
98
|
+
// Silently fail
|
|
99
|
+
});
|
|
100
|
+
}, 5000);
|
|
101
|
+
return () => clearInterval(interval);
|
|
102
|
+
}, [benchmarkRunId, run]);
|
|
103
|
+
// Show loading state
|
|
104
|
+
if (!run && benchmarkRunId && !error) {
|
|
105
|
+
return (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: [
|
|
106
|
+
{ label: "Home" },
|
|
107
|
+
{ label: "Benchmarks" },
|
|
108
|
+
{ label: "Benchmark Runs" },
|
|
109
|
+
{ label: "Loading...", active: true },
|
|
110
|
+
] }), _jsx(SpinnerComponent, { message: "Loading benchmark run details..." })] }));
|
|
111
|
+
}
|
|
112
|
+
// Show error state
|
|
113
|
+
if (error && !run) {
|
|
114
|
+
return (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: [
|
|
115
|
+
{ label: "Home" },
|
|
116
|
+
{ label: "Benchmarks" },
|
|
117
|
+
{ label: "Benchmark Runs" },
|
|
118
|
+
{ label: "Error", active: true },
|
|
119
|
+
] }), _jsx(ErrorMessage, { message: "Failed to load benchmark run details", error: error })] }));
|
|
120
|
+
}
|
|
121
|
+
// Show not found error
|
|
122
|
+
if (!run) {
|
|
123
|
+
return (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: [
|
|
124
|
+
{ label: "Home" },
|
|
125
|
+
{ label: "Benchmarks" },
|
|
126
|
+
{ label: "Benchmark Runs" },
|
|
127
|
+
{ label: "Not Found", active: true },
|
|
128
|
+
] }), _jsx(ErrorMessage, { message: `Benchmark run ${benchmarkRunId || "unknown"} not found`, error: new Error("Benchmark run not found") })] }));
|
|
129
|
+
}
|
|
130
|
+
// Helper to calculate overall run status based on scenarios
|
|
131
|
+
const calculateOverallStatus = (scenarios) => {
|
|
132
|
+
if (scenarios.length === 0) {
|
|
133
|
+
return {
|
|
134
|
+
status: "not-started",
|
|
135
|
+
label: "Not Started",
|
|
136
|
+
color: colors.textDim,
|
|
137
|
+
icon: figures.circle,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// Check for any failures or timeouts
|
|
141
|
+
const hasFailed = scenarios.some((s) => s.state === "failed" || s.state === "timeout");
|
|
142
|
+
if (hasFailed) {
|
|
143
|
+
return {
|
|
144
|
+
status: "failed",
|
|
145
|
+
label: "Failed",
|
|
146
|
+
color: colors.error,
|
|
147
|
+
icon: figures.cross,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Check if all are completed
|
|
151
|
+
const allCompleted = scenarios.every((s) => s.state === "completed" || s.state === "scored");
|
|
152
|
+
if (allCompleted) {
|
|
153
|
+
return {
|
|
154
|
+
status: "pass",
|
|
155
|
+
label: "Complete",
|
|
156
|
+
color: colors.success,
|
|
157
|
+
icon: figures.tick,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// Check if any are running
|
|
161
|
+
const anyRunning = scenarios.some((s) => s.state === "running" || s.state === "scoring");
|
|
162
|
+
if (anyRunning) {
|
|
163
|
+
return {
|
|
164
|
+
status: "in-progress",
|
|
165
|
+
label: "In Progress",
|
|
166
|
+
color: colors.warning,
|
|
167
|
+
icon: figures.circleFilled,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// Default to not started
|
|
171
|
+
return {
|
|
172
|
+
status: "not-started",
|
|
173
|
+
label: "Not Started",
|
|
174
|
+
color: colors.textDim,
|
|
175
|
+
icon: figures.circle,
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
// Helper to format duration
|
|
179
|
+
const formatDuration = (ms) => {
|
|
180
|
+
if (ms < 1000)
|
|
181
|
+
return `${ms}ms`;
|
|
182
|
+
const seconds = Math.floor(ms / 1000);
|
|
183
|
+
if (seconds < 60)
|
|
184
|
+
return `${seconds}s`;
|
|
185
|
+
const minutes = Math.floor(seconds / 60);
|
|
186
|
+
const remainingSeconds = seconds % 60;
|
|
187
|
+
if (minutes < 60)
|
|
188
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
189
|
+
const hours = Math.floor(minutes / 60);
|
|
190
|
+
const remainingMinutes = minutes % 60;
|
|
191
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
192
|
+
};
|
|
193
|
+
// Build detail sections
|
|
194
|
+
const detailSections = [];
|
|
195
|
+
// Basic details section
|
|
196
|
+
const basicFields = [];
|
|
197
|
+
if (run.benchmark_id) {
|
|
198
|
+
basicFields.push({
|
|
199
|
+
label: "Benchmark ID",
|
|
200
|
+
value: _jsx(Text, { color: colors.idColor, children: run.benchmark_id }),
|
|
201
|
+
action: {
|
|
202
|
+
type: "navigate",
|
|
203
|
+
screen: "benchmark-detail",
|
|
204
|
+
params: { benchmarkId: run.benchmark_id },
|
|
205
|
+
hint: "View Benchmark",
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
if (run.purpose) {
|
|
210
|
+
basicFields.push({
|
|
211
|
+
label: "Purpose",
|
|
212
|
+
value: run.purpose,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (run.score !== undefined && run.score !== null) {
|
|
216
|
+
basicFields.push({
|
|
217
|
+
label: "Score",
|
|
218
|
+
value: (_jsx(Text, { color: colors.success, bold: true, children: run.score.toFixed(2) })),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (basicFields.length > 0) {
|
|
222
|
+
detailSections.push({
|
|
223
|
+
title: "Details",
|
|
224
|
+
icon: figures.squareSmallFilled,
|
|
225
|
+
color: colors.warning,
|
|
226
|
+
fields: basicFields,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
// Overall Status Section
|
|
230
|
+
const overallStatus = calculateOverallStatus(scenarioRuns);
|
|
231
|
+
detailSections.push({
|
|
232
|
+
title: "Overall Status",
|
|
233
|
+
icon: overallStatus.icon,
|
|
234
|
+
color: overallStatus.color,
|
|
235
|
+
fields: [
|
|
236
|
+
{
|
|
237
|
+
label: "Status",
|
|
238
|
+
value: (_jsx(Text, { color: overallStatus.color, bold: true, children: overallStatus.label })),
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
label: "Scenarios",
|
|
242
|
+
value: `${scenarioRuns.length} scenario${scenarioRuns.length !== 1 ? "s" : ""}`,
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
// Scenario Runs Section
|
|
247
|
+
if (scenarioRuns.length > 0) {
|
|
248
|
+
// Define columns for scenario table
|
|
249
|
+
const scenarioColumns = [
|
|
250
|
+
createTextColumn("id", "ID", (s) => s.id, {
|
|
251
|
+
width: 26,
|
|
252
|
+
color: colors.idColor,
|
|
253
|
+
dimColor: false,
|
|
254
|
+
bold: false,
|
|
255
|
+
}),
|
|
256
|
+
createTextColumn("name", "Name", (s) => s.name || "(unnamed)", {
|
|
257
|
+
width: 50,
|
|
258
|
+
}),
|
|
259
|
+
createComponentColumn("status", "Status", (s, _index, isSelected) => {
|
|
260
|
+
const statusDisplay = getStatusDisplay(s.state);
|
|
261
|
+
const text = statusDisplay.text.slice(0, 12).padEnd(12, " ");
|
|
262
|
+
return (_jsx(Text, { color: isSelected ? colors.text : statusDisplay.color, bold: isSelected, inverse: isSelected, children: text }));
|
|
263
|
+
}, { width: 12 }),
|
|
264
|
+
createTextColumn("score", "Score", (s) => {
|
|
265
|
+
const score = s.scoring_contract_result?.score;
|
|
266
|
+
return score !== undefined ? String(score) : "";
|
|
267
|
+
}, {
|
|
268
|
+
width: 10,
|
|
269
|
+
color: colors.info,
|
|
270
|
+
}),
|
|
271
|
+
];
|
|
272
|
+
detailSections.push({
|
|
273
|
+
title: "Scenario Runs",
|
|
274
|
+
icon: figures.pointer,
|
|
275
|
+
color: colors.info,
|
|
276
|
+
fields: [
|
|
277
|
+
{
|
|
278
|
+
label: "",
|
|
279
|
+
value: (_jsx(Box, { paddingTop: 1, children: _jsx(Table, { data: scenarioRuns, columns: scenarioColumns, selectedIndex: -1, keyExtractor: (s) => s.id }) })),
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
// Timing section
|
|
285
|
+
const timingFields = [];
|
|
286
|
+
if (run.start_time_ms) {
|
|
287
|
+
timingFields.push({
|
|
288
|
+
label: "Started",
|
|
289
|
+
value: formatTimestamp(run.start_time_ms),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const endTimeMs = run.start_time_ms && run.duration_ms
|
|
293
|
+
? run.start_time_ms + run.duration_ms
|
|
294
|
+
: undefined;
|
|
295
|
+
if (endTimeMs) {
|
|
296
|
+
timingFields.push({
|
|
297
|
+
label: "Ended",
|
|
298
|
+
value: formatTimestamp(endTimeMs),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (run.duration_ms) {
|
|
302
|
+
timingFields.push({
|
|
303
|
+
label: "Duration",
|
|
304
|
+
value: _jsx(Text, { color: colors.info, children: formatDuration(run.duration_ms) }),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (timingFields.length > 0) {
|
|
308
|
+
detailSections.push({
|
|
309
|
+
title: "Timing",
|
|
310
|
+
icon: figures.play,
|
|
311
|
+
color: colors.info,
|
|
312
|
+
fields: timingFields,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// Secrets Provided section (show keys only, not values)
|
|
316
|
+
if (run.secrets_provided && Object.keys(run.secrets_provided).length > 0) {
|
|
317
|
+
const secretFields = Object.entries(run.secrets_provided).map(([envVar, secretName]) => ({
|
|
318
|
+
label: envVar,
|
|
319
|
+
value: _jsxs(Text, { color: colors.warning, children: [secretName, " (secret)"] }),
|
|
320
|
+
action: {
|
|
321
|
+
type: "navigate",
|
|
322
|
+
screen: "secret-detail",
|
|
323
|
+
params: { secretId: secretName },
|
|
324
|
+
hint: "View Secret",
|
|
325
|
+
},
|
|
326
|
+
}));
|
|
327
|
+
detailSections.push({
|
|
328
|
+
title: "Secrets Provided",
|
|
329
|
+
icon: figures.warning,
|
|
330
|
+
color: colors.warning,
|
|
331
|
+
fields: secretFields,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
// Metadata section
|
|
335
|
+
if (run.metadata && Object.keys(run.metadata).length > 0) {
|
|
336
|
+
const metadataFields = Object.entries(run.metadata).map(([key, value]) => ({
|
|
337
|
+
label: key,
|
|
338
|
+
value: value,
|
|
339
|
+
}));
|
|
340
|
+
detailSections.push({
|
|
341
|
+
title: "Metadata",
|
|
342
|
+
icon: figures.identical,
|
|
343
|
+
color: colors.secondary,
|
|
344
|
+
fields: metadataFields,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
// Operations available for benchmark runs
|
|
348
|
+
const operations = [
|
|
349
|
+
{
|
|
350
|
+
key: "view-scenarios",
|
|
351
|
+
label: "View Scenario Runs",
|
|
352
|
+
color: colors.info,
|
|
353
|
+
icon: figures.arrowRight,
|
|
354
|
+
shortcut: "s",
|
|
355
|
+
},
|
|
356
|
+
];
|
|
357
|
+
// Handle operation selection
|
|
358
|
+
const handleOperation = async (operation, resource) => {
|
|
359
|
+
switch (operation) {
|
|
360
|
+
case "view-scenarios":
|
|
361
|
+
navigate("scenario-run-list", { benchmarkRunId: resource.id });
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
// Build detailed info lines for full details view
|
|
366
|
+
const buildDetailLines = (r) => {
|
|
367
|
+
const lines = [];
|
|
368
|
+
// Core Information
|
|
369
|
+
lines.push(_jsx(Text, { color: colors.warning, bold: true, children: "Benchmark Run Details" }, "core-title"));
|
|
370
|
+
lines.push(_jsxs(Text, { color: colors.idColor, children: [" ", "ID: ", r.id] }, "core-id"));
|
|
371
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Name: ", r.name || "(none)"] }, "core-name"));
|
|
372
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Status: ", r.state] }, "core-status"));
|
|
373
|
+
if (r.benchmark_id) {
|
|
374
|
+
lines.push(_jsxs(Text, { color: colors.idColor, children: [" ", "Benchmark ID: ", r.benchmark_id] }, "core-benchmark"));
|
|
375
|
+
}
|
|
376
|
+
if (r.purpose) {
|
|
377
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Purpose: ", r.purpose] }, "core-purpose"));
|
|
378
|
+
}
|
|
379
|
+
if (r.score !== undefined && r.score !== null) {
|
|
380
|
+
lines.push(_jsxs(Text, { color: colors.success, children: [" ", "Score: ", r.score.toFixed(2)] }, "core-score"));
|
|
381
|
+
}
|
|
382
|
+
lines.push(_jsx(Text, { children: " " }, "core-space"));
|
|
383
|
+
// Timing
|
|
384
|
+
lines.push(_jsx(Text, { color: colors.info, bold: true, children: "Timing" }, "timing-title"));
|
|
385
|
+
if (r.start_time_ms) {
|
|
386
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Started: ", new Date(r.start_time_ms).toLocaleString()] }, "timing-started"));
|
|
387
|
+
}
|
|
388
|
+
const detailEndTimeMs = r.start_time_ms && r.duration_ms
|
|
389
|
+
? r.start_time_ms + r.duration_ms
|
|
390
|
+
: undefined;
|
|
391
|
+
if (detailEndTimeMs) {
|
|
392
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Ended: ", new Date(detailEndTimeMs).toLocaleString()] }, "timing-ended"));
|
|
393
|
+
}
|
|
394
|
+
if (r.duration_ms) {
|
|
395
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", "Duration: ", formatDuration(r.duration_ms)] }, "timing-duration"));
|
|
396
|
+
}
|
|
397
|
+
lines.push(_jsx(Text, { children: " " }, "timing-space"));
|
|
398
|
+
// Secrets Provided
|
|
399
|
+
if (r.secrets_provided && Object.keys(r.secrets_provided).length > 0) {
|
|
400
|
+
lines.push(_jsx(Text, { color: colors.warning, bold: true, children: "Secrets Provided" }, "secrets-title"));
|
|
401
|
+
Object.entries(r.secrets_provided).forEach(([envVar, secretName], idx) => {
|
|
402
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", envVar, " \u2192 ", secretName] }, `secret-${idx}`));
|
|
403
|
+
});
|
|
404
|
+
lines.push(_jsx(Text, { children: " " }, "secrets-space"));
|
|
405
|
+
}
|
|
406
|
+
// Metadata
|
|
407
|
+
if (r.metadata && Object.keys(r.metadata).length > 0) {
|
|
408
|
+
lines.push(_jsx(Text, { color: colors.secondary, bold: true, children: "Metadata" }, "meta-title"));
|
|
409
|
+
Object.entries(r.metadata).forEach(([key, value], idx) => {
|
|
410
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", key, ": ", value] }, `meta-${idx}`));
|
|
411
|
+
});
|
|
412
|
+
lines.push(_jsx(Text, { children: " " }, "meta-space"));
|
|
413
|
+
}
|
|
414
|
+
// Raw JSON
|
|
415
|
+
lines.push(_jsx(Text, { color: colors.warning, bold: true, children: "Raw JSON" }, "json-title"));
|
|
416
|
+
const jsonLines = JSON.stringify(r, null, 2).split("\n");
|
|
417
|
+
jsonLines.forEach((line, idx) => {
|
|
418
|
+
lines.push(_jsxs(Text, { dimColor: true, children: [" ", line] }, `json-${idx}`));
|
|
419
|
+
});
|
|
420
|
+
return lines;
|
|
421
|
+
};
|
|
422
|
+
// Check if run is still in progress for polling
|
|
423
|
+
const isRunning = run.state === "running";
|
|
424
|
+
return (_jsx(ResourceDetailPage, { resource: run, resourceType: "Benchmark Runs", getDisplayName: (r) => r.name || r.id, getId: (r) => r.id, getStatus: (r) => r.state, detailSections: detailSections, operations: operations, onOperation: handleOperation, onBack: goBack, buildDetailLines: buildDetailLines, pollResource: isRunning ? pollRun : undefined, breadcrumbPrefix: [{ label: "Home" }, { label: "Benchmarks" }] }));
|
|
425
|
+
}
|