@computesdk/tensorlake 0.0.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/LICENSE +21 -0
- package/README.md +270 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +292 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +267 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 computesdk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @computesdk/tensorlake
|
|
2
|
+
|
|
3
|
+
Tensorlake provider for ComputeSDK - stateful MicroVM sandboxes for agentic applications and LLM-generated code execution.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @computesdk/tensorlake
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
1. Get your API key from [cloud.tensorlake.ai](https://cloud.tensorlake.ai)
|
|
14
|
+
2. Set the environment variable:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
export TENSORLAKE_API_KEY=your_api_key_here
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Gateway Mode (Recommended)
|
|
23
|
+
|
|
24
|
+
Use the gateway for zero-config auto-detection:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { compute } from 'computesdk';
|
|
28
|
+
|
|
29
|
+
// Auto-detects Tensorlake from TENSORLAKE_API_KEY environment variable
|
|
30
|
+
const sandbox = await compute.sandbox.create();
|
|
31
|
+
|
|
32
|
+
const result = await sandbox.runCommand('uname -a');
|
|
33
|
+
console.log(result.stdout);
|
|
34
|
+
|
|
35
|
+
await sandbox.destroy();
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Direct Mode
|
|
39
|
+
|
|
40
|
+
For direct SDK usage without the gateway:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { tensorlake } from '@computesdk/tensorlake';
|
|
44
|
+
|
|
45
|
+
const compute = tensorlake({ apiKey: process.env.TENSORLAKE_API_KEY });
|
|
46
|
+
|
|
47
|
+
const sandbox = await compute.sandbox.create();
|
|
48
|
+
|
|
49
|
+
const result = await sandbox.runCommand(`uname -a`);
|
|
50
|
+
|
|
51
|
+
console.log(result.stdout);
|
|
52
|
+
await sandbox.destroy();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
### Environment Variables
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export TENSORLAKE_API_KEY=your_api_key_here
|
|
61
|
+
export TENSORLAKE_API_URL=https://api.tensorlake.ai # optional override
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Configuration Options
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface TensorlakeConfig {
|
|
68
|
+
/** Tensorlake API key — falls back to TENSORLAKE_API_KEY environment variable */
|
|
69
|
+
apiKey?: string;
|
|
70
|
+
/** Override for the management API base URL */
|
|
71
|
+
apiUrl?: string;
|
|
72
|
+
/** Override for the sandbox proxy URL */
|
|
73
|
+
proxyUrl?: string;
|
|
74
|
+
/** Default container image for new sandboxes (default: ubuntu-minimal) */
|
|
75
|
+
image?: string;
|
|
76
|
+
/** Default timeout in seconds for sandboxes */
|
|
77
|
+
timeout?: number;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
- **Stateful MicroVMs** - Full VM isolation with persistent state within a session
|
|
84
|
+
- **Snapshot & restore** - Snapshot a running sandbox and resume from it later
|
|
85
|
+
- **Code execution** - Python and Node.js with auto-detection
|
|
86
|
+
- **Command execution** - Run shell commands, including background processes
|
|
87
|
+
- **Filesystem operations** - Read, write, list, and remove files and directories
|
|
88
|
+
- **URL access** - Expose sandbox ports via proxy URLs
|
|
89
|
+
- **Auto runtime detection** - Automatically detects Python vs Node.js from code patterns
|
|
90
|
+
|
|
91
|
+
## API Reference
|
|
92
|
+
|
|
93
|
+
### Sandbox Management
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// Create a sandbox (default image: ubuntu-minimal)
|
|
97
|
+
const sandbox = await compute.sandbox.create();
|
|
98
|
+
|
|
99
|
+
// Create with options
|
|
100
|
+
const sandbox = await compute.sandbox.create({
|
|
101
|
+
image: 'ubuntu-minimal',
|
|
102
|
+
timeout: 300000, // ms → converted to seconds internally
|
|
103
|
+
name: 'my-sandbox',
|
|
104
|
+
snapshotId: 'snap-abc123', // resume from a snapshot
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Get an existing sandbox by ID
|
|
108
|
+
const sandbox = await compute.sandbox.getById('sandbox-id');
|
|
109
|
+
|
|
110
|
+
// List all running sandboxes
|
|
111
|
+
const sandboxes = await compute.sandbox.list();
|
|
112
|
+
|
|
113
|
+
// Destroy a sandbox
|
|
114
|
+
await sandbox.destroy();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Command Execution
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Run a command and wait for output
|
|
121
|
+
const result = await sandbox.runCommand('ls -la /tmp');
|
|
122
|
+
console.log(result.stdout);
|
|
123
|
+
console.log(result.exitCode);
|
|
124
|
+
|
|
125
|
+
// Run with environment variables and working directory
|
|
126
|
+
const result = await sandbox.runCommand('npm install', {
|
|
127
|
+
env: { NODE_ENV: 'production' },
|
|
128
|
+
cwd: '/app',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Fire-and-forget background process
|
|
132
|
+
await sandbox.runCommand('python server.py', { background: true });
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Filesystem Operations
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Write a file
|
|
139
|
+
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello")');
|
|
140
|
+
|
|
141
|
+
// Read a file
|
|
142
|
+
const content = await sandbox.filesystem.readFile('/tmp/hello.py');
|
|
143
|
+
|
|
144
|
+
// Create a directory (creates parents as needed)
|
|
145
|
+
await sandbox.filesystem.mkdir('/tmp/data/nested');
|
|
146
|
+
|
|
147
|
+
// List directory contents
|
|
148
|
+
const entries = await sandbox.filesystem.readdir('/tmp');
|
|
149
|
+
// entries: [{ name, type: 'file'|'directory', size, modified }]
|
|
150
|
+
|
|
151
|
+
// Check existence
|
|
152
|
+
const exists = await sandbox.filesystem.exists('/tmp/hello.py');
|
|
153
|
+
|
|
154
|
+
// Remove a file or directory
|
|
155
|
+
await sandbox.filesystem.remove('/tmp/hello.py');
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Snapshots
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// Snapshot the current state of a running sandbox
|
|
162
|
+
const snapshot = await compute.snapshot.create(sandboxId, { name: 'after-setup' });
|
|
163
|
+
console.log(snapshot.id); // 'snap-abc123'
|
|
164
|
+
|
|
165
|
+
// List all snapshots
|
|
166
|
+
const snapshots = await compute.snapshot.list();
|
|
167
|
+
|
|
168
|
+
// Delete a snapshot
|
|
169
|
+
await compute.snapshot.delete('snap-abc123');
|
|
170
|
+
|
|
171
|
+
// Resume from a snapshot
|
|
172
|
+
const sandbox = await compute.sandbox.create({ snapshotId: 'snap-abc123' });
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### URL Access
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Get a proxy URL for a port exposed inside the sandbox
|
|
179
|
+
const url = await sandbox.getUrl({ port: 443 });
|
|
180
|
+
// → "https://<sandbox-id>.sandbox.tensorlake.ai"
|
|
181
|
+
|
|
182
|
+
const customPortUrl = await sandbox.getUrl({ port: 8080 });
|
|
183
|
+
// → "https://8080-<sandbox-id>.sandbox.tensorlake.ai"
|
|
184
|
+
|
|
185
|
+
const wsUrl = await sandbox.getUrl({ port: 443, protocol: 'wss' });
|
|
186
|
+
// → "wss://<sandbox-id>.sandbox.tensorlake.ai"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Examples
|
|
190
|
+
|
|
191
|
+
### Agentic Code Execution
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { tensorlake } from '@computesdk/tensorlake';
|
|
195
|
+
|
|
196
|
+
const compute = tensorlake({ apiKey: process.env.TENSORLAKE_API_KEY });
|
|
197
|
+
const sandbox = await compute.sandbox.create({ timeout: 600000 });
|
|
198
|
+
|
|
199
|
+
// Install dependencies once
|
|
200
|
+
await sandbox.runCommand('pip install requests pandas');
|
|
201
|
+
|
|
202
|
+
const result = await sandbox.runCommand('python --version');
|
|
203
|
+
console.log(result.stdout);
|
|
204
|
+
|
|
205
|
+
await sandbox.destroy();
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Snapshot-Backed Warm Starts
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { tensorlake } from '@computesdk/tensorlake';
|
|
212
|
+
|
|
213
|
+
const compute = tensorlake({ apiKey: process.env.TENSORLAKE_API_KEY });
|
|
214
|
+
|
|
215
|
+
// One-time setup: create a pre-warmed snapshot
|
|
216
|
+
async function createBaseSnapshot(): Promise<string> {
|
|
217
|
+
const sandbox = await compute.sandbox.create();
|
|
218
|
+
await sandbox.runCommand('pip install pandas numpy scikit-learn');
|
|
219
|
+
const snapshot = await compute.snapshot.create(sandbox.sandboxId);
|
|
220
|
+
await sandbox.destroy();
|
|
221
|
+
return snapshot.id;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Fast boot from snapshot — skips install step
|
|
225
|
+
const snapshotId = await createBaseSnapshot();
|
|
226
|
+
const sandbox = await compute.sandbox.create({ snapshotId });
|
|
227
|
+
|
|
228
|
+
const result = await sandbox.runCommand(`uname -a`);
|
|
229
|
+
|
|
230
|
+
console.log(result.stdout);
|
|
231
|
+
await sandbox.destroy();
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Error Handling
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { tensorlake } from '@computesdk/tensorlake';
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const compute = tensorlake({ apiKey: process.env.TENSORLAKE_API_KEY });
|
|
241
|
+
const sandbox = await compute.sandbox.create();
|
|
242
|
+
const result = await sandbox.runCommand('umane -a');
|
|
243
|
+
console.log(result.stdout);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (error.message.includes('Missing Tensorlake API key')) {
|
|
246
|
+
console.error('Set TENSORLAKE_API_KEY environment variable');
|
|
247
|
+
} else if (error.message.includes('authentication failed')) {
|
|
248
|
+
console.error('Check your API key at https://cloud.tensorlake.ai');
|
|
249
|
+
} else {
|
|
250
|
+
console.error(error);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Best Practices
|
|
256
|
+
|
|
257
|
+
1. **Snapshots for warm starts** - Snapshot after installing dependencies to avoid repeating setup
|
|
258
|
+
2. **Destroy sandboxes** - Always call `sandbox.destroy()` to release resources
|
|
259
|
+
3. **Set timeouts** - Use `timeout` on long-running workloads to avoid runaway VMs
|
|
260
|
+
4. **Background processes** - Use `{ background: true }` for servers or daemons; they survive after the initiating command returns
|
|
261
|
+
5. **API key security** - Never commit API keys; use environment variables or a secrets manager
|
|
262
|
+
|
|
263
|
+
## Support
|
|
264
|
+
|
|
265
|
+
- [Tensorlake Documentation](https://docs.tensorlake.ai)
|
|
266
|
+
- [ComputeSDK Issues](https://github.com/computesdk/computesdk/issues)
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as _computesdk_provider from '@computesdk/provider';
|
|
2
|
+
import { Sandbox } from 'tensorlake';
|
|
3
|
+
|
|
4
|
+
interface TensorlakeConfig {
|
|
5
|
+
/** Tensorlake API key — falls back to TENSORLAKE_API_KEY environment variable */
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
/** Override for the management API base URL */
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
/** Override for the sandbox proxy URL */
|
|
10
|
+
proxyUrl?: string;
|
|
11
|
+
/** Default container image for new sandboxes (default: ubuntu-minimal) */
|
|
12
|
+
image?: string;
|
|
13
|
+
/** Default timeout in milliseconds for sandboxes */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
}
|
|
16
|
+
interface TensorlakeSandboxContext {
|
|
17
|
+
config: TensorlakeConfig;
|
|
18
|
+
/** Connected SDK Sandbox instance — used for all proxy operations */
|
|
19
|
+
sandbox: InstanceType<typeof Sandbox>;
|
|
20
|
+
}
|
|
21
|
+
declare const tensorlake: (config: TensorlakeConfig) => _computesdk_provider.Provider<TensorlakeSandboxContext, any, any>;
|
|
22
|
+
|
|
23
|
+
export { type TensorlakeConfig, type TensorlakeSandboxContext as TensorlakeSandbox, type TensorlakeSandboxContext, tensorlake };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as _computesdk_provider from '@computesdk/provider';
|
|
2
|
+
import { Sandbox } from 'tensorlake';
|
|
3
|
+
|
|
4
|
+
interface TensorlakeConfig {
|
|
5
|
+
/** Tensorlake API key — falls back to TENSORLAKE_API_KEY environment variable */
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
/** Override for the management API base URL */
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
/** Override for the sandbox proxy URL */
|
|
10
|
+
proxyUrl?: string;
|
|
11
|
+
/** Default container image for new sandboxes (default: ubuntu-minimal) */
|
|
12
|
+
image?: string;
|
|
13
|
+
/** Default timeout in milliseconds for sandboxes */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
}
|
|
16
|
+
interface TensorlakeSandboxContext {
|
|
17
|
+
config: TensorlakeConfig;
|
|
18
|
+
/** Connected SDK Sandbox instance — used for all proxy operations */
|
|
19
|
+
sandbox: InstanceType<typeof Sandbox>;
|
|
20
|
+
}
|
|
21
|
+
declare const tensorlake: (config: TensorlakeConfig) => _computesdk_provider.Provider<TensorlakeSandboxContext, any, any>;
|
|
22
|
+
|
|
23
|
+
export { type TensorlakeConfig, type TensorlakeSandboxContext as TensorlakeSandbox, type TensorlakeSandboxContext, tensorlake };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
tensorlake: () => tensorlake
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
var import_tensorlake = require("tensorlake");
|
|
27
|
+
var import_provider = require("@computesdk/provider");
|
|
28
|
+
var DEFAULT_IMAGE = "ubuntu-minimal";
|
|
29
|
+
function resolveAuth(config) {
|
|
30
|
+
const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.TENSORLAKE_API_KEY || "";
|
|
31
|
+
if (!apiKey) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Missing Tensorlake API key. Provide 'apiKey' in config or set TENSORLAKE_API_KEY environment variable. Get your API key from https://app.tensorlake.ai`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const apiUrl = config.apiUrl || typeof process !== "undefined" && process.env?.TENSORLAKE_API_URL || void 0;
|
|
37
|
+
return { apiKey, apiUrl };
|
|
38
|
+
}
|
|
39
|
+
var tensorlake = (0, import_provider.defineProvider)({
|
|
40
|
+
name: "tensorlake",
|
|
41
|
+
methods: {
|
|
42
|
+
sandbox: {
|
|
43
|
+
create: async (config, options) => {
|
|
44
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
45
|
+
const image = options?.image || config.image || DEFAULT_IMAGE;
|
|
46
|
+
const timeoutSecs = options?.timeout ? Math.ceil(options.timeout / 1e3) : config.timeout;
|
|
47
|
+
try {
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
const instance = await import_tensorlake.Sandbox.create({
|
|
50
|
+
image,
|
|
51
|
+
cpus: 1,
|
|
52
|
+
memoryMb: 1024,
|
|
53
|
+
ephemeralDiskMb: 2048,
|
|
54
|
+
...timeoutSecs && { timeoutSecs },
|
|
55
|
+
...options?.name && { name: options.name },
|
|
56
|
+
...options?.snapshotId && { snapshotId: options.snapshotId },
|
|
57
|
+
proxyUrl: config.proxyUrl,
|
|
58
|
+
apiKey,
|
|
59
|
+
apiUrl
|
|
60
|
+
});
|
|
61
|
+
const sandbox = {
|
|
62
|
+
config,
|
|
63
|
+
sandbox: instance
|
|
64
|
+
};
|
|
65
|
+
const durationMs = Date.now() - startTime;
|
|
66
|
+
return {
|
|
67
|
+
sandbox,
|
|
68
|
+
sandboxId: instance.sandboxId,
|
|
69
|
+
durationMs
|
|
70
|
+
};
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error instanceof Error && error.message.includes("401")) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Tensorlake authentication failed. Please check your TENSORLAKE_API_KEY. Get your API key from https://app.tensorlake.ai`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Failed to create Tensorlake sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
getById: async (config, sandboxId) => {
|
|
83
|
+
try {
|
|
84
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
85
|
+
const sandbox = await import_tensorlake.Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
86
|
+
const ctx = {
|
|
87
|
+
config,
|
|
88
|
+
sandbox
|
|
89
|
+
};
|
|
90
|
+
return { sandbox: ctx, sandboxId: sandbox.sandboxId };
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
list: async (config) => {
|
|
96
|
+
try {
|
|
97
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
98
|
+
const sandboxes = await import_tensorlake.Sandbox.list({ apiKey, apiUrl });
|
|
99
|
+
return Promise.all(
|
|
100
|
+
sandboxes.map(async (s) => {
|
|
101
|
+
const sandbox = await import_tensorlake.Sandbox.connect({
|
|
102
|
+
sandboxId: s.sandboxId,
|
|
103
|
+
proxyUrl: config.proxyUrl,
|
|
104
|
+
routingHint: s.routingHint,
|
|
105
|
+
apiKey,
|
|
106
|
+
apiUrl
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
sandbox: {
|
|
110
|
+
sandboxId: s.sandboxId,
|
|
111
|
+
config,
|
|
112
|
+
sandbox
|
|
113
|
+
},
|
|
114
|
+
sandboxId: s.sandboxId
|
|
115
|
+
};
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
} catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
destroy: async (config, sandboxId) => {
|
|
123
|
+
try {
|
|
124
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
125
|
+
const sandbox = await import_tensorlake.Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
126
|
+
await sandbox.terminate();
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
runCommand: async (ctx, command, options) => {
|
|
131
|
+
const startTime = Date.now();
|
|
132
|
+
if (options?.background) {
|
|
133
|
+
try {
|
|
134
|
+
await ctx.sandbox.startProcess("sh", {
|
|
135
|
+
args: ["-c", command],
|
|
136
|
+
stdoutMode: import_tensorlake.OutputMode.DISCARD,
|
|
137
|
+
stderrMode: import_tensorlake.OutputMode.DISCARD,
|
|
138
|
+
...options.env && Object.keys(options.env).length > 0 && { env: options.env },
|
|
139
|
+
...options.cwd && { workingDir: options.cwd }
|
|
140
|
+
});
|
|
141
|
+
} catch (error) {
|
|
142
|
+
return {
|
|
143
|
+
stdout: "",
|
|
144
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
145
|
+
exitCode: 127,
|
|
146
|
+
durationMs: Date.now() - startTime
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const result = await ctx.sandbox.run("sh", {
|
|
152
|
+
args: ["-c", command],
|
|
153
|
+
...options?.env && Object.keys(options.env).length > 0 && { env: options.env },
|
|
154
|
+
...options?.cwd && { workingDir: options.cwd }
|
|
155
|
+
});
|
|
156
|
+
const durationMs = Date.now() - startTime;
|
|
157
|
+
return {
|
|
158
|
+
stdout: result.stdout,
|
|
159
|
+
stderr: result.stderr,
|
|
160
|
+
exitCode: result.exitCode ?? 0,
|
|
161
|
+
durationMs
|
|
162
|
+
};
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
stdout: "",
|
|
166
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
167
|
+
exitCode: 127,
|
|
168
|
+
durationMs: Date.now() - startTime
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
getInfo: async (ctx) => {
|
|
173
|
+
try {
|
|
174
|
+
const info = await ctx.sandbox.info();
|
|
175
|
+
return {
|
|
176
|
+
id: ctx.sandbox.sandboxId,
|
|
177
|
+
provider: "tensorlake",
|
|
178
|
+
status: info.status === import_tensorlake.SandboxStatus.RUNNING ? "running" : "stopped",
|
|
179
|
+
createdAt: info.createdAt || /* @__PURE__ */ new Date(),
|
|
180
|
+
timeout: info.timeoutSecs != null ? info.timeoutSecs * 1e3 : 3e5,
|
|
181
|
+
metadata: {}
|
|
182
|
+
};
|
|
183
|
+
} catch {
|
|
184
|
+
return {
|
|
185
|
+
id: ctx.sandbox.sandboxId,
|
|
186
|
+
provider: "tensorlake",
|
|
187
|
+
status: "running",
|
|
188
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
189
|
+
timeout: 3e5,
|
|
190
|
+
metadata: {}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
getUrl: async (ctx, options) => {
|
|
195
|
+
const { port, protocol: optionsProtocol } = options;
|
|
196
|
+
const protocol = optionsProtocol || "https";
|
|
197
|
+
const apiUrl = ctx.config.apiUrl || typeof process !== "undefined" && process.env?.TENSORLAKE_API_URL || "https://api.tensorlake.ai";
|
|
198
|
+
const proxyDomain = new URL(apiUrl).hostname;
|
|
199
|
+
const subdomain = port === 443 || port === 80 ? ctx.sandbox.sandboxId : `${port}-${ctx.sandbox.sandboxId}`;
|
|
200
|
+
return `${protocol}://${subdomain}.${proxyDomain}`;
|
|
201
|
+
},
|
|
202
|
+
filesystem: {
|
|
203
|
+
readFile: async (ctx, path) => {
|
|
204
|
+
const bytes = await ctx.sandbox.readFile(path);
|
|
205
|
+
return Buffer.from(bytes).toString("utf-8");
|
|
206
|
+
},
|
|
207
|
+
writeFile: async (ctx, path, content) => {
|
|
208
|
+
await ctx.sandbox.writeFile(path, Buffer.from(content, "utf-8"));
|
|
209
|
+
},
|
|
210
|
+
mkdir: async (ctx, path) => {
|
|
211
|
+
const result = await ctx.sandbox.run("mkdir", { args: ["-p", path] });
|
|
212
|
+
if (result.exitCode !== 0) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`Failed to create directory ${path}: ${result.stderr}`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
readdir: async (ctx, path) => {
|
|
219
|
+
const response = await ctx.sandbox.listDirectory(path);
|
|
220
|
+
return response.entries.map((e) => ({
|
|
221
|
+
name: e.name,
|
|
222
|
+
type: e.isDir ? "directory" : "file",
|
|
223
|
+
size: e.size || 0,
|
|
224
|
+
modified: e.modifiedAt ?? /* @__PURE__ */ new Date()
|
|
225
|
+
}));
|
|
226
|
+
},
|
|
227
|
+
exists: async (ctx, path) => {
|
|
228
|
+
try {
|
|
229
|
+
await ctx.sandbox.readFile(path);
|
|
230
|
+
return true;
|
|
231
|
+
} catch {
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
await ctx.sandbox.listDirectory(path);
|
|
235
|
+
return true;
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
},
|
|
240
|
+
remove: async (ctx, path) => {
|
|
241
|
+
try {
|
|
242
|
+
await ctx.sandbox.deleteFile(path);
|
|
243
|
+
} catch {
|
|
244
|
+
const result = await ctx.sandbox.run("rm", { args: ["-rf", path] });
|
|
245
|
+
if (result.exitCode !== 0) {
|
|
246
|
+
throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
getInstance: (ctx) => ctx
|
|
252
|
+
},
|
|
253
|
+
snapshot: {
|
|
254
|
+
create: async (config, sandboxId, options) => {
|
|
255
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
256
|
+
const sandbox = await import_tensorlake.Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
257
|
+
const result = await sandbox.checkpoint();
|
|
258
|
+
if (!result) {
|
|
259
|
+
throw new Error(
|
|
260
|
+
`Failed to create snapshot for sandbox '${sandboxId}': checkpoint() did not return a snapshot result.`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
id: result.snapshotId,
|
|
265
|
+
provider: "tensorlake",
|
|
266
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
267
|
+
metadata: { name: options?.name }
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
list: async (config) => {
|
|
271
|
+
try {
|
|
272
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
273
|
+
return await import_tensorlake.Sandbox.listSnapshots({ apiKey, apiUrl });
|
|
274
|
+
} catch {
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
delete: async (config, snapshotId) => {
|
|
279
|
+
try {
|
|
280
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
281
|
+
await import_tensorlake.Sandbox.deleteSnapshot(snapshotId, { apiKey, apiUrl });
|
|
282
|
+
} catch {
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
289
|
+
0 && (module.exports = {
|
|
290
|
+
tensorlake
|
|
291
|
+
});
|
|
292
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/// <reference types=\"node\" />\n/**\n * Tensorlake Provider - SDK-based Implementation\n *\n * Stateful MicroVM sandboxes for agentic applications and LLM-generated code execution.\n * Uses the official tensorlake npm SDK (0.5.7).\n */\n\nimport { Sandbox, SandboxStatus, OutputMode } from \"tensorlake\";\nimport type { SandboxInfo } from \"tensorlake\";\nimport { defineProvider } from \"@computesdk/provider\";\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo as ComputeSandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from \"@computesdk/provider\";\n\nconst DEFAULT_IMAGE = \"ubuntu-minimal\";\n\nexport interface TensorlakeConfig {\n /** Tensorlake API key — falls back to TENSORLAKE_API_KEY environment variable */\n apiKey?: string;\n /** Override for the management API base URL */\n apiUrl?: string;\n /** Override for the sandbox proxy URL */\n proxyUrl?: string;\n /** Default container image for new sandboxes (default: ubuntu-minimal) */\n image?: string;\n /** Default timeout in milliseconds for sandboxes */\n timeout?: number;\n}\n\nexport interface TensorlakeSandboxContext {\n config: TensorlakeConfig;\n /** Connected SDK Sandbox instance — used for all proxy operations */\n sandbox: InstanceType<typeof Sandbox>;\n}\n\nfunction resolveAuth(config: TensorlakeConfig): {\n apiKey: string;\n apiUrl?: string;\n} {\n const apiKey =\n config.apiKey ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_KEY) ||\n \"\";\n if (!apiKey) {\n throw new Error(\n `Missing Tensorlake API key. Provide 'apiKey' in config or set TENSORLAKE_API_KEY environment variable. ` +\n `Get your API key from https://app.tensorlake.ai`\n );\n }\n const apiUrl =\n config.apiUrl ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_URL) ||\n undefined;\n return { apiKey, apiUrl };\n}\n\nexport const tensorlake = defineProvider<\n TensorlakeSandboxContext,\n TensorlakeConfig\n>({\n name: \"tensorlake\",\n methods: {\n sandbox: {\n create: async (\n config: TensorlakeConfig,\n options?: CreateSandboxOptions\n ) => {\n const { apiKey, apiUrl } = resolveAuth(config);\n const image = options?.image || config.image || DEFAULT_IMAGE;\n const timeoutSecs = options?.timeout\n ? Math.ceil(options.timeout / 1000)\n : config.timeout;\n\n try {\n const startTime = Date.now();\n const instance = await Sandbox.create({\n image,\n cpus: 1,\n memoryMb: 1024,\n ephemeralDiskMb: 2048,\n ...(timeoutSecs && { timeoutSecs }),\n ...(options?.name && { name: options.name }),\n ...(options?.snapshotId && { snapshotId: options.snapshotId }),\n proxyUrl: config.proxyUrl,\n apiKey,\n apiUrl,\n });\n\n const sandbox: TensorlakeSandboxContext = {\n config,\n sandbox: instance,\n };\n const durationMs = Date.now() - startTime;\n return {\n sandbox,\n sandboxId: instance.sandboxId,\n durationMs,\n };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"401\")) {\n throw new Error(\n `Tensorlake authentication failed. Please check your TENSORLAKE_API_KEY. ` +\n `Get your API key from https://app.tensorlake.ai`\n );\n }\n throw new Error(\n `Failed to create Tensorlake sandbox: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n },\n\n getById: async (config: TensorlakeConfig, sandboxId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n const ctx: TensorlakeSandboxContext = {\n config,\n sandbox,\n };\n return { sandbox: ctx, sandboxId: sandbox.sandboxId };\n } catch {\n return null;\n }\n },\n\n list: async (config: TensorlakeConfig) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandboxes = await Sandbox.list({ apiKey, apiUrl });\n return Promise.all(\n sandboxes.map(async (s) => {\n const sandbox = await Sandbox.connect({\n sandboxId: s.sandboxId,\n proxyUrl: config.proxyUrl,\n routingHint: s.routingHint,\n apiKey,\n apiUrl,\n });\n return {\n sandbox: {\n sandboxId: s.sandboxId,\n config,\n sandbox,\n } as TensorlakeSandboxContext,\n sandboxId: s.sandboxId,\n };\n })\n );\n } catch {\n return [];\n }\n },\n\n destroy: async (config: TensorlakeConfig, sandboxId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n await sandbox.terminate();\n } catch {\n // Sandbox may already be terminated\n }\n },\n\n runCommand: async (\n ctx: TensorlakeSandboxContext,\n command: string,\n options?: RunCommandOptions\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n\n if (options?.background) {\n try {\n await ctx.sandbox.startProcess(\"sh\", {\n args: [\"-c\", command],\n stdoutMode: OutputMode.DISCARD,\n stderrMode: OutputMode.DISCARD,\n ...(options.env &&\n Object.keys(options.env).length > 0 && { env: options.env }),\n ...(options.cwd && { workingDir: options.cwd }),\n });\n } catch (error) {\n return {\n stdout: \"\",\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n }\n\n try {\n const result = await ctx.sandbox.run(\"sh\", {\n args: [\"-c\", command],\n ...(options?.env &&\n Object.keys(options.env).length > 0 && { env: options.env }),\n ...(options?.cwd && { workingDir: options.cwd }),\n });\n\n const durationMs = Date.now() - startTime;\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n durationMs,\n };\n } catch (error) {\n return {\n stdout: \"\",\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (\n ctx: TensorlakeSandboxContext\n ): Promise<ComputeSandboxInfo> => {\n try {\n const info = await ctx.sandbox.info();\n return {\n id: ctx.sandbox.sandboxId,\n provider: \"tensorlake\",\n status:\n info.status === SandboxStatus.RUNNING ? \"running\" : \"stopped\",\n createdAt: info.createdAt || new Date(),\n timeout:\n info.timeoutSecs != null ? info.timeoutSecs * 1000 : 300_000,\n metadata: {},\n };\n } catch {\n return {\n id: ctx.sandbox.sandboxId,\n provider: \"tensorlake\",\n status: \"running\",\n createdAt: new Date(),\n timeout: 300_000,\n metadata: {},\n };\n }\n },\n\n getUrl: async (\n ctx: TensorlakeSandboxContext,\n options: { port: number; protocol?: string }\n ): Promise<string> => {\n const { port, protocol: optionsProtocol } = options;\n const protocol = optionsProtocol || \"https\";\n\n const apiUrl =\n ctx.config.apiUrl ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_URL) ||\n \"https://api.tensorlake.ai\";\n\n const proxyDomain = new URL(apiUrl).hostname;\n const subdomain =\n port === 443 || port === 80\n ? ctx.sandbox.sandboxId\n : `${port}-${ctx.sandbox.sandboxId}`;\n\n return `${protocol}://${subdomain}.${proxyDomain}`;\n },\n\n filesystem: {\n readFile: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<string> => {\n const bytes = await ctx.sandbox.readFile(path);\n return Buffer.from(bytes).toString(\"utf-8\");\n },\n\n writeFile: async (\n ctx: TensorlakeSandboxContext,\n path: string,\n content: string\n ): Promise<void> => {\n await ctx.sandbox.writeFile(path, Buffer.from(content, \"utf-8\"));\n },\n\n mkdir: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<void> => {\n const result = await ctx.sandbox.run(\"mkdir\", { args: [\"-p\", path] });\n if (result.exitCode !== 0) {\n throw new Error(\n `Failed to create directory ${path}: ${result.stderr}`\n );\n }\n },\n\n readdir: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<FileEntry[]> => {\n const response = await ctx.sandbox.listDirectory(path);\n return response.entries.map((e) => ({\n name: e.name,\n type: e.isDir ? (\"directory\" as const) : (\"file\" as const),\n size: e.size || 0,\n modified: e.modifiedAt ?? new Date(),\n }));\n },\n\n exists: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<boolean> => {\n try {\n await ctx.sandbox.readFile(path);\n return true;\n } catch {}\n try {\n await ctx.sandbox.listDirectory(path);\n return true;\n } catch {}\n return false;\n },\n\n remove: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<void> => {\n try {\n await ctx.sandbox.deleteFile(path);\n } catch {\n // May be a directory — fall back to rm -rf\n const result = await ctx.sandbox.run(\"rm\", { args: [\"-rf\", path] });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n }\n },\n },\n\n getInstance: (ctx: TensorlakeSandboxContext): TensorlakeSandboxContext =>\n ctx,\n },\n\n snapshot: {\n create: async (\n config: TensorlakeConfig,\n sandboxId: string,\n options?: { name?: string }\n ) => {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n const result = await sandbox.checkpoint();\n\n if (!result) {\n throw new Error(\n `Failed to create snapshot for sandbox '${sandboxId}': checkpoint() did not return a snapshot result.`\n );\n }\n\n return {\n id: result.snapshotId,\n provider: \"tensorlake\",\n createdAt: new Date(),\n metadata: { name: options?.name },\n };\n },\n\n list: async (config: TensorlakeConfig) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n return await Sandbox.listSnapshots({ apiKey, apiUrl });\n } catch {\n return [];\n }\n },\n\n delete: async (config: TensorlakeConfig, snapshotId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n await Sandbox.deleteSnapshot(snapshotId, { apiKey, apiUrl });\n } catch {\n // Ignore\n }\n },\n },\n },\n});\n\nexport type { TensorlakeSandboxContext as TensorlakeSandbox };\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Sandbox, SandboxStatus, OutputMode } from "tensorlake";
|
|
3
|
+
import { defineProvider } from "@computesdk/provider";
|
|
4
|
+
var DEFAULT_IMAGE = "ubuntu-minimal";
|
|
5
|
+
function resolveAuth(config) {
|
|
6
|
+
const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.TENSORLAKE_API_KEY || "";
|
|
7
|
+
if (!apiKey) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
`Missing Tensorlake API key. Provide 'apiKey' in config or set TENSORLAKE_API_KEY environment variable. Get your API key from https://app.tensorlake.ai`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
const apiUrl = config.apiUrl || typeof process !== "undefined" && process.env?.TENSORLAKE_API_URL || void 0;
|
|
13
|
+
return { apiKey, apiUrl };
|
|
14
|
+
}
|
|
15
|
+
var tensorlake = defineProvider({
|
|
16
|
+
name: "tensorlake",
|
|
17
|
+
methods: {
|
|
18
|
+
sandbox: {
|
|
19
|
+
create: async (config, options) => {
|
|
20
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
21
|
+
const image = options?.image || config.image || DEFAULT_IMAGE;
|
|
22
|
+
const timeoutSecs = options?.timeout ? Math.ceil(options.timeout / 1e3) : config.timeout;
|
|
23
|
+
try {
|
|
24
|
+
const startTime = Date.now();
|
|
25
|
+
const instance = await Sandbox.create({
|
|
26
|
+
image,
|
|
27
|
+
cpus: 1,
|
|
28
|
+
memoryMb: 1024,
|
|
29
|
+
ephemeralDiskMb: 2048,
|
|
30
|
+
...timeoutSecs && { timeoutSecs },
|
|
31
|
+
...options?.name && { name: options.name },
|
|
32
|
+
...options?.snapshotId && { snapshotId: options.snapshotId },
|
|
33
|
+
proxyUrl: config.proxyUrl,
|
|
34
|
+
apiKey,
|
|
35
|
+
apiUrl
|
|
36
|
+
});
|
|
37
|
+
const sandbox = {
|
|
38
|
+
config,
|
|
39
|
+
sandbox: instance
|
|
40
|
+
};
|
|
41
|
+
const durationMs = Date.now() - startTime;
|
|
42
|
+
return {
|
|
43
|
+
sandbox,
|
|
44
|
+
sandboxId: instance.sandboxId,
|
|
45
|
+
durationMs
|
|
46
|
+
};
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof Error && error.message.includes("401")) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Tensorlake authentication failed. Please check your TENSORLAKE_API_KEY. Get your API key from https://app.tensorlake.ai`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Failed to create Tensorlake sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
getById: async (config, sandboxId) => {
|
|
59
|
+
try {
|
|
60
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
61
|
+
const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
62
|
+
const ctx = {
|
|
63
|
+
config,
|
|
64
|
+
sandbox
|
|
65
|
+
};
|
|
66
|
+
return { sandbox: ctx, sandboxId: sandbox.sandboxId };
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
list: async (config) => {
|
|
72
|
+
try {
|
|
73
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
74
|
+
const sandboxes = await Sandbox.list({ apiKey, apiUrl });
|
|
75
|
+
return Promise.all(
|
|
76
|
+
sandboxes.map(async (s) => {
|
|
77
|
+
const sandbox = await Sandbox.connect({
|
|
78
|
+
sandboxId: s.sandboxId,
|
|
79
|
+
proxyUrl: config.proxyUrl,
|
|
80
|
+
routingHint: s.routingHint,
|
|
81
|
+
apiKey,
|
|
82
|
+
apiUrl
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
sandbox: {
|
|
86
|
+
sandboxId: s.sandboxId,
|
|
87
|
+
config,
|
|
88
|
+
sandbox
|
|
89
|
+
},
|
|
90
|
+
sandboxId: s.sandboxId
|
|
91
|
+
};
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
} catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
destroy: async (config, sandboxId) => {
|
|
99
|
+
try {
|
|
100
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
101
|
+
const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
102
|
+
await sandbox.terminate();
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
runCommand: async (ctx, command, options) => {
|
|
107
|
+
const startTime = Date.now();
|
|
108
|
+
if (options?.background) {
|
|
109
|
+
try {
|
|
110
|
+
await ctx.sandbox.startProcess("sh", {
|
|
111
|
+
args: ["-c", command],
|
|
112
|
+
stdoutMode: OutputMode.DISCARD,
|
|
113
|
+
stderrMode: OutputMode.DISCARD,
|
|
114
|
+
...options.env && Object.keys(options.env).length > 0 && { env: options.env },
|
|
115
|
+
...options.cwd && { workingDir: options.cwd }
|
|
116
|
+
});
|
|
117
|
+
} catch (error) {
|
|
118
|
+
return {
|
|
119
|
+
stdout: "",
|
|
120
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
121
|
+
exitCode: 127,
|
|
122
|
+
durationMs: Date.now() - startTime
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const result = await ctx.sandbox.run("sh", {
|
|
128
|
+
args: ["-c", command],
|
|
129
|
+
...options?.env && Object.keys(options.env).length > 0 && { env: options.env },
|
|
130
|
+
...options?.cwd && { workingDir: options.cwd }
|
|
131
|
+
});
|
|
132
|
+
const durationMs = Date.now() - startTime;
|
|
133
|
+
return {
|
|
134
|
+
stdout: result.stdout,
|
|
135
|
+
stderr: result.stderr,
|
|
136
|
+
exitCode: result.exitCode ?? 0,
|
|
137
|
+
durationMs
|
|
138
|
+
};
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
stdout: "",
|
|
142
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
143
|
+
exitCode: 127,
|
|
144
|
+
durationMs: Date.now() - startTime
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
getInfo: async (ctx) => {
|
|
149
|
+
try {
|
|
150
|
+
const info = await ctx.sandbox.info();
|
|
151
|
+
return {
|
|
152
|
+
id: ctx.sandbox.sandboxId,
|
|
153
|
+
provider: "tensorlake",
|
|
154
|
+
status: info.status === SandboxStatus.RUNNING ? "running" : "stopped",
|
|
155
|
+
createdAt: info.createdAt || /* @__PURE__ */ new Date(),
|
|
156
|
+
timeout: info.timeoutSecs != null ? info.timeoutSecs * 1e3 : 3e5,
|
|
157
|
+
metadata: {}
|
|
158
|
+
};
|
|
159
|
+
} catch {
|
|
160
|
+
return {
|
|
161
|
+
id: ctx.sandbox.sandboxId,
|
|
162
|
+
provider: "tensorlake",
|
|
163
|
+
status: "running",
|
|
164
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
165
|
+
timeout: 3e5,
|
|
166
|
+
metadata: {}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
getUrl: async (ctx, options) => {
|
|
171
|
+
const { port, protocol: optionsProtocol } = options;
|
|
172
|
+
const protocol = optionsProtocol || "https";
|
|
173
|
+
const apiUrl = ctx.config.apiUrl || typeof process !== "undefined" && process.env?.TENSORLAKE_API_URL || "https://api.tensorlake.ai";
|
|
174
|
+
const proxyDomain = new URL(apiUrl).hostname;
|
|
175
|
+
const subdomain = port === 443 || port === 80 ? ctx.sandbox.sandboxId : `${port}-${ctx.sandbox.sandboxId}`;
|
|
176
|
+
return `${protocol}://${subdomain}.${proxyDomain}`;
|
|
177
|
+
},
|
|
178
|
+
filesystem: {
|
|
179
|
+
readFile: async (ctx, path) => {
|
|
180
|
+
const bytes = await ctx.sandbox.readFile(path);
|
|
181
|
+
return Buffer.from(bytes).toString("utf-8");
|
|
182
|
+
},
|
|
183
|
+
writeFile: async (ctx, path, content) => {
|
|
184
|
+
await ctx.sandbox.writeFile(path, Buffer.from(content, "utf-8"));
|
|
185
|
+
},
|
|
186
|
+
mkdir: async (ctx, path) => {
|
|
187
|
+
const result = await ctx.sandbox.run("mkdir", { args: ["-p", path] });
|
|
188
|
+
if (result.exitCode !== 0) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`Failed to create directory ${path}: ${result.stderr}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
readdir: async (ctx, path) => {
|
|
195
|
+
const response = await ctx.sandbox.listDirectory(path);
|
|
196
|
+
return response.entries.map((e) => ({
|
|
197
|
+
name: e.name,
|
|
198
|
+
type: e.isDir ? "directory" : "file",
|
|
199
|
+
size: e.size || 0,
|
|
200
|
+
modified: e.modifiedAt ?? /* @__PURE__ */ new Date()
|
|
201
|
+
}));
|
|
202
|
+
},
|
|
203
|
+
exists: async (ctx, path) => {
|
|
204
|
+
try {
|
|
205
|
+
await ctx.sandbox.readFile(path);
|
|
206
|
+
return true;
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
await ctx.sandbox.listDirectory(path);
|
|
211
|
+
return true;
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
return false;
|
|
215
|
+
},
|
|
216
|
+
remove: async (ctx, path) => {
|
|
217
|
+
try {
|
|
218
|
+
await ctx.sandbox.deleteFile(path);
|
|
219
|
+
} catch {
|
|
220
|
+
const result = await ctx.sandbox.run("rm", { args: ["-rf", path] });
|
|
221
|
+
if (result.exitCode !== 0) {
|
|
222
|
+
throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
getInstance: (ctx) => ctx
|
|
228
|
+
},
|
|
229
|
+
snapshot: {
|
|
230
|
+
create: async (config, sandboxId, options) => {
|
|
231
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
232
|
+
const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });
|
|
233
|
+
const result = await sandbox.checkpoint();
|
|
234
|
+
if (!result) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`Failed to create snapshot for sandbox '${sandboxId}': checkpoint() did not return a snapshot result.`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
id: result.snapshotId,
|
|
241
|
+
provider: "tensorlake",
|
|
242
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
243
|
+
metadata: { name: options?.name }
|
|
244
|
+
};
|
|
245
|
+
},
|
|
246
|
+
list: async (config) => {
|
|
247
|
+
try {
|
|
248
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
249
|
+
return await Sandbox.listSnapshots({ apiKey, apiUrl });
|
|
250
|
+
} catch {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
delete: async (config, snapshotId) => {
|
|
255
|
+
try {
|
|
256
|
+
const { apiKey, apiUrl } = resolveAuth(config);
|
|
257
|
+
await Sandbox.deleteSnapshot(snapshotId, { apiKey, apiUrl });
|
|
258
|
+
} catch {
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
export {
|
|
265
|
+
tensorlake
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/// <reference types=\"node\" />\n/**\n * Tensorlake Provider - SDK-based Implementation\n *\n * Stateful MicroVM sandboxes for agentic applications and LLM-generated code execution.\n * Uses the official tensorlake npm SDK (0.5.7).\n */\n\nimport { Sandbox, SandboxStatus, OutputMode } from \"tensorlake\";\nimport type { SandboxInfo } from \"tensorlake\";\nimport { defineProvider } from \"@computesdk/provider\";\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo as ComputeSandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from \"@computesdk/provider\";\n\nconst DEFAULT_IMAGE = \"ubuntu-minimal\";\n\nexport interface TensorlakeConfig {\n /** Tensorlake API key — falls back to TENSORLAKE_API_KEY environment variable */\n apiKey?: string;\n /** Override for the management API base URL */\n apiUrl?: string;\n /** Override for the sandbox proxy URL */\n proxyUrl?: string;\n /** Default container image for new sandboxes (default: ubuntu-minimal) */\n image?: string;\n /** Default timeout in milliseconds for sandboxes */\n timeout?: number;\n}\n\nexport interface TensorlakeSandboxContext {\n config: TensorlakeConfig;\n /** Connected SDK Sandbox instance — used for all proxy operations */\n sandbox: InstanceType<typeof Sandbox>;\n}\n\nfunction resolveAuth(config: TensorlakeConfig): {\n apiKey: string;\n apiUrl?: string;\n} {\n const apiKey =\n config.apiKey ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_KEY) ||\n \"\";\n if (!apiKey) {\n throw new Error(\n `Missing Tensorlake API key. Provide 'apiKey' in config or set TENSORLAKE_API_KEY environment variable. ` +\n `Get your API key from https://app.tensorlake.ai`\n );\n }\n const apiUrl =\n config.apiUrl ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_URL) ||\n undefined;\n return { apiKey, apiUrl };\n}\n\nexport const tensorlake = defineProvider<\n TensorlakeSandboxContext,\n TensorlakeConfig\n>({\n name: \"tensorlake\",\n methods: {\n sandbox: {\n create: async (\n config: TensorlakeConfig,\n options?: CreateSandboxOptions\n ) => {\n const { apiKey, apiUrl } = resolveAuth(config);\n const image = options?.image || config.image || DEFAULT_IMAGE;\n const timeoutSecs = options?.timeout\n ? Math.ceil(options.timeout / 1000)\n : config.timeout;\n\n try {\n const startTime = Date.now();\n const instance = await Sandbox.create({\n image,\n cpus: 1,\n memoryMb: 1024,\n ephemeralDiskMb: 2048,\n ...(timeoutSecs && { timeoutSecs }),\n ...(options?.name && { name: options.name }),\n ...(options?.snapshotId && { snapshotId: options.snapshotId }),\n proxyUrl: config.proxyUrl,\n apiKey,\n apiUrl,\n });\n\n const sandbox: TensorlakeSandboxContext = {\n config,\n sandbox: instance,\n };\n const durationMs = Date.now() - startTime;\n return {\n sandbox,\n sandboxId: instance.sandboxId,\n durationMs,\n };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"401\")) {\n throw new Error(\n `Tensorlake authentication failed. Please check your TENSORLAKE_API_KEY. ` +\n `Get your API key from https://app.tensorlake.ai`\n );\n }\n throw new Error(\n `Failed to create Tensorlake sandbox: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n },\n\n getById: async (config: TensorlakeConfig, sandboxId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n const ctx: TensorlakeSandboxContext = {\n config,\n sandbox,\n };\n return { sandbox: ctx, sandboxId: sandbox.sandboxId };\n } catch {\n return null;\n }\n },\n\n list: async (config: TensorlakeConfig) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandboxes = await Sandbox.list({ apiKey, apiUrl });\n return Promise.all(\n sandboxes.map(async (s) => {\n const sandbox = await Sandbox.connect({\n sandboxId: s.sandboxId,\n proxyUrl: config.proxyUrl,\n routingHint: s.routingHint,\n apiKey,\n apiUrl,\n });\n return {\n sandbox: {\n sandboxId: s.sandboxId,\n config,\n sandbox,\n } as TensorlakeSandboxContext,\n sandboxId: s.sandboxId,\n };\n })\n );\n } catch {\n return [];\n }\n },\n\n destroy: async (config: TensorlakeConfig, sandboxId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n await sandbox.terminate();\n } catch {\n // Sandbox may already be terminated\n }\n },\n\n runCommand: async (\n ctx: TensorlakeSandboxContext,\n command: string,\n options?: RunCommandOptions\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n\n if (options?.background) {\n try {\n await ctx.sandbox.startProcess(\"sh\", {\n args: [\"-c\", command],\n stdoutMode: OutputMode.DISCARD,\n stderrMode: OutputMode.DISCARD,\n ...(options.env &&\n Object.keys(options.env).length > 0 && { env: options.env }),\n ...(options.cwd && { workingDir: options.cwd }),\n });\n } catch (error) {\n return {\n stdout: \"\",\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n }\n\n try {\n const result = await ctx.sandbox.run(\"sh\", {\n args: [\"-c\", command],\n ...(options?.env &&\n Object.keys(options.env).length > 0 && { env: options.env }),\n ...(options?.cwd && { workingDir: options.cwd }),\n });\n\n const durationMs = Date.now() - startTime;\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n durationMs,\n };\n } catch (error) {\n return {\n stdout: \"\",\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (\n ctx: TensorlakeSandboxContext\n ): Promise<ComputeSandboxInfo> => {\n try {\n const info = await ctx.sandbox.info();\n return {\n id: ctx.sandbox.sandboxId,\n provider: \"tensorlake\",\n status:\n info.status === SandboxStatus.RUNNING ? \"running\" : \"stopped\",\n createdAt: info.createdAt || new Date(),\n timeout:\n info.timeoutSecs != null ? info.timeoutSecs * 1000 : 300_000,\n metadata: {},\n };\n } catch {\n return {\n id: ctx.sandbox.sandboxId,\n provider: \"tensorlake\",\n status: \"running\",\n createdAt: new Date(),\n timeout: 300_000,\n metadata: {},\n };\n }\n },\n\n getUrl: async (\n ctx: TensorlakeSandboxContext,\n options: { port: number; protocol?: string }\n ): Promise<string> => {\n const { port, protocol: optionsProtocol } = options;\n const protocol = optionsProtocol || \"https\";\n\n const apiUrl =\n ctx.config.apiUrl ||\n (typeof process !== \"undefined\" && process.env?.TENSORLAKE_API_URL) ||\n \"https://api.tensorlake.ai\";\n\n const proxyDomain = new URL(apiUrl).hostname;\n const subdomain =\n port === 443 || port === 80\n ? ctx.sandbox.sandboxId\n : `${port}-${ctx.sandbox.sandboxId}`;\n\n return `${protocol}://${subdomain}.${proxyDomain}`;\n },\n\n filesystem: {\n readFile: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<string> => {\n const bytes = await ctx.sandbox.readFile(path);\n return Buffer.from(bytes).toString(\"utf-8\");\n },\n\n writeFile: async (\n ctx: TensorlakeSandboxContext,\n path: string,\n content: string\n ): Promise<void> => {\n await ctx.sandbox.writeFile(path, Buffer.from(content, \"utf-8\"));\n },\n\n mkdir: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<void> => {\n const result = await ctx.sandbox.run(\"mkdir\", { args: [\"-p\", path] });\n if (result.exitCode !== 0) {\n throw new Error(\n `Failed to create directory ${path}: ${result.stderr}`\n );\n }\n },\n\n readdir: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<FileEntry[]> => {\n const response = await ctx.sandbox.listDirectory(path);\n return response.entries.map((e) => ({\n name: e.name,\n type: e.isDir ? (\"directory\" as const) : (\"file\" as const),\n size: e.size || 0,\n modified: e.modifiedAt ?? new Date(),\n }));\n },\n\n exists: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<boolean> => {\n try {\n await ctx.sandbox.readFile(path);\n return true;\n } catch {}\n try {\n await ctx.sandbox.listDirectory(path);\n return true;\n } catch {}\n return false;\n },\n\n remove: async (\n ctx: TensorlakeSandboxContext,\n path: string\n ): Promise<void> => {\n try {\n await ctx.sandbox.deleteFile(path);\n } catch {\n // May be a directory — fall back to rm -rf\n const result = await ctx.sandbox.run(\"rm\", { args: [\"-rf\", path] });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n }\n },\n },\n\n getInstance: (ctx: TensorlakeSandboxContext): TensorlakeSandboxContext =>\n ctx,\n },\n\n snapshot: {\n create: async (\n config: TensorlakeConfig,\n sandboxId: string,\n options?: { name?: string }\n ) => {\n const { apiKey, apiUrl } = resolveAuth(config);\n const sandbox = await Sandbox.connect({ sandboxId, apiKey, apiUrl });\n const result = await sandbox.checkpoint();\n\n if (!result) {\n throw new Error(\n `Failed to create snapshot for sandbox '${sandboxId}': checkpoint() did not return a snapshot result.`\n );\n }\n\n return {\n id: result.snapshotId,\n provider: \"tensorlake\",\n createdAt: new Date(),\n metadata: { name: options?.name },\n };\n },\n\n list: async (config: TensorlakeConfig) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n return await Sandbox.listSnapshots({ apiKey, apiUrl });\n } catch {\n return [];\n }\n },\n\n delete: async (config: TensorlakeConfig, snapshotId: string) => {\n try {\n const { apiKey, apiUrl } = resolveAuth(config);\n await Sandbox.deleteSnapshot(snapshotId, { apiKey, apiUrl });\n } catch {\n // Ignore\n }\n },\n },\n },\n});\n\nexport type { TensorlakeSandboxContext as TensorlakeSandbox };\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@computesdk/tensorlake",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Tensorlake provider for ComputeSDK - stateful MicroVM sandboxes for agentic applications and LLM-generated code execution",
|
|
5
|
+
"author": "Garrison",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"tensorlake": "0.5.7",
|
|
22
|
+
"@computesdk/provider": "2.0.0",
|
|
23
|
+
"computesdk": "4.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^20.19.39",
|
|
27
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
28
|
+
"eslint": "^8.57.1",
|
|
29
|
+
"rimraf": "^5.0.10",
|
|
30
|
+
"tsup": "^8.5.1",
|
|
31
|
+
"typescript": "^5.9.3",
|
|
32
|
+
"vitest": "^1.6.1",
|
|
33
|
+
"@computesdk/test-utils": "2.0.0"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"computesdk",
|
|
37
|
+
"tensorlake",
|
|
38
|
+
"sandbox",
|
|
39
|
+
"microvm",
|
|
40
|
+
"code-execution",
|
|
41
|
+
"agentic",
|
|
42
|
+
"cloud",
|
|
43
|
+
"compute",
|
|
44
|
+
"provider"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/computesdk/computesdk.git",
|
|
49
|
+
"directory": "packages/tensorlake"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://www.computesdk.com",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/computesdk/computesdk/issues"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsup",
|
|
57
|
+
"clean": "rimraf dist",
|
|
58
|
+
"dev": "tsup --watch",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest watch",
|
|
61
|
+
"test:coverage": "vitest run --coverage",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"lint": "eslint"
|
|
64
|
+
}
|
|
65
|
+
}
|