@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 +65 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +81 -0
- package/package.json +25 -0
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/)
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|