@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.
Files changed (73) hide show
  1. package/README.md +19 -5
  2. package/dist/cli.js +0 -0
  3. package/dist/commands/blueprint/delete.js +21 -0
  4. package/dist/commands/blueprint/list.js +226 -174
  5. package/dist/commands/blueprint/prune.js +13 -28
  6. package/dist/commands/devbox/create.js +41 -0
  7. package/dist/commands/devbox/list.js +125 -109
  8. package/dist/commands/devbox/tunnel.js +4 -19
  9. package/dist/commands/gateway-config/create.js +44 -0
  10. package/dist/commands/gateway-config/delete.js +21 -0
  11. package/dist/commands/gateway-config/get.js +15 -0
  12. package/dist/commands/gateway-config/list.js +493 -0
  13. package/dist/commands/gateway-config/update.js +60 -0
  14. package/dist/commands/menu.js +2 -1
  15. package/dist/commands/secret/list.js +379 -4
  16. package/dist/commands/snapshot/list.js +11 -2
  17. package/dist/commands/snapshot/prune.js +265 -0
  18. package/dist/components/BenchmarkMenu.js +108 -0
  19. package/dist/components/DetailedInfoView.js +20 -0
  20. package/dist/components/DevboxActionsMenu.js +9 -61
  21. package/dist/components/DevboxCreatePage.js +531 -14
  22. package/dist/components/DevboxDetailPage.js +27 -22
  23. package/dist/components/GatewayConfigCreatePage.js +265 -0
  24. package/dist/components/LogsViewer.js +6 -40
  25. package/dist/components/MainMenu.js +63 -22
  26. package/dist/components/ResourceDetailPage.js +143 -160
  27. package/dist/components/ResourceListView.js +3 -33
  28. package/dist/components/ResourcePicker.js +220 -0
  29. package/dist/components/SecretCreatePage.js +183 -0
  30. package/dist/components/SettingsMenu.js +95 -0
  31. package/dist/components/StateHistory.js +1 -20
  32. package/dist/components/StatusBadge.js +80 -0
  33. package/dist/components/StreamingLogsViewer.js +8 -42
  34. package/dist/components/form/FormTextInput.js +4 -2
  35. package/dist/components/resourceDetailTypes.js +18 -0
  36. package/dist/hooks/useInputHandler.js +103 -0
  37. package/dist/router/Router.js +99 -2
  38. package/dist/screens/BenchmarkDetailScreen.js +163 -0
  39. package/dist/screens/BenchmarkJobCreateScreen.js +524 -0
  40. package/dist/screens/BenchmarkJobDetailScreen.js +614 -0
  41. package/dist/screens/BenchmarkJobListScreen.js +479 -0
  42. package/dist/screens/BenchmarkListScreen.js +266 -0
  43. package/dist/screens/BenchmarkMenuScreen.js +29 -0
  44. package/dist/screens/BenchmarkRunDetailScreen.js +425 -0
  45. package/dist/screens/BenchmarkRunListScreen.js +275 -0
  46. package/dist/screens/BlueprintDetailScreen.js +5 -1
  47. package/dist/screens/DevboxCreateScreen.js +2 -2
  48. package/dist/screens/GatewayConfigDetailScreen.js +236 -0
  49. package/dist/screens/GatewayConfigListScreen.js +7 -0
  50. package/dist/screens/MenuScreen.js +5 -2
  51. package/dist/screens/ScenarioRunDetailScreen.js +226 -0
  52. package/dist/screens/ScenarioRunListScreen.js +245 -0
  53. package/dist/screens/SecretCreateScreen.js +7 -0
  54. package/dist/screens/SecretDetailScreen.js +198 -0
  55. package/dist/screens/SecretListScreen.js +7 -0
  56. package/dist/screens/SettingsMenuScreen.js +26 -0
  57. package/dist/screens/SnapshotDetailScreen.js +6 -0
  58. package/dist/services/agentService.js +42 -0
  59. package/dist/services/benchmarkJobService.js +122 -0
  60. package/dist/services/benchmarkService.js +120 -0
  61. package/dist/services/gatewayConfigService.js +114 -0
  62. package/dist/services/scenarioService.js +34 -0
  63. package/dist/store/benchmarkJobStore.js +66 -0
  64. package/dist/store/benchmarkStore.js +183 -0
  65. package/dist/store/betaFeatureStore.js +47 -0
  66. package/dist/store/gatewayConfigStore.js +83 -0
  67. package/dist/store/index.js +1 -0
  68. package/dist/utils/browser.js +22 -0
  69. package/dist/utils/clipboard.js +41 -0
  70. package/dist/utils/commands.js +80 -0
  71. package/dist/utils/config.js +8 -0
  72. package/dist/utils/time.js +121 -0
  73. package/package.json +42 -43
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * BenchmarkMenu - Sub-menu for benchmark-related resources
4
+ */
5
+ import React from "react";
6
+ import { Box, Text, useInput, useApp, useStdout } from "ink";
7
+ import figures from "figures";
8
+ import { Breadcrumb } from "./Breadcrumb.js";
9
+ import { NavigationTips } from "./NavigationTips.js";
10
+ import { colors } from "../utils/theme.js";
11
+ import { useExitOnCtrlC } from "../hooks/useExitOnCtrlC.js";
12
+ const benchmarkMenuItems = [
13
+ {
14
+ key: "benchmarks",
15
+ label: "Benchmarks",
16
+ description: "View benchmark definitions",
17
+ icon: "◉",
18
+ color: colors.primary,
19
+ },
20
+ {
21
+ key: "benchmark-runs",
22
+ label: "Benchmark Runs",
23
+ description: "View and manage benchmark executions",
24
+ icon: "▶",
25
+ color: colors.success,
26
+ },
27
+ {
28
+ key: "benchmark-jobs",
29
+ label: "Benchmark Jobs",
30
+ description: "Run and manage benchmark jobs",
31
+ icon: "▣",
32
+ color: colors.warning,
33
+ },
34
+ {
35
+ key: "scenario-runs",
36
+ label: "Scenario Runs",
37
+ description: "View individual scenario results",
38
+ icon: "◈",
39
+ color: colors.info,
40
+ },
41
+ ];
42
+ export const BenchmarkMenu = ({ onSelect, onBack }) => {
43
+ const { exit } = useApp();
44
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
45
+ const { stdout } = useStdout();
46
+ // Get terminal dimensions for responsive layout
47
+ const getTerminalDimensions = React.useCallback(() => {
48
+ return {
49
+ height: stdout?.rows && stdout.rows > 0 ? stdout.rows : 20,
50
+ width: stdout?.columns && stdout.columns > 0 ? stdout.columns : 80,
51
+ };
52
+ }, [stdout]);
53
+ const [terminalDimensions, setTerminalDimensions] = React.useState(getTerminalDimensions);
54
+ React.useEffect(() => {
55
+ setTerminalDimensions(getTerminalDimensions());
56
+ if (!stdout)
57
+ return;
58
+ const handleResize = () => {
59
+ setTerminalDimensions(getTerminalDimensions());
60
+ };
61
+ stdout.on("resize", handleResize);
62
+ return () => {
63
+ stdout.off("resize", handleResize);
64
+ };
65
+ }, [stdout, getTerminalDimensions]);
66
+ const terminalWidth = terminalDimensions.width;
67
+ const isNarrow = terminalWidth < 70;
68
+ // Handle Ctrl+C to exit
69
+ useExitOnCtrlC();
70
+ useInput((input, key) => {
71
+ if (key.upArrow && selectedIndex > 0) {
72
+ setSelectedIndex(selectedIndex - 1);
73
+ }
74
+ else if (key.downArrow && selectedIndex < benchmarkMenuItems.length - 1) {
75
+ setSelectedIndex(selectedIndex + 1);
76
+ }
77
+ else if (key.return) {
78
+ onSelect(benchmarkMenuItems[selectedIndex].key);
79
+ }
80
+ else if (key.escape) {
81
+ onBack();
82
+ }
83
+ else if (input === "1") {
84
+ onSelect("benchmarks");
85
+ }
86
+ else if (input === "2") {
87
+ onSelect("benchmark-runs");
88
+ }
89
+ else if (input === "3") {
90
+ onSelect("benchmark-jobs");
91
+ }
92
+ else if (input === "4") {
93
+ onSelect("scenario-runs");
94
+ }
95
+ else if (input === "q") {
96
+ exit();
97
+ }
98
+ });
99
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Breadcrumb, { items: [{ label: "Home" }, { label: "Benchmarks", active: true }] }), _jsxs(Box, { paddingX: 2, marginBottom: 1, children: [_jsx(Text, { color: colors.primary, bold: true, children: "Benchmarks" }), _jsx(Text, { color: colors.textDim, dimColor: true, children: isNarrow ? "" : " • Performance testing and evaluation" })] }), _jsx(Box, { flexDirection: "column", paddingX: 2, children: benchmarkMenuItems.map((item, index) => {
100
+ const isSelected = index === selectedIndex;
101
+ return (_jsxs(Box, { marginBottom: 0, children: [_jsx(Text, { color: isSelected ? item.color : colors.textDim, children: isSelected ? figures.pointer : " " }), _jsx(Text, { children: " " }), _jsx(Text, { color: item.color, bold: true, children: item.icon }), _jsx(Text, { children: " " }), _jsx(Text, { color: isSelected ? item.color : colors.text, bold: isSelected, children: item.label }), !isNarrow && (_jsxs(Text, { color: colors.textDim, dimColor: true, children: [" ", "- ", item.description] })), _jsxs(Text, { color: colors.textDim, dimColor: true, children: [" ", "[", index + 1, "]"] })] }, item.key));
102
+ }) }), _jsx(NavigationTips, { showArrows: true, paddingX: 2, tips: [
103
+ { key: "1-4", label: "Quick select" },
104
+ { key: "Enter", label: "Select" },
105
+ { key: "Esc", label: "Back" },
106
+ { key: "q", label: "Quit" },
107
+ ] })] }));
108
+ };
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import figures from "figures";
4
+ import { Header } from "./Header.js";
5
+ import { StatusBadge } from "./StatusBadge.js";
6
+ import { Breadcrumb } from "./Breadcrumb.js";
7
+ import { colors } from "../utils/theme.js";
8
+ export function DetailedInfoView({ detailLines, scrollOffset, viewportHeight, displayName, resourceId, status, resourceType, breadcrumbPrefix = [], }) {
9
+ const maxScroll = Math.max(0, detailLines.length - viewportHeight);
10
+ const actualScroll = Math.min(scrollOffset, maxScroll);
11
+ const visibleLines = detailLines.slice(actualScroll, actualScroll + viewportHeight);
12
+ const hasMore = actualScroll + viewportHeight < detailLines.length;
13
+ const hasLess = actualScroll > 0;
14
+ return (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: [
15
+ ...breadcrumbPrefix,
16
+ { label: resourceType },
17
+ { label: displayName },
18
+ { label: "Full Details", active: true },
19
+ ] }), _jsx(Header, { title: `${displayName} - Complete Information` }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Box, { marginBottom: 1, children: [_jsx(StatusBadge, { status: status }), _jsx(Text, { children: " " }), _jsx(Text, { color: colors.idColor, children: resourceId })] }) }), _jsx(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, borderStyle: "round", borderColor: colors.border, paddingX: 2, paddingY: 1, children: _jsx(Box, { flexDirection: "column", children: visibleLines }) }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: colors.textDim, dimColor: true, children: [figures.arrowUp, figures.arrowDown, " Scroll \u2022 Line ", actualScroll + 1, "-", Math.min(actualScroll + viewportHeight, detailLines.length), " of", " ", detailLines.length] }), hasLess && _jsxs(Text, { color: colors.primary, children: [" ", figures.arrowUp] }), hasMore && _jsxs(Text, { color: colors.primary, children: [" ", figures.arrowDown] }), _jsxs(Text, { color: colors.textDim, dimColor: true, children: [" ", "\u2022 [q or esc] Back to Details"] })] })] }));
20
+ }
@@ -11,6 +11,8 @@ import { Breadcrumb } from "./Breadcrumb.js";
11
11
  import { NavigationTips } from "./NavigationTips.js";
12
12
  import { ConfirmationPrompt } from "./ConfirmationPrompt.js";
13
13
  import { colors } from "../utils/theme.js";
14
+ import { openInBrowser } from "../utils/browser.js";
15
+ import { copyToClipboard } from "../utils/clipboard.js";
14
16
  import { useViewportHeight } from "../hooks/useViewportHeight.js";
15
17
  import { useNavigation } from "../store/navigationStore.js";
16
18
  import { useExitOnCtrlC } from "../hooks/useExitOnCtrlC.js";
@@ -393,31 +395,9 @@ export const DevboxActionsMenu = ({ devbox, onBack, breadcrumbItems = [
393
395
  // Open tunnel URL in browser
394
396
  const tunnelUrl = operationResult.__tunnelUrl;
395
397
  if (tunnelUrl) {
396
- const openBrowser = async () => {
397
- const { exec } = await import("child_process");
398
- const platform = process.platform;
399
- let openCommand;
400
- if (platform === "darwin") {
401
- openCommand = `open "${tunnelUrl}"`;
402
- }
403
- else if (platform === "win32") {
404
- openCommand = `start "${tunnelUrl}"`;
405
- }
406
- else {
407
- openCommand = `xdg-open "${tunnelUrl}"`;
408
- }
409
- exec(openCommand, (error) => {
410
- if (error) {
411
- setCopyStatus("Could not open browser");
412
- setTimeout(() => setCopyStatus(null), 2000);
413
- }
414
- else {
415
- setCopyStatus("Opened in browser!");
416
- setTimeout(() => setCopyStatus(null), 2000);
417
- }
418
- });
419
- };
420
- openBrowser();
398
+ openInBrowser(tunnelUrl);
399
+ setCopyStatus("Opened in browser!");
400
+ setTimeout(() => setCopyStatus(null), 2000);
421
401
  }
422
402
  }
423
403
  else if ((key.upArrow || input === "k") &&
@@ -469,42 +449,10 @@ export const DevboxActionsMenu = ({ devbox, onBack, breadcrumbItems = [
469
449
  // Copy exec output to clipboard
470
450
  const output = (operationResult.stdout || "") +
471
451
  (operationResult.stderr || "");
472
- const copyToClipboard = async (text) => {
473
- const { spawn } = await import("child_process");
474
- const platform = process.platform;
475
- let command;
476
- let args;
477
- if (platform === "darwin") {
478
- command = "pbcopy";
479
- args = [];
480
- }
481
- else if (platform === "win32") {
482
- command = "clip";
483
- args = [];
484
- }
485
- else {
486
- command = "xclip";
487
- args = ["-selection", "clipboard"];
488
- }
489
- const proc = spawn(command, args);
490
- proc.stdin.write(text);
491
- proc.stdin.end();
492
- proc.on("exit", (code) => {
493
- if (code === 0) {
494
- setCopyStatus("Copied to clipboard!");
495
- setTimeout(() => setCopyStatus(null), 2000);
496
- }
497
- else {
498
- setCopyStatus("Failed to copy");
499
- setTimeout(() => setCopyStatus(null), 2000);
500
- }
501
- });
502
- proc.on("error", () => {
503
- setCopyStatus("Copy not supported");
504
- setTimeout(() => setCopyStatus(null), 2000);
505
- });
506
- };
507
- copyToClipboard(output);
452
+ copyToClipboard(output).then((status) => {
453
+ setCopyStatus(status);
454
+ setTimeout(() => setCopyStatus(null), 2000);
455
+ });
508
456
  }
509
457
  return;
510
458
  }