Skip to content

Commit 0dc3485

Browse files
committed
cp dines
1 parent 36bdc2e commit 0dc3485

13 files changed

Lines changed: 107 additions & 118 deletions

src/commands/devbox/list.tsx

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,10 @@ const ListDevboxesUI = ({
9494
// Fetch ONE page only
9595
const page = (await client.devboxes.list(queryParams)) as unknown as DevboxesCursorIDPage<Devbox>;
9696

97-
// Extract data and create defensive copies
97+
// Extract data and create defensive copies using JSON serialization
9898
if (page.devboxes && Array.isArray(page.devboxes)) {
9999
page.devboxes.forEach((d: Devbox) => {
100-
const plain: Record<string, unknown> = {};
101-
for (const key in d) {
102-
const value = (d as unknown as Record<string, unknown>)[key];
103-
if (value === null || value === undefined) {
104-
plain[key] = value;
105-
} else if (Array.isArray(value)) {
106-
plain[key] = [...value];
107-
} else if (typeof value === "object") {
108-
plain[key] = JSON.parse(JSON.stringify(value));
109-
} else {
110-
plain[key] = value;
111-
}
112-
}
113-
pageDevboxes.push(plain as Devbox);
100+
pageDevboxes.push(JSON.parse(JSON.stringify(d)) as Devbox);
114101
});
115102
}
116103

@@ -303,9 +290,7 @@ const ListDevboxesUI = ({
303290
"capabilities",
304291
"Capabilities",
305292
(devbox: Devbox) => {
306-
const caps = [];
307-
if (devbox?.entitlements?.network_enabled) caps.push("net");
308-
if (devbox?.entitlements?.gpu_enabled) caps.push("gpu");
293+
const caps = devbox?.capabilities || [];
309294
const text = caps.length > 0 ? caps.join(",") : "-";
310295
return text.length > 20 ? text.substring(0, 17) + "..." : text;
311296
},

src/commands/mcp-install.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export async function installMcpConfig() {
4747
console.log(`📍 rli command location: ${rliPath}\n`);
4848

4949
// Read or create config
50-
let config: any = { mcpServers: {} };
50+
let config: { mcpServers: Record<string, unknown>; [key: string]: unknown } = { mcpServers: {} };
5151

5252
if (existsSync(configPath)) {
5353
console.log("✓ Found existing Claude Desktop config");
@@ -136,8 +136,9 @@ export async function installMcpConfig() {
136136
console.log(
137137
'\n💡 Tip: Make sure you\'ve run "rli auth" to configure your API key first!',
138138
);
139-
} catch (error: any) {
140-
console.error("\n❌ Error installing MCP configuration:", error.message);
139+
} catch (error) {
140+
const errorMessage = error instanceof Error ? error.message : String(error);
141+
console.error("\n❌ Error installing MCP configuration:", errorMessage);
141142
console.error(
142143
"\n💡 You can manually add this configuration to your Claude Desktop config:",
143144
);

src/components/ActionsPopup.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import figures from "figures";
44
import chalk from "chalk";
55
import { isLightMode } from "../utils/theme.js";
66

7-
// Generic resource type - accepts any object with an id
7+
// Generic resource type - accepts any object with an id and optional name
88
interface ResourceWithId {
99
id: string;
10-
[key: string]: unknown;
10+
name?: string | null;
1111
}
1212

1313
interface ActionsPopupProps {

src/components/DetailView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ export const DetailView = ({ sections }: DetailViewProps) => {
4949
* Helper to build detail sections from an object
5050
*/
5151
export function buildDetailSections(
52-
data: Record<string, any>,
52+
data: Record<string, unknown>,
5353
config: {
5454
[sectionName: string]: {
5555
fields: Array<{
5656
key: string;
5757
label: string;
58-
formatter?: (value: any) => string | React.ReactNode;
58+
formatter?: (value: unknown) => string | React.ReactNode;
5959
color?: string;
6060
}>;
6161
};

src/components/DevboxCreatePage.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from "react";
22
import { Box, Text, useInput } from "ink";
33
import TextInput from "ink-text-input";
44
import figures from "figures";
5+
import type { DevboxCreateParams, DevboxView } from "@runloop/api-client/resources/devboxes/devboxes";
6+
import type { LaunchParameters } from "@runloop/api-client/resources/shared";
57
import { getClient } from "../utils/client.js";
68
import { SpinnerComponent } from "./Spinner.js";
79
import { ErrorMessage } from "./ErrorMessage.js";
@@ -13,7 +15,7 @@ import { useExitOnCtrlC } from "../hooks/useExitOnCtrlC.js";
1315

1416
interface DevboxCreatePageProps {
1517
onBack: () => void;
16-
onCreate?: (devbox: any) => void;
18+
onCreate?: (devbox: DevboxView) => void;
1719
initialBlueprintId?: string;
1820
}
1921

@@ -77,7 +79,7 @@ export const DevboxCreatePage = ({
7779
>(null);
7880
const [selectedMetadataIndex, setSelectedMetadataIndex] = React.useState(-1); // -1 means "add new" row
7981
const [creating, setCreating] = React.useState(false);
80-
const [result, setResult] = React.useState<any>(null);
82+
const [result, setResult] = React.useState<DevboxView | null>(null);
8183
const [error, setError] = React.useState<Error | null>(null);
8284

8385
const baseFields: Array<{
@@ -122,7 +124,7 @@ export const DevboxCreatePage = ({
122124

123125
const fields = [...baseFields, ...customFields, ...remainingFields];
124126

125-
const architectures = ["arm64", "x86_64"];
127+
const architectures = ["arm64", "x86_64"] as const;
126128
const resourceSizes = [
127129
"X_SMALL",
128130
"SMALL",
@@ -131,7 +133,7 @@ export const DevboxCreatePage = ({
131133
"X_LARGE",
132134
"XX_LARGE",
133135
"CUSTOM_SIZE",
134-
];
136+
] as const;
135137

136138
const currentFieldIndex = fields.findIndex((f) => f.key === currentField);
137139

@@ -318,13 +320,16 @@ export const DevboxCreatePage = ({
318320
architecture: architectures[newIndex] as "arm64" | "x86_64",
319321
});
320322
} else if (currentField === "resource_size") {
321-
const currentIndex = resourceSizes.indexOf(formData.resource_size);
323+
// Find current index, defaulting to 0 if not found (e.g., empty string)
324+
const currentSize = formData.resource_size || "SMALL";
325+
const currentIndex = resourceSizes.indexOf(currentSize as typeof resourceSizes[number]);
326+
const safeIndex = currentIndex === -1 ? 0 : currentIndex;
322327
const newIndex = key.leftArrow
323-
? Math.max(0, currentIndex - 1)
324-
: Math.min(resourceSizes.length - 1, currentIndex + 1);
328+
? Math.max(0, safeIndex - 1)
329+
: Math.min(resourceSizes.length - 1, safeIndex + 1);
325330
setFormData({
326331
...formData,
327-
resource_size: resourceSizes[newIndex] as any,
332+
resource_size: resourceSizes[newIndex],
328333
});
329334
}
330335
return;
@@ -387,7 +392,7 @@ export const DevboxCreatePage = ({
387392
try {
388393
const client = getClient();
389394

390-
const launchParameters: any = {};
395+
const launchParameters: LaunchParameters = {};
391396

392397
if (formData.architecture) {
393398
launchParameters.architecture = formData.architecture;
@@ -412,7 +417,7 @@ export const DevboxCreatePage = ({
412417
);
413418
}
414419

415-
const createParams: any = {};
420+
const createParams: DevboxCreateParams = {};
416421

417422
if (formData.name) {
418423
createParams.name = formData.name;

src/components/DevboxDetailPage.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import { colors } from "../utils/theme.js";
1111
import { useViewportHeight } from "../hooks/useViewportHeight.js";
1212
import { useExitOnCtrlC } from "../hooks/useExitOnCtrlC.js";
1313
import { getDevbox } from "../services/devboxService.js";
14+
import type { Devbox } from "../store/devboxStore.js";
1415

1516
interface DevboxDetailPageProps {
16-
devbox: any;
17+
devbox: Devbox;
1718
onBack: () => void;
1819
}
1920

@@ -313,12 +314,14 @@ export const DevboxDetailPage = ({
313314
Status: {capitalize(selectedDevbox.status)}
314315
</Text>,
315316
);
316-
lines.push(
317-
<Text key="core-created" dimColor>
318-
{" "}
319-
Created: {new Date(selectedDevbox.create_time_ms).toLocaleString()}
320-
</Text>,
321-
);
317+
if (selectedDevbox.create_time_ms) {
318+
lines.push(
319+
<Text key="core-created" dimColor>
320+
{" "}
321+
Created: {new Date(selectedDevbox.create_time_ms).toLocaleString()}
322+
</Text>,
323+
);
324+
}
322325
if (selectedDevbox.end_time_ms) {
323326
lines.push(
324327
<Text key="core-ended" dimColor>
@@ -582,8 +585,8 @@ export const DevboxDetailPage = ({
582585
State History
583586
</Text>,
584587
);
585-
selectedDevbox.state_transitions.forEach(
586-
(transition: any, idx: number) => {
588+
(selectedDevbox.state_transitions as Array<{ status: string; transition_time_ms?: number }>).forEach(
589+
(transition, idx: number) => {
587590
const text = `${idx + 1}. ${capitalize(transition.status)}${transition.transition_time_ms ? ` at ${new Date(transition.transition_time_ms).toLocaleString()}` : ""}`;
588591
lines.push(
589592
<Text key={`state-${idx}`} dimColor>

src/components/ResourceActionsMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type OperationDef = {
1818
};
1919

2020
interface BaseProps {
21-
resource: Record<string, unknown>;
21+
resource: { id: string; name?: string | null };
2222
onBack: () => void;
2323
breadcrumbItems?: Array<{ label: string; active?: boolean }>;
2424
initialOperation?: string;

src/screens/DevboxDetailScreen.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import React from "react";
66
import { useNavigation } from "../store/navigationStore.js";
7-
import { useDevboxStore } from "../store/devboxStore.js";
7+
import { useDevboxStore, type Devbox } from "../store/devboxStore.js";
88
import { DevboxDetailPage } from "../components/DevboxDetailPage.js";
99
import { getDevbox } from "../services/devboxService.js";
1010
import { SpinnerComponent } from "../components/Spinner.js";
@@ -22,7 +22,7 @@ export function DevboxDetailScreen({ devboxId }: DevboxDetailScreenProps) {
2222

2323
const [loading, setLoading] = React.useState(false);
2424
const [error, setError] = React.useState<Error | null>(null);
25-
const [fetchedDevbox, setFetchedDevbox] = React.useState<any>(null);
25+
const [fetchedDevbox, setFetchedDevbox] = React.useState<Devbox | null>(null);
2626

2727
// Find devbox in store first
2828
const devboxFromStore = devboxes.find((d) => d.id === devboxId);
@@ -91,5 +91,10 @@ export function DevboxDetailScreen({ devboxId }: DevboxDetailScreenProps) {
9191
);
9292
}
9393

94+
// At this point devbox is guaranteed to exist (loading check above handles the null case)
95+
if (!devbox) {
96+
return null; // TypeScript guard - should never reach here
97+
}
98+
9499
return <DevboxDetailPage devbox={devbox} onBack={goBack} />;
95100
}

src/screens/MenuScreen.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* MenuScreen - Main menu using navigation context
33
*/
44
import React from "react";
5-
import { useNavigation } from "../store/navigationStore.js";
5+
import { useNavigation, type ScreenName } from "../store/navigationStore.js";
66
import { MainMenu } from "../components/MainMenu.js";
77

88
export function MenuScreen() {
@@ -20,7 +20,8 @@ export function MenuScreen() {
2020
navigate("snapshot-list");
2121
break;
2222
default:
23-
navigate(key as any);
23+
// Fallback for any other screen names
24+
navigate(key as ScreenName);
2425
}
2526
};
2627

src/services/blueprintService.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*/
44
import { getClient } from "../utils/client.js";
55
import type { Blueprint } from "../store/blueprintStore.js";
6+
import type { BlueprintListParams, BlueprintView } from "@runloop/api-client/resources/blueprints";
7+
import type { BlueprintsCursorIDPage } from "@runloop/api-client/pagination";
68

79
export interface ListBlueprintsOptions {
810
limit: number;
@@ -24,44 +26,48 @@ export async function listBlueprints(
2426
): Promise<ListBlueprintsResult> {
2527
const client = getClient();
2628

27-
const queryParams: any = {
29+
const queryParams: BlueprintListParams = {
2830
limit: options.limit,
2931
};
3032

3133
if (options.startingAfter) {
3234
queryParams.starting_after = options.startingAfter;
3335
}
3436
if (options.search) {
35-
queryParams.search = options.search;
37+
queryParams.name = options.search;
3638
}
3739

3840
const pagePromise = client.blueprints.list(queryParams);
39-
let page = (await pagePromise) as any;
41+
const page = (await pagePromise) as unknown as BlueprintsCursorIDPage<BlueprintView>;
4042

4143
const blueprints: Blueprint[] = [];
4244

4345
if (page.blueprints && Array.isArray(page.blueprints)) {
44-
page.blueprints.forEach((b: any) => {
46+
page.blueprints.forEach((b: BlueprintView) => {
4547
// CRITICAL: Truncate all strings to prevent Yoga crashes
4648
const MAX_ID_LENGTH = 100;
4749
const MAX_NAME_LENGTH = 200;
4850
const MAX_STATUS_LENGTH = 50;
4951
const MAX_ARCH_LENGTH = 50;
5052
const MAX_RESOURCES_LENGTH = 100;
5153

54+
// Extract architecture and resources from launch_parameters
55+
const architecture = b.parameters?.launch_parameters?.architecture;
56+
const resources = b.parameters?.launch_parameters?.resource_size_request;
57+
5258
blueprints.push({
5359
id: String(b.id || "").substring(0, MAX_ID_LENGTH),
5460
name: String(b.name || "").substring(0, MAX_NAME_LENGTH),
5561
status: String(b.status || "").substring(0, MAX_STATUS_LENGTH),
5662
create_time_ms: b.create_time_ms,
57-
build_status: b.build_status
58-
? String(b.build_status).substring(0, MAX_STATUS_LENGTH)
63+
build_status: b.status
64+
? String(b.status).substring(0, MAX_STATUS_LENGTH)
5965
: undefined,
60-
architecture: b.architecture
61-
? String(b.architecture).substring(0, MAX_ARCH_LENGTH)
66+
architecture: architecture
67+
? String(architecture).substring(0, MAX_ARCH_LENGTH)
6268
: undefined,
63-
resources: b.resources
64-
? String(b.resources).substring(0, MAX_RESOURCES_LENGTH)
69+
resources: resources
70+
? String(resources).substring(0, MAX_RESOURCES_LENGTH)
6571
: undefined,
6672
});
6773
});
@@ -73,8 +79,6 @@ export async function listBlueprints(
7379
hasMore: page.has_more || false,
7480
};
7581

76-
page = null as any;
77-
7882
return result;
7983
}
8084

0 commit comments

Comments
 (0)