@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,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
import { getClient } from "../../utils/client.js";
|
|
5
|
+
import { Banner } from "../../components/Banner.js";
|
|
6
|
+
import { SpinnerComponent } from "../../components/Spinner.js";
|
|
7
|
+
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
|
8
|
+
import { createExecutor } from "../../utils/CommandExecutor.js";
|
|
9
|
+
import { colors } from "../../utils/theme.js";
|
|
10
|
+
const BlueprintLogsUI = ({ blueprintId }) => {
|
|
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 getLogs = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const client = getClient();
|
|
18
|
+
const logs = await client.blueprints.logs(blueprintId);
|
|
19
|
+
setResult(logs);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
setError(err);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
setLoading(false);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
getLogs();
|
|
29
|
+
}, [blueprintId]);
|
|
30
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && (_jsx(SpinnerComponent, { message: "Fetching blueprint build logs..." })), result && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.primary, children: "Blueprint Build Logs:" }), result.logs && result.logs.length > 0 ? (result.logs.map((log, index) => (_jsxs(Box, { marginLeft: 2, children: [_jsx(Text, { color: colors.textDim, children: log.timestampMs
|
|
31
|
+
? new Date(log.timestampMs).toISOString()
|
|
32
|
+
: "" }), _jsxs(Text, { color: colors.textDim, children: [" [", log.level, "]"] }), _jsxs(Text, { children: [" ", log.message] })] }, index)))) : (_jsx(Text, { color: colors.textDim, children: "No logs available" }))] })), error && (_jsx(ErrorMessage, { message: "Failed to get blueprint logs", error: error }))] }));
|
|
33
|
+
};
|
|
34
|
+
export async function getBlueprintLogs(options) {
|
|
35
|
+
const executor = createExecutor({ output: options.output });
|
|
36
|
+
await executor.executeAction(async () => {
|
|
37
|
+
const client = executor.getClient();
|
|
38
|
+
return client.blueprints.logs(options.id);
|
|
39
|
+
}, () => _jsx(BlueprintLogsUI, { blueprintId: options.id }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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 PreviewBlueprintUI = ({ name, dockerfile, systemSetupCommands }) => {
|
|
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 previewBlueprint = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getClient();
|
|
17
|
+
const blueprint = await client.blueprints.preview({
|
|
18
|
+
name,
|
|
19
|
+
dockerfile,
|
|
20
|
+
system_setup_commands: systemSetupCommands,
|
|
21
|
+
});
|
|
22
|
+
setResult(blueprint);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
setError(err);
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
previewBlueprint();
|
|
32
|
+
}, [name, dockerfile, systemSetupCommands]);
|
|
33
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Previewing blueprint..." }), result && (_jsx(SuccessMessage, { message: "Blueprint preview generated", details: `Name: ${result.name}\nDockerfile: ${result.dockerfile ? "Present" : "Not provided"}\nSetup Commands: ${result.systemSetupCommands?.length || 0}` })), error && (_jsx(ErrorMessage, { message: "Failed to preview blueprint", error: error }))] }));
|
|
34
|
+
};
|
|
35
|
+
export async function previewBlueprint(options) {
|
|
36
|
+
const executor = createExecutor({ output: options.output });
|
|
37
|
+
await executor.executeAction(async () => {
|
|
38
|
+
const client = executor.getClient();
|
|
39
|
+
return client.blueprints.preview({
|
|
40
|
+
name: options.name,
|
|
41
|
+
dockerfile: options.dockerfile,
|
|
42
|
+
system_setup_commands: options.systemSetupCommands,
|
|
43
|
+
});
|
|
44
|
+
}, () => (_jsx(PreviewBlueprintUI, { name: options.name, dockerfile: options.dockerfile, systemSetupCommands: options.systemSetupCommands })));
|
|
45
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React from
|
|
3
|
-
import { Box, Text } from
|
|
4
|
-
import { getClient } from
|
|
5
|
-
import { Banner } from
|
|
6
|
-
import { SpinnerComponent } from
|
|
7
|
-
import { SuccessMessage } from
|
|
8
|
-
import { ErrorMessage } from
|
|
9
|
-
import { createExecutor } from
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
import { getClient } from "../../utils/client.js";
|
|
5
|
+
import { Banner } from "../../components/Banner.js";
|
|
6
|
+
import { SpinnerComponent } from "../../components/Spinner.js";
|
|
7
|
+
import { SuccessMessage } from "../../components/SuccessMessage.js";
|
|
8
|
+
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
|
9
|
+
import { createExecutor } from "../../utils/CommandExecutor.js";
|
|
10
|
+
import { colors } from "../../utils/theme.js";
|
|
10
11
|
const CreateDevboxUI = ({ name, template }) => {
|
|
11
12
|
const [loading, setLoading] = React.useState(true);
|
|
12
13
|
const [result, setResult] = React.useState(null);
|
|
@@ -30,7 +31,7 @@ const CreateDevboxUI = ({ name, template }) => {
|
|
|
30
31
|
};
|
|
31
32
|
create();
|
|
32
33
|
}, []);
|
|
33
|
-
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Creating..." }), result && (_jsxs(_Fragment, { children: [_jsx(SuccessMessage, { message: "Devbox created!", details: `ID: ${result.id}\nStatus: ${result.status}` }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color:
|
|
34
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Creating..." }), result && (_jsxs(_Fragment, { children: [_jsx(SuccessMessage, { message: "Devbox created!", details: `ID: ${result.id}\nStatus: ${result.status}` }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: colors.textDim, children: "Try: " }), _jsxs(Text, { color: colors.primary, children: ["rli devbox exec ", result.id, " ls"] })] })] })), error && (_jsx(ErrorMessage, { message: "Failed to create devbox", error: error }))] }));
|
|
34
35
|
};
|
|
35
36
|
export async function createDevbox(options) {
|
|
36
37
|
const executor = createExecutor(options);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from
|
|
3
|
-
import { getClient } from
|
|
4
|
-
import { Header } from
|
|
5
|
-
import { SpinnerComponent } from
|
|
6
|
-
import { SuccessMessage } from
|
|
7
|
-
import { ErrorMessage } from
|
|
8
|
-
import { createExecutor } from
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { getClient } from "../../utils/client.js";
|
|
4
|
+
import { Header } from "../../components/Header.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
9
|
const DeleteDevboxUI = ({ id }) => {
|
|
10
10
|
const [loading, setLoading] = React.useState(true);
|
|
11
11
|
const [success, setSuccess] = React.useState(false);
|
|
@@ -26,7 +26,7 @@ const DeleteDevboxUI = ({ id }) => {
|
|
|
26
26
|
};
|
|
27
27
|
deleteDevbox();
|
|
28
28
|
}, []);
|
|
29
|
-
return (_jsxs(_Fragment, { children: [_jsx(Header, { title: "Shutdown Devbox", subtitle: `Shutting down devbox: ${id}` }), loading && _jsx(SpinnerComponent, { message: "Shutting down devbox..." }), success && (_jsx(SuccessMessage, { message: "Devbox shut down successfully!", details: `ID: ${id}` })), error && _jsx(ErrorMessage, { message: "Failed to shutdown devbox", error: error })] }));
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx(Header, { title: "Shutdown Devbox", subtitle: `Shutting down devbox: ${id}` }), loading && _jsx(SpinnerComponent, { message: "Shutting down devbox..." }), success && (_jsx(SuccessMessage, { message: "Devbox shut down successfully!", details: `ID: ${id}` })), error && (_jsx(ErrorMessage, { message: "Failed to shutdown devbox", error: error }))] }));
|
|
30
30
|
};
|
|
31
31
|
export async function deleteDevbox(id, options = {}) {
|
|
32
32
|
const executor = createExecutor(options);
|
|
@@ -0,0 +1,49 @@
|
|
|
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 { writeFileSync } from "fs";
|
|
10
|
+
const DownloadFileUI = ({ devboxId, filePath, outputPath }) => {
|
|
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 downloadFile = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const client = getClient();
|
|
18
|
+
const result = await client.devboxes.downloadFile(devboxId, {
|
|
19
|
+
path: filePath,
|
|
20
|
+
});
|
|
21
|
+
// The result should contain the file contents, write them to the output path
|
|
22
|
+
writeFileSync(outputPath, result);
|
|
23
|
+
setResult({ filePath, outputPath });
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
setError(err);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
downloadFile();
|
|
33
|
+
}, [devboxId, filePath, outputPath]);
|
|
34
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && (_jsx(SpinnerComponent, { message: "Downloading file from devbox..." })), result && (_jsx(SuccessMessage, { message: "File downloaded successfully", details: `Remote: ${result.filePath}\nLocal: ${result.outputPath}` })), error && (_jsx(ErrorMessage, { message: "Failed to download file", error: error }))] }));
|
|
35
|
+
};
|
|
36
|
+
export async function downloadFile(devboxId, options) {
|
|
37
|
+
const executor = createExecutor({ output: options.outputFormat });
|
|
38
|
+
await executor.executeAction(async () => {
|
|
39
|
+
const client = executor.getClient();
|
|
40
|
+
const result = await client.devboxes.downloadFile(devboxId, {
|
|
41
|
+
path: options.filePath,
|
|
42
|
+
});
|
|
43
|
+
writeFileSync(options.outputPath, result);
|
|
44
|
+
return {
|
|
45
|
+
filePath: options.filePath,
|
|
46
|
+
outputPath: options.outputPath,
|
|
47
|
+
};
|
|
48
|
+
}, () => (_jsx(DownloadFileUI, { devboxId: devboxId, filePath: options.filePath, outputPath: options.outputPath })));
|
|
49
|
+
}
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from
|
|
3
|
-
import {
|
|
4
|
-
import { getClient } from
|
|
5
|
-
import { Header } from
|
|
6
|
-
import { SpinnerComponent } from
|
|
7
|
-
import { ErrorMessage } from
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
import { getClient } from "../../utils/client.js";
|
|
5
|
+
import { Header } from "../../components/Header.js";
|
|
6
|
+
import { SpinnerComponent } from "../../components/Spinner.js";
|
|
7
|
+
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
|
8
|
+
import { colors } from "../../utils/theme.js";
|
|
9
|
+
import { createExecutor } from "../../utils/CommandExecutor.js";
|
|
8
10
|
const ExecCommandUI = ({ id, command, }) => {
|
|
9
11
|
const [loading, setLoading] = React.useState(true);
|
|
10
|
-
const [output, setOutput] = React.useState(
|
|
12
|
+
const [output, setOutput] = React.useState("");
|
|
11
13
|
const [error, setError] = React.useState(null);
|
|
12
14
|
React.useEffect(() => {
|
|
13
15
|
const exec = async () => {
|
|
14
16
|
try {
|
|
15
17
|
const client = getClient();
|
|
16
18
|
const result = await client.devboxes.executeSync(id, {
|
|
17
|
-
command: command.join(
|
|
19
|
+
command: command.join(" "),
|
|
18
20
|
});
|
|
19
|
-
setOutput(result.stdout || result.stderr ||
|
|
21
|
+
setOutput(result.stdout || result.stderr || "Command executed successfully");
|
|
20
22
|
}
|
|
21
23
|
catch (err) {
|
|
22
24
|
setError(err);
|
|
@@ -27,9 +29,17 @@ const ExecCommandUI = ({ id, command, }) => {
|
|
|
27
29
|
};
|
|
28
30
|
exec();
|
|
29
31
|
}, []);
|
|
30
|
-
return (_jsxs(_Fragment, { children: [_jsx(Header, { title: "Execute Command", subtitle: `Running in devbox: ${id}` }), loading && _jsx(SpinnerComponent, { message: "Executing command..." }), !loading && !error && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Box, { borderStyle: "round", borderColor:
|
|
32
|
+
return (_jsxs(_Fragment, { children: [_jsx(Header, { title: "Execute Command", subtitle: `Running in devbox: ${id}` }), loading && _jsx(SpinnerComponent, { message: "Executing command..." }), !loading && !error && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Box, { borderStyle: "round", borderColor: colors.success, padding: 1, children: _jsx(Text, { children: output }) }) })), error && (_jsx(ErrorMessage, { message: "Failed to execute command", error: error }))] }));
|
|
31
33
|
};
|
|
32
|
-
export async function execCommand(id, command) {
|
|
33
|
-
const
|
|
34
|
-
await
|
|
34
|
+
export async function execCommand(id, command, options = {}) {
|
|
35
|
+
const executor = createExecutor({ output: options.output });
|
|
36
|
+
await executor.executeAction(async () => {
|
|
37
|
+
const client = executor.getClient();
|
|
38
|
+
const result = await client.devboxes.executeSync(id, {
|
|
39
|
+
command: command.join(" "),
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
result: result.stdout || result.stderr || "Command executed successfully",
|
|
43
|
+
};
|
|
44
|
+
}, () => _jsx(ExecCommandUI, { id: id, command: command }));
|
|
35
45
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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 ExecAsyncUI = ({ devboxId, command, shellName }) => {
|
|
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 execAsync = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getClient();
|
|
17
|
+
const execution = await client.devboxes.executeAsync(devboxId, {
|
|
18
|
+
command,
|
|
19
|
+
shell_name: shellName || undefined,
|
|
20
|
+
});
|
|
21
|
+
setResult(execution);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
setError(err);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
execAsync();
|
|
31
|
+
}, [devboxId, command, shellName]);
|
|
32
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Starting async execution..." }), result && (_jsx(SuccessMessage, { message: "Async execution started", details: `Execution ID: ${result.id}\nCommand: ${command}\nStatus: ${result.status}` })), error && (_jsx(ErrorMessage, { message: "Failed to start async execution", error: error }))] }));
|
|
33
|
+
};
|
|
34
|
+
export async function execAsync(devboxId, options) {
|
|
35
|
+
const executor = createExecutor({ output: options.output });
|
|
36
|
+
await executor.executeAction(async () => {
|
|
37
|
+
const client = executor.getClient();
|
|
38
|
+
return client.devboxes.executeAsync(devboxId, {
|
|
39
|
+
command: options.command,
|
|
40
|
+
shell_name: options.shellName || undefined,
|
|
41
|
+
});
|
|
42
|
+
}, () => (_jsx(ExecAsyncUI, { devboxId: devboxId, command: options.command, shellName: options.shellName })));
|
|
43
|
+
}
|
|
@@ -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 GetDevboxUI = ({ devboxId }) => {
|
|
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 getDevbox = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getClient();
|
|
17
|
+
const devbox = await client.devboxes.retrieve(devboxId);
|
|
18
|
+
setResult(devbox);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
setError(err);
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
getDevbox();
|
|
28
|
+
}, [devboxId]);
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && _jsx(SpinnerComponent, { message: "Fetching devbox details..." }), result && (_jsx(SuccessMessage, { message: "Devbox details retrieved", details: `ID: ${result.id}\nStatus: ${result.status}\nCreated: ${new Date(result.createdAt).toLocaleString()}` })), error && _jsx(ErrorMessage, { message: "Failed to get devbox", error: error })] }));
|
|
30
|
+
};
|
|
31
|
+
export async function getDevbox(devboxId, options) {
|
|
32
|
+
const executor = createExecutor(options);
|
|
33
|
+
await executor.executeAction(async () => {
|
|
34
|
+
const client = executor.getClient();
|
|
35
|
+
return client.devboxes.retrieve(devboxId);
|
|
36
|
+
}, () => _jsx(GetDevboxUI, { devboxId: devboxId }));
|
|
37
|
+
}
|
|
@@ -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 GetAsyncUI = ({ devboxId, executionId }) => {
|
|
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 getAsync = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getClient();
|
|
17
|
+
const execution = await client.devboxes.executions.retrieve(executionId, devboxId);
|
|
18
|
+
setResult(execution);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
setError(err);
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
getAsync();
|
|
28
|
+
}, [devboxId, executionId]);
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx(Banner, {}), loading && (_jsx(SpinnerComponent, { message: "Getting async execution status..." })), result && (_jsx(SuccessMessage, { message: "Async execution status retrieved", details: `Execution ID: ${result.id}\nStatus: ${result.status}\nCommand: ${result.command}` })), error && (_jsx(ErrorMessage, { message: "Failed to get async execution status", error: error }))] }));
|
|
30
|
+
};
|
|
31
|
+
export async function getAsync(devboxId, options) {
|
|
32
|
+
const executor = createExecutor({ output: options.output });
|
|
33
|
+
await executor.executeAction(async () => {
|
|
34
|
+
const client = executor.getClient();
|
|
35
|
+
return client.devboxes.executions.retrieve(devboxId, options.executionId);
|
|
36
|
+
}, () => _jsx(GetAsyncUI, { devboxId: devboxId, executionId: options.executionId }));
|
|
37
|
+
}
|