@runloop/rl-cli 0.0.3 → 0.1.1
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 +64 -29
- package/dist/cli.js +401 -92
- package/dist/commands/auth.js +12 -11
- package/dist/commands/blueprint/create.js +108 -0
- package/dist/commands/blueprint/get.js +37 -0
- package/dist/commands/blueprint/list.js +293 -225
- package/dist/commands/blueprint/logs.js +40 -0
- package/dist/commands/blueprint/preview.js +45 -0
- package/dist/commands/devbox/create.js +10 -9
- package/dist/commands/devbox/delete.js +8 -8
- package/dist/commands/devbox/download.js +49 -0
- package/dist/commands/devbox/exec.js +23 -13
- package/dist/commands/devbox/execAsync.js +43 -0
- package/dist/commands/devbox/get.js +37 -0
- package/dist/commands/devbox/getAsync.js +37 -0
- package/dist/commands/devbox/list.js +328 -190
- package/dist/commands/devbox/logs.js +40 -0
- package/dist/commands/devbox/read.js +49 -0
- package/dist/commands/devbox/resume.js +37 -0
- package/dist/commands/devbox/rsync.js +118 -0
- package/dist/commands/devbox/scp.js +122 -0
- package/dist/commands/devbox/shutdown.js +37 -0
- package/dist/commands/devbox/ssh.js +104 -0
- package/dist/commands/devbox/suspend.js +37 -0
- package/dist/commands/devbox/tunnel.js +120 -0
- package/dist/commands/devbox/upload.js +10 -10
- package/dist/commands/devbox/write.js +51 -0
- package/dist/commands/mcp-http.js +37 -0
- package/dist/commands/mcp-install.js +120 -0
- package/dist/commands/mcp.js +30 -0
- package/dist/commands/menu.js +20 -20
- package/dist/commands/object/delete.js +37 -0
- package/dist/commands/object/download.js +88 -0
- package/dist/commands/object/get.js +37 -0
- package/dist/commands/object/list.js +112 -0
- package/dist/commands/object/upload.js +130 -0
- package/dist/commands/snapshot/create.js +12 -11
- package/dist/commands/snapshot/delete.js +8 -8
- package/dist/commands/snapshot/list.js +56 -97
- package/dist/commands/snapshot/status.js +37 -0
- package/dist/components/ActionsPopup.js +16 -13
- package/dist/components/Banner.js +4 -4
- package/dist/components/Breadcrumb.js +55 -5
- package/dist/components/DetailView.js +7 -4
- package/dist/components/DevboxActionsMenu.js +315 -178
- package/dist/components/DevboxCard.js +15 -14
- package/dist/components/DevboxCreatePage.js +147 -113
- package/dist/components/DevboxDetailPage.js +180 -102
- package/dist/components/ErrorMessage.js +5 -4
- package/dist/components/Header.js +4 -3
- package/dist/components/MainMenu.js +34 -33
- package/dist/components/MetadataDisplay.js +17 -9
- package/dist/components/OperationsMenu.js +6 -5
- package/dist/components/ResourceActionsMenu.js +117 -0
- package/dist/components/ResourceListView.js +213 -0
- package/dist/components/Spinner.js +5 -4
- package/dist/components/StatusBadge.js +81 -31
- package/dist/components/SuccessMessage.js +4 -3
- package/dist/components/Table.example.js +53 -23
- package/dist/components/Table.js +19 -11
- package/dist/hooks/useCursorPagination.js +125 -0
- package/dist/mcp/server-http.js +416 -0
- package/dist/mcp/server.js +397 -0
- package/dist/utils/CommandExecutor.js +16 -12
- package/dist/utils/client.js +7 -7
- package/dist/utils/config.js +130 -4
- package/dist/utils/interactiveCommand.js +2 -2
- package/dist/utils/output.js +17 -17
- package/dist/utils/ssh.js +160 -0
- package/dist/utils/sshSession.js +16 -12
- package/dist/utils/theme.js +22 -0
- package/dist/utils/url.js +4 -4
- package/package.json +29 -4
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { getClient } from "../../utils/client.js";
|
|
4
|
+
import { Banner } from "../../components/Banner.js";
|
|
5
|
+
import { SpinnerComponent } from "../../components/Spinner.js";
|
|
6
|
+
import { SuccessMessage } from "../../components/SuccessMessage.js";
|
|
7
|
+
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
|
8
|
+
import { createExecutor } from "../../utils/CommandExecutor.js";
|
|
9
|
+
import { readFile } from "fs/promises";
|
|
10
|
+
const CreateBlueprintUI = ({ name, dockerfile, dockerfilePath, systemSetupCommands, resources, architecture, availablePorts, root, user, }) => {
|
|
11
|
+
const [loading, setLoading] = React.useState(true);
|
|
12
|
+
const [result, setResult] = React.useState(null);
|
|
13
|
+
const [error, setError] = React.useState(null);
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
const createBlueprint = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const client = getClient();
|
|
18
|
+
// Read dockerfile from file if path is provided
|
|
19
|
+
let dockerfileContents = dockerfile;
|
|
20
|
+
if (dockerfilePath) {
|
|
21
|
+
dockerfileContents = await readFile(dockerfilePath, "utf-8");
|
|
22
|
+
}
|
|
23
|
+
// Parse user parameters
|
|
24
|
+
let userParameters = undefined;
|
|
25
|
+
if (user && root) {
|
|
26
|
+
throw new Error("Only one of --user or --root can be specified");
|
|
27
|
+
}
|
|
28
|
+
else if (user) {
|
|
29
|
+
const [username, uid] = user.split(":");
|
|
30
|
+
if (!username || !uid) {
|
|
31
|
+
throw new Error("User must be in format 'username:uid'");
|
|
32
|
+
}
|
|
33
|
+
userParameters = { username, uid: parseInt(uid) };
|
|
34
|
+
}
|
|
35
|
+
else if (root) {
|
|
36
|
+
userParameters = { username: "root", uid: 0 };
|
|
37
|
+
}
|
|
38
|
+
const blueprint = await client.blueprints.create({
|
|
39
|
+
name,
|
|
40
|
+
dockerfile: dockerfileContents,
|
|
41
|
+
system_setup_commands: systemSetupCommands,
|
|
42
|
+
launch_parameters: {
|
|
43
|
+
resource_size_request: resources,
|
|
44
|
+
architecture: architecture,
|
|
45
|
+
available_ports: availablePorts?.map((port) => parseInt(port, 10)),
|
|
46
|
+
user_parameters: userParameters,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
setResult(blueprint);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
setError(err);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
setLoading(false);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
createBlueprint();
|
|
59
|
+
}, [
|
|
60
|
+
name,
|
|
61
|
+
dockerfile,
|
|
62
|
+
dockerfilePath,
|
|
63
|
+
systemSetupCommands,
|
|
64
|
+
resources,
|
|
65
|
+
architecture,
|
|
66
|
+
availablePorts,
|
|
67
|
+
root,
|
|
68
|
+
user,
|
|
69
|
+
]);
|
|
70
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Creating blueprint..." }), result && (_jsx(SuccessMessage, { message: "Blueprint created successfully", details: `ID: ${result.id}\nName: ${result.name}\nStatus: ${result.status}` })), error && (_jsx(ErrorMessage, { message: "Failed to create blueprint", error: error }))] }));
|
|
71
|
+
};
|
|
72
|
+
export async function createBlueprint(options) {
|
|
73
|
+
const executor = createExecutor({ output: options.output });
|
|
74
|
+
await executor.executeAction(async () => {
|
|
75
|
+
const client = executor.getClient();
|
|
76
|
+
// Read dockerfile from file if path is provided
|
|
77
|
+
let dockerfileContents = options.dockerfile;
|
|
78
|
+
if (options.dockerfilePath) {
|
|
79
|
+
dockerfileContents = await readFile(options.dockerfilePath, "utf-8");
|
|
80
|
+
}
|
|
81
|
+
// Parse user parameters
|
|
82
|
+
let userParameters = undefined;
|
|
83
|
+
if (options.user && options.root) {
|
|
84
|
+
throw new Error("Only one of --user or --root can be specified");
|
|
85
|
+
}
|
|
86
|
+
else if (options.user) {
|
|
87
|
+
const [username, uid] = options.user.split(":");
|
|
88
|
+
if (!username || !uid) {
|
|
89
|
+
throw new Error("User must be in format 'username:uid'");
|
|
90
|
+
}
|
|
91
|
+
userParameters = { username, uid: parseInt(uid) };
|
|
92
|
+
}
|
|
93
|
+
else if (options.root) {
|
|
94
|
+
userParameters = { username: "root", uid: 0 };
|
|
95
|
+
}
|
|
96
|
+
return client.blueprints.create({
|
|
97
|
+
name: options.name,
|
|
98
|
+
dockerfile: dockerfileContents,
|
|
99
|
+
system_setup_commands: options.systemSetupCommands,
|
|
100
|
+
launch_parameters: {
|
|
101
|
+
resource_size_request: options.resources,
|
|
102
|
+
architecture: options.architecture,
|
|
103
|
+
available_ports: options.availablePorts?.map((port) => parseInt(port, 10)),
|
|
104
|
+
user_parameters: userParameters,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}, () => (_jsx(CreateBlueprintUI, { name: options.name, dockerfile: options.dockerfile, dockerfilePath: options.dockerfilePath, systemSetupCommands: options.systemSetupCommands, resources: options.resources, architecture: options.architecture, availablePorts: options.availablePorts, root: options.root, user: options.user })));
|
|
108
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { getClient } from "../../utils/client.js";
|
|
4
|
+
import { Banner } from "../../components/Banner.js";
|
|
5
|
+
import { SpinnerComponent } from "../../components/Spinner.js";
|
|
6
|
+
import { SuccessMessage } from "../../components/SuccessMessage.js";
|
|
7
|
+
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
|
8
|
+
import { createExecutor } from "../../utils/CommandExecutor.js";
|
|
9
|
+
const GetBlueprintUI = ({ blueprintId }) => {
|
|
10
|
+
const [loading, setLoading] = React.useState(true);
|
|
11
|
+
const [result, setResult] = React.useState(null);
|
|
12
|
+
const [error, setError] = React.useState(null);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
const getBlueprint = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getClient();
|
|
17
|
+
const blueprint = await client.blueprints.retrieve(blueprintId);
|
|
18
|
+
setResult(blueprint);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
setError(err);
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
getBlueprint();
|
|
28
|
+
}, [blueprintId]);
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Fetching blueprint details..." }), result && (_jsx(SuccessMessage, { message: "Blueprint details retrieved", details: `ID: ${result.id}\nName: ${result.name}\nStatus: ${result.status}\nCreated: ${new Date(result.createdAt).toLocaleString()}` })), error && (_jsx(ErrorMessage, { message: "Failed to get blueprint", error: error }))] }));
|
|
30
|
+
};
|
|
31
|
+
export async function getBlueprint(options) {
|
|
32
|
+
const executor = createExecutor({ output: options.output });
|
|
33
|
+
await executor.executeAction(async () => {
|
|
34
|
+
const client = executor.getClient();
|
|
35
|
+
return client.blueprints.retrieve(options.id);
|
|
36
|
+
}, () => _jsx(GetBlueprintUI, { blueprintId: options.id }));
|
|
37
|
+
}
|