@freestyle-sh/with-uv 0.1.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.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @freestyle-sh/with-uv
2
+
3
+ Python runtime via [uv](https://github.com/astral-sh/uv) for [Freestyle](https://freestyle.sh) VMs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @freestyle-sh/with-uv freestyle-sandboxes
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { freestyle } from "freestyle-sandboxes";
15
+ import { VmUv } from "@freestyle-sh/with-uv";
16
+
17
+ const { vm } = await freestyle.vms.create({
18
+ with: {
19
+ uv: new VmUv(),
20
+ },
21
+ });
22
+
23
+ const res = await vm.uv.runCode(
24
+ "import json; print(json.dumps({ 'hello': 'world' }))"
25
+ );
26
+
27
+ console.log(res);
28
+ // { result: { hello: 'world' }, stdout: '{"hello": "world"}\n', statusCode: 0 }
29
+ ```
30
+
31
+ ## Options
32
+
33
+ ```typescript
34
+ new VmUv({
35
+ version: "0.5.0", // Optional: specific uv version
36
+ pythonVersion: "3.13", // Optional: Python version (default: "3.14")
37
+ })
38
+ ```
39
+
40
+ | Option | Type | Default | Description |
41
+ |--------|------|---------|-------------|
42
+ | `version` | `string` | `undefined` | uv version to install. If not specified, installs the latest version. |
43
+ | `pythonVersion` | `string` | `"3.14"` | Python version to install via uv. |
44
+
45
+ ## API
46
+
47
+ ### `vm.uv.runCode(code: string)`
48
+
49
+ Executes Python code using uv's managed Python runtime.
50
+
51
+ **Returns:** `Promise<RunCodeResponse>`
52
+
53
+ ```typescript
54
+ type RunCodeResponse<Result> = {
55
+ result: Result; // Parsed JSON from stdout (if valid JSON)
56
+ stdout?: string; // Raw stdout output
57
+ stderr?: string; // Raw stderr output
58
+ statusCode?: number; // Exit code
59
+ };
60
+ ```
61
+
62
+ ## Documentation
63
+
64
+ - [Freestyle Documentation](https://docs.freestyle.sh)
65
+ - [uv Documentation](https://docs.astral.sh/uv/)
@@ -0,0 +1,25 @@
1
+ import { VmWith, VmWithInstance, CreateVmOptions } from 'freestyle-sandboxes';
2
+ import { VmRunCodeInstance, JSONValue, RunCodeResponse, VmRunCode } from '@freestyle-sh/with-type-run-code';
3
+
4
+ type UvOptions = {
5
+ version?: string;
6
+ pythonVersion?: string;
7
+ };
8
+ type UvResolvedOptions = {
9
+ version?: string;
10
+ pythonVersion: string;
11
+ };
12
+ declare class VmUv extends VmWith<VmUvInstance> implements VmRunCode<VmRunCodeInstance> {
13
+ options: UvResolvedOptions;
14
+ constructor(options?: UvOptions);
15
+ configure(existingConfig: CreateVmOptions): CreateVmOptions | Promise<CreateVmOptions>;
16
+ createInstance(): VmUvInstance;
17
+ installServiceName(): string;
18
+ }
19
+ declare class VmUvInstance extends VmWithInstance implements VmRunCodeInstance {
20
+ builder: VmUv;
21
+ constructor(builder: VmUv);
22
+ runCode<Result extends JSONValue = any>(code: string): Promise<RunCodeResponse<Result>>;
23
+ }
24
+
25
+ export { VmUv };
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ import { VmWith, VmTemplate, VmWithInstance } from 'freestyle-sandboxes';
2
+
3
+ class VmUv extends VmWith {
4
+ options;
5
+ constructor(options) {
6
+ super();
7
+ this.options = {
8
+ version: options?.version,
9
+ pythonVersion: options?.pythonVersion ?? "3.14"
10
+ };
11
+ }
12
+ configure(existingConfig) {
13
+ const versionArg = this.options.version ? `UV_VERSION="${this.options.version}" ` : "";
14
+ const installScript = `#!/bin/bash
15
+ set -e
16
+ export UV_INSTALL_DIR="/opt/uv/bin"
17
+ ${versionArg}curl -LsSf https://astral.sh/uv/install.sh | sh
18
+ /opt/uv/bin/uv python install ${this.options.pythonVersion}
19
+ /opt/uv/bin/uv --version
20
+ `;
21
+ const uvInit = `export PATH="/opt/uv/bin:$PATH"
22
+ `;
23
+ const uvConfig = {
24
+ template: new VmTemplate({
25
+ additionalFiles: {
26
+ "/opt/install-uv.sh": {
27
+ content: installScript
28
+ },
29
+ "/etc/profile.d/uv.sh": {
30
+ content: uvInit
31
+ }
32
+ },
33
+ systemd: {
34
+ services: [
35
+ {
36
+ name: "install-uv",
37
+ mode: "oneshot",
38
+ deleteAfterSuccess: true,
39
+ exec: ["bash /opt/install-uv.sh"],
40
+ timeoutSec: 300
41
+ }
42
+ ]
43
+ }
44
+ })
45
+ };
46
+ return this.compose(existingConfig, uvConfig);
47
+ }
48
+ createInstance() {
49
+ return new VmUvInstance(this);
50
+ }
51
+ installServiceName() {
52
+ return "install-uv.service";
53
+ }
54
+ }
55
+ class VmUvInstance extends VmWithInstance {
56
+ builder;
57
+ constructor(builder) {
58
+ super();
59
+ this.builder = builder;
60
+ }
61
+ async runCode(code) {
62
+ const result = await this.vm.exec({
63
+ command: `/opt/uv/bin/uv run python -c "${code.replace(/"/g, '\\"')}"`
64
+ });
65
+ let parsedResult = void 0;
66
+ if (result.stdout) {
67
+ try {
68
+ parsedResult = JSON.parse(result.stdout);
69
+ } catch (e) {
70
+ }
71
+ }
72
+ return {
73
+ result: parsedResult,
74
+ stdout: result.stdout ?? void 0,
75
+ stderr: result.stderr ?? void 0,
76
+ statusCode: result.statusCode ?? -1
77
+ };
78
+ }
79
+ }
80
+
81
+ export { VmUv };
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@freestyle-sh/with-uv",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "dependencies": {
6
+ "freestyle-sandboxes": "^0.1.2",
7
+ "@freestyle-sh/with-type-run-code": "^0.1.0"
8
+ },
9
+ "type": "module",
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "source": "./src/index.ts",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "pkgroll"
24
+ }
25
+ }