Skip to content

Commit 576b33c

Browse files
committed
cp dines
1 parent 409095d commit 576b33c

4 files changed

Lines changed: 203 additions & 65 deletions

File tree

package-lock.json

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"author": "",
2020
"license": "MIT",
2121
"dependencies": {
22+
"@inkjs/ui": "^2.0.0",
2223
"@runloop/api-client": "^0.55.0",
2324
"chalk": "^5.3.0",
2425
"commander": "^12.1.0",

src/commands/devbox/list.tsx

Lines changed: 158 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -732,94 +732,195 @@ const ListDevboxesUI: React.FC<{ status?: string }> = ({ status }) => {
732732
}
733733

734734
// Operations selection mode
735+
const lp = selectedDevbox.launch_parameters;
736+
const hasResources = lp?.resource_size_request || lp?.custom_cpu_cores || lp?.custom_gb_memory || lp?.custom_disk_size;
737+
const hasCapabilities = selectedDevbox.capabilities && selectedDevbox.capabilities.filter((c: string) => c !== 'unknown').length > 0;
738+
735739
return (
736740
<>
737741
<Header title="Devbox Details" />
738-
<Box flexDirection="column" marginBottom={1}>
742+
743+
{/* Main info card */}
744+
<Box
745+
flexDirection="column"
746+
borderStyle="round"
747+
borderColor="cyan"
748+
paddingX={2}
749+
paddingY={1}
750+
marginBottom={1}
751+
>
739752
<Box marginBottom={1}>
740753
<Text color="cyan" bold>
741754
{selectedDevbox.name || selectedDevbox.id.slice(0, 12)}
742755
</Text>
743-
<Text> </Text>
756+
<Text> </Text>
744757
<StatusBadge status={selectedDevbox.status} />
745758
</Box>
746-
<Box flexDirection="column" gap={1}>
759+
760+
<Box flexDirection="column">
747761
<Box>
748-
<Text color="gray">ID: </Text>
762+
<Text color="gray" dimColor>ID: </Text>
749763
<Text dimColor>{selectedDevbox.id}</Text>
750764
</Box>
751-
<Box>
752-
<Text color="gray">URL: </Text>
753-
<Text color="cyan" dimColor>
754-
https://platform.runloop.ai/devboxes/{selectedDevbox.id}
755-
</Text>
756-
</Box>
765+
757766
{selectedDevbox.create_time_ms && (
758-
<Box>
759-
<Text color="gray">Created: </Text>
767+
<Box marginTop={1}>
768+
<Text color="gray" dimColor>Created: </Text>
760769
<Text dimColor>{new Date(selectedDevbox.create_time_ms).toLocaleString()}</Text>
770+
<Text color="gray" dimColor> ({formatTimeAgo(selectedDevbox.create_time_ms)})</Text>
761771
</Box>
762772
)}
773+
763774
{uptime !== null && selectedDevbox.status === 'running' && (
764775
<Box>
765-
<Text color="gray">Uptime: </Text>
766-
<Text dimColor>{uptime < 60 ? `${uptime}m` : `${Math.floor(uptime / 60)}h ${uptime % 60}m`}</Text>
767-
</Box>
768-
)}
769-
{selectedDevbox.launch_parameters?.keep_alive_time_seconds && (
770-
<Box>
771-
<Text color="gray">Keep Alive: </Text>
772-
<Text dimColor>{Math.floor(selectedDevbox.launch_parameters.keep_alive_time_seconds / 60)}m</Text>
776+
<Text color="gray" dimColor>Uptime: </Text>
777+
<Text color="green" dimColor>{uptime < 60 ? `${uptime}m` : `${Math.floor(uptime / 60)}h ${uptime % 60}m`}</Text>
778+
{lp?.keep_alive_time_seconds && (
779+
<Text color="gray" dimColor> (keep-alive: {Math.floor(lp.keep_alive_time_seconds / 60)}m)</Text>
780+
)}
773781
</Box>
774782
)}
775-
{selectedDevbox.launch_parameters?.resource_size_request && (
776-
<Box>
777-
<Text color="gray">Resource Size: </Text>
778-
<Text dimColor>{selectedDevbox.launch_parameters.resource_size_request}</Text>
779-
</Box>
780-
)}
781-
{selectedDevbox.launch_parameters?.architecture && (
782-
<Box>
783-
<Text color="gray">Architecture: </Text>
784-
<Text dimColor>{selectedDevbox.launch_parameters.architecture}</Text>
785-
</Box>
786-
)}
787-
{selectedDevbox.capabilities && selectedDevbox.capabilities.length > 0 && (
788-
<Box>
789-
<Text color="gray">Capabilities: </Text>
790-
<Text dimColor>{selectedDevbox.capabilities.filter((c: string) => c !== 'unknown').join(', ')}</Text>
783+
</Box>
784+
</Box>
785+
786+
{/* Resources & Config */}
787+
{hasResources && (
788+
<Box
789+
flexDirection="column"
790+
borderStyle="round"
791+
borderColor="yellow"
792+
paddingX={2}
793+
paddingY={1}
794+
marginBottom={1}
795+
>
796+
<Box marginBottom={1}>
797+
<Text color="yellow" bold>{figures.squareSmallFilled} Resources</Text>
798+
</Box>
799+
<Box flexDirection="column">
800+
{lp?.resource_size_request && (
801+
<Box>
802+
<Text color="gray" dimColor>Size: </Text>
803+
<Text color="yellow" dimColor>{lp.resource_size_request}</Text>
804+
</Box>
805+
)}
806+
{lp?.architecture && (
807+
<Box>
808+
<Text color="gray" dimColor>Arch: </Text>
809+
<Text dimColor>{lp.architecture}</Text>
810+
</Box>
811+
)}
812+
{lp?.custom_cpu_cores && (
813+
<Box>
814+
<Text color="gray" dimColor>CPU: </Text>
815+
<Text dimColor>{lp.custom_cpu_cores} cores</Text>
816+
</Box>
817+
)}
818+
{lp?.custom_gb_memory && (
819+
<Box>
820+
<Text color="gray" dimColor>Memory: </Text>
821+
<Text dimColor>{lp.custom_gb_memory}GB</Text>
822+
</Box>
823+
)}
824+
{lp?.custom_disk_size && (
825+
<Box>
826+
<Text color="gray" dimColor>Disk: </Text>
827+
<Text dimColor>{lp.custom_disk_size}GB</Text>
828+
</Box>
829+
)}
830+
</Box>
831+
</Box>
832+
)}
833+
834+
{/* Capabilities & Source */}
835+
<Box flexDirection="row" gap={2} marginBottom={1}>
836+
{hasCapabilities && (
837+
<Box
838+
flexDirection="column"
839+
borderStyle="round"
840+
borderColor="blue"
841+
paddingX={2}
842+
paddingY={1}
843+
flexGrow={1}
844+
>
845+
<Box marginBottom={1}>
846+
<Text color="blue" bold>{figures.tick} Capabilities</Text>
791847
</Box>
792-
)}
793-
{selectedDevbox.blueprint_id && (
794-
<Box>
795-
<Text color="gray">Blueprint: </Text>
796-
<Text dimColor>{selectedDevbox.blueprint_id}</Text>
848+
<Box flexDirection="column">
849+
{selectedDevbox.capabilities.filter((c: string) => c !== 'unknown').map((cap: string) => (
850+
<Box key={cap}>
851+
<Text color="gray" dimColor>{figures.pointer} </Text>
852+
<Text dimColor>{cap}</Text>
853+
</Box>
854+
))}
797855
</Box>
798-
)}
799-
{selectedDevbox.snapshot_id && (
800-
<Box>
801-
<Text color="gray">Snapshot: </Text>
802-
<Text dimColor>{selectedDevbox.snapshot_id}</Text>
856+
</Box>
857+
)}
858+
859+
{(selectedDevbox.blueprint_id || selectedDevbox.snapshot_id) && (
860+
<Box
861+
flexDirection="column"
862+
borderStyle="round"
863+
borderColor="magenta"
864+
paddingX={2}
865+
paddingY={1}
866+
flexGrow={1}
867+
>
868+
<Box marginBottom={1}>
869+
<Text color="magenta" bold>{figures.circleFilled} Source</Text>
803870
</Box>
804-
)}
805-
{selectedDevbox.failure_reason && (
806-
<Box>
807-
<Text color="red">Failure: </Text>
808-
<Text color="red" dimColor>{selectedDevbox.failure_reason}</Text>
871+
<Box flexDirection="column">
872+
{selectedDevbox.blueprint_id && (
873+
<Box>
874+
<Text color="gray" dimColor>Blueprint: </Text>
875+
<Text dimColor>{selectedDevbox.blueprint_id.slice(0, 20)}</Text>
876+
</Box>
877+
)}
878+
{selectedDevbox.snapshot_id && (
879+
<Box>
880+
<Text color="gray" dimColor>Snapshot: </Text>
881+
<Text dimColor>{selectedDevbox.snapshot_id.slice(0, 20)}</Text>
882+
</Box>
883+
)}
809884
</Box>
810-
)}
811-
</Box>
885+
</Box>
886+
)}
812887
</Box>
813888

889+
{/* Metadata */}
814890
{selectedDevbox.metadata && Object.keys(selectedDevbox.metadata).length > 0 && (
815-
<Box marginTop={1}>
816-
<MetadataDisplay metadata={selectedDevbox.metadata} showBorder={true} />
891+
<Box
892+
flexDirection="column"
893+
borderStyle="round"
894+
borderColor="green"
895+
paddingX={2}
896+
paddingY={1}
897+
marginBottom={1}
898+
>
899+
<MetadataDisplay metadata={selectedDevbox.metadata} showBorder={false} />
900+
</Box>
901+
)}
902+
903+
{/* Failure reason */}
904+
{selectedDevbox.failure_reason && (
905+
<Box
906+
flexDirection="column"
907+
borderStyle="round"
908+
borderColor="red"
909+
paddingX={2}
910+
paddingY={1}
911+
marginBottom={1}
912+
>
913+
<Box>
914+
<Text color="red" bold>{figures.cross} Failure: </Text>
915+
<Text color="red" dimColor>{selectedDevbox.failure_reason}</Text>
916+
</Box>
817917
</Box>
818918
)}
819919

920+
{/* Operations */}
820921
<Box flexDirection="column" marginTop={1} marginBottom={1}>
821922
<Text color="cyan" bold>
822-
Select Operation:
923+
{figures.play} Operations
823924
</Text>
824925
<Box marginTop={1} flexDirection="column">
825926
{operations.map((op, index) => {
@@ -842,7 +943,7 @@ const ListDevboxesUI: React.FC<{ status?: string }> = ({ status }) => {
842943
<Box marginTop={1}>
843944
<Text color="gray" dimColor>
844945
{figures.arrowUp}
845-
{figures.arrowDown} Navigate • [Enter] Select • [i] View Details • [o] Open in Browser • [q] Back
946+
{figures.arrowDown} Navigate • [Enter] Select • [i] Full Details • [o] Browser • [q] Back
846947
</Text>
847948
</Box>
848949
</>

src/components/MetadataDisplay.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { Box, Text } from 'ink';
3+
import { Badge } from '@inkjs/ui';
34
import figures from 'figures';
45

56
interface MetadataDisplayProps {
@@ -38,14 +39,9 @@ export const MetadataDisplay: React.FC<MetadataDisplayProps> = ({
3839
{entries.map(([key, value], index) => {
3940
const color = getColorForKey(key, index);
4041
return (
41-
<Box key={key}>
42-
<Text color={color} bold>[</Text>
43-
<Text color={color}>{key}</Text>
44-
<Text color="gray">:</Text>
45-
<Text color="white">{value}</Text>
46-
<Text color={color} bold>]</Text>
47-
<Text> </Text>
48-
</Box>
42+
<Badge key={key} color={color}>
43+
{`${key}: ${value}`}
44+
</Badge>
4945
);
5046
})}
5147
</Box>

0 commit comments

Comments
 (0)