@computesdk/opencomputer 1.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 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,98 @@
1
+ # @computesdk/opencomputer
2
+
3
+ OpenComputer provider for ComputeSDK - create persistent cloud VMs, run commands, read/write files, expose preview URLs, and manage checkpoints through the ComputeSDK interface.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install computesdk @computesdk/opencomputer
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ Create an OpenComputer API key and set:
14
+
15
+ ```bash
16
+ export OPENCOMPUTER_API_KEY=your_api_key_here
17
+ ```
18
+
19
+ Optionally override the API URL:
20
+
21
+ ```bash
22
+ export OPENCOMPUTER_API_URL=https://app.opencomputer.dev
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```typescript
28
+ import { compute } from 'computesdk';
29
+ import { opencomputer } from '@computesdk/opencomputer';
30
+
31
+ compute.setConfig({
32
+ provider: opencomputer({ apiKey: process.env.OPENCOMPUTER_API_KEY }),
33
+ });
34
+
35
+ const sandbox = await compute.sandbox.create({ templateId: 'base' });
36
+
37
+ const result = await sandbox.runCommand('echo "Hello from OpenComputer"');
38
+ console.log(result.stdout);
39
+
40
+ await sandbox.filesystem.writeFile('/tmp/hello.txt', 'Hello ComputeSDK');
41
+ console.log(await sandbox.filesystem.readFile('/tmp/hello.txt'));
42
+
43
+ const url = await sandbox.getUrl({ port: 3000 });
44
+ console.log(url);
45
+
46
+ await sandbox.destroy();
47
+ ```
48
+
49
+ ## Configuration
50
+
51
+ ```typescript
52
+ interface OpenComputerConfig {
53
+ apiKey?: string;
54
+ apiUrl?: string;
55
+ template?: string;
56
+ timeout?: number;
57
+ envs?: Record<string, string>;
58
+ metadata?: Record<string, string>;
59
+ cpuCount?: number;
60
+ memoryMB?: number;
61
+ diskMB?: number;
62
+ secretStore?: string;
63
+ burst?: boolean;
64
+ previewAuth?: { scheme?: 'bearer'; token?: 'auto' | string };
65
+ }
66
+ ```
67
+
68
+ `timeout` uses ComputeSDK's millisecond convention and is converted to OpenComputer's seconds-based API.
69
+
70
+ ## Features
71
+
72
+ - Command execution via OpenComputer exec
73
+ - Filesystem read, write, mkdir, list, exists, and remove
74
+ - Sandbox create, reconnect by ID, and destroy
75
+ - Preview URLs for sandbox ports
76
+ - Checkpoints through ComputeSDK snapshots
77
+
78
+ ## Snapshots
79
+
80
+ OpenComputer checkpoints are scoped to a source sandbox. This provider returns snapshot IDs in the form `sandboxId:checkpointId` so ComputeSDK can later delete the checkpoint.
81
+
82
+ ```typescript
83
+ const sandbox = await compute.sandbox.create();
84
+
85
+ const snapshot = await compute.snapshot.create(sandbox.sandboxId, {
86
+ name: 'ready-state',
87
+ });
88
+
89
+ const clone = await compute.sandbox.create({ snapshotId: snapshot.id });
90
+
91
+ await compute.snapshot.delete(snapshot.id);
92
+ await clone.destroy();
93
+ await sandbox.destroy();
94
+ ```
95
+
96
+ You can also pass a raw OpenComputer checkpoint ID to `compute.sandbox.create({ snapshotId })` when you only need to fork from it.
97
+
98
+ Snapshots default to OpenComputer `disk_only` checkpoints with `promoteToFull: true`. Override with `metadata: { kind: 'full' }` or `metadata: { promoteToFull: false }` when needed.
@@ -0,0 +1,139 @@
1
+ import * as _computesdk_provider from '@computesdk/provider';
2
+
3
+ /**
4
+ * OpenComputer Provider - Factory-based Implementation
5
+ *
6
+ * Wraps the official `@opencomputer/sdk` so OpenComputer sandboxes can be used
7
+ * through the ComputeSDK provider interface.
8
+ */
9
+ interface OpenComputerProcessResult {
10
+ stdout?: string;
11
+ stderr?: string;
12
+ exitCode?: number;
13
+ }
14
+ interface OpenComputerExecSession {
15
+ sessionId: string;
16
+ }
17
+ interface OpenComputerEntryInfo {
18
+ name: string;
19
+ isDir: boolean;
20
+ path: string;
21
+ size: number;
22
+ }
23
+ interface OpenComputerCheckpointInfo {
24
+ id: string;
25
+ sandboxId?: string;
26
+ orgId?: string;
27
+ name?: string;
28
+ status?: string;
29
+ sizeBytes?: number;
30
+ createdAt?: string;
31
+ sandboxConfig?: Record<string, unknown>;
32
+ }
33
+ interface OpenComputerPreviewURLResult {
34
+ hostname?: string;
35
+ customHostname?: string;
36
+ port: number;
37
+ }
38
+ interface OpenComputerNativeSandbox {
39
+ readonly sandboxId: string;
40
+ readonly id: string;
41
+ readonly status: string;
42
+ readonly previewAuthToken?: string;
43
+ readonly webhooks?: Array<{
44
+ id: string;
45
+ url: string;
46
+ secret?: string;
47
+ }>;
48
+ readonly commands: {
49
+ run(command: string, opts?: {
50
+ cwd?: string;
51
+ env?: Record<string, string>;
52
+ timeout?: number;
53
+ timeoutMs?: number;
54
+ }): Promise<OpenComputerProcessResult>;
55
+ };
56
+ readonly exec?: {
57
+ run(command: string, opts?: {
58
+ cwd?: string;
59
+ env?: Record<string, string>;
60
+ timeout?: number;
61
+ timeoutMs?: number;
62
+ }): Promise<OpenComputerProcessResult>;
63
+ background?(command: string, opts?: {
64
+ cwd?: string;
65
+ env?: Record<string, string>;
66
+ timeout?: number;
67
+ timeoutMs?: number;
68
+ }): Promise<OpenComputerExecSession>;
69
+ };
70
+ readonly files: {
71
+ read(path: string): Promise<string>;
72
+ write(path: string, content: string): Promise<void>;
73
+ makeDir(path: string): Promise<void>;
74
+ list(path?: string): Promise<OpenComputerEntryInfo[]>;
75
+ exists(path: string): Promise<boolean>;
76
+ remove(path: string): Promise<void>;
77
+ };
78
+ getPreviewDomain(port: number): string;
79
+ createPreviewURL(opts: {
80
+ port: number;
81
+ domain?: string;
82
+ authConfig?: Record<string, unknown>;
83
+ }): Promise<OpenComputerPreviewURLResult>;
84
+ listPreviewURLs(): Promise<OpenComputerPreviewURLResult[]>;
85
+ kill(): Promise<void>;
86
+ isRunning(): Promise<boolean>;
87
+ createCheckpoint(name: string, opts?: {
88
+ kind?: 'full' | 'disk_only';
89
+ promoteToFull?: boolean;
90
+ retentionPolicy?: unknown;
91
+ }): Promise<OpenComputerCheckpointInfo>;
92
+ listCheckpoints(): Promise<OpenComputerCheckpointInfo[]>;
93
+ deleteCheckpoint(checkpointId: string): Promise<void>;
94
+ }
95
+ interface OpenComputerConfig {
96
+ /** OpenComputer API key - falls back to OPENCOMPUTER_API_KEY. */
97
+ apiKey?: string;
98
+ /** OpenComputer API URL - falls back to OPENCOMPUTER_API_URL, then production. */
99
+ apiUrl?: string;
100
+ /** Default template for new sandboxes. Defaults to OpenComputer's `base` template. */
101
+ template?: string;
102
+ /** Default idle timeout in milliseconds. OpenComputer receives this as seconds. */
103
+ timeout?: number;
104
+ /** Default environment variables for new sandboxes. */
105
+ envs?: Record<string, string>;
106
+ /** Default metadata for new sandboxes. */
107
+ metadata?: Record<string, string>;
108
+ /** OpenComputer CPU count for new sandboxes. */
109
+ cpuCount?: number;
110
+ /** OpenComputer memory size in MB for new sandboxes. */
111
+ memoryMB?: number;
112
+ /** OpenComputer workspace disk size in MB for new sandboxes. */
113
+ diskMB?: number;
114
+ /** Secret store to attach to new sandboxes. */
115
+ secretStore?: string;
116
+ /** Create Burst sandboxes by default. */
117
+ burst?: boolean;
118
+ /** Require bearer auth on preview URLs. */
119
+ previewAuth?: {
120
+ scheme?: 'bearer';
121
+ token?: 'auto' | string;
122
+ };
123
+ }
124
+ interface OpenComputerSnapshot {
125
+ id: string;
126
+ provider: 'opencomputer';
127
+ createdAt: Date;
128
+ metadata: {
129
+ sandboxId?: string;
130
+ orgId?: string;
131
+ name?: string;
132
+ status?: string;
133
+ sizeBytes?: number;
134
+ sandboxConfig?: Record<string, unknown>;
135
+ };
136
+ }
137
+ declare const opencomputer: (config?: OpenComputerConfig) => _computesdk_provider.Provider<OpenComputerNativeSandbox, any, OpenComputerSnapshot>;
138
+
139
+ export { type OpenComputerConfig, type OpenComputerNativeSandbox, type OpenComputerSnapshot, opencomputer };
@@ -0,0 +1,139 @@
1
+ import * as _computesdk_provider from '@computesdk/provider';
2
+
3
+ /**
4
+ * OpenComputer Provider - Factory-based Implementation
5
+ *
6
+ * Wraps the official `@opencomputer/sdk` so OpenComputer sandboxes can be used
7
+ * through the ComputeSDK provider interface.
8
+ */
9
+ interface OpenComputerProcessResult {
10
+ stdout?: string;
11
+ stderr?: string;
12
+ exitCode?: number;
13
+ }
14
+ interface OpenComputerExecSession {
15
+ sessionId: string;
16
+ }
17
+ interface OpenComputerEntryInfo {
18
+ name: string;
19
+ isDir: boolean;
20
+ path: string;
21
+ size: number;
22
+ }
23
+ interface OpenComputerCheckpointInfo {
24
+ id: string;
25
+ sandboxId?: string;
26
+ orgId?: string;
27
+ name?: string;
28
+ status?: string;
29
+ sizeBytes?: number;
30
+ createdAt?: string;
31
+ sandboxConfig?: Record<string, unknown>;
32
+ }
33
+ interface OpenComputerPreviewURLResult {
34
+ hostname?: string;
35
+ customHostname?: string;
36
+ port: number;
37
+ }
38
+ interface OpenComputerNativeSandbox {
39
+ readonly sandboxId: string;
40
+ readonly id: string;
41
+ readonly status: string;
42
+ readonly previewAuthToken?: string;
43
+ readonly webhooks?: Array<{
44
+ id: string;
45
+ url: string;
46
+ secret?: string;
47
+ }>;
48
+ readonly commands: {
49
+ run(command: string, opts?: {
50
+ cwd?: string;
51
+ env?: Record<string, string>;
52
+ timeout?: number;
53
+ timeoutMs?: number;
54
+ }): Promise<OpenComputerProcessResult>;
55
+ };
56
+ readonly exec?: {
57
+ run(command: string, opts?: {
58
+ cwd?: string;
59
+ env?: Record<string, string>;
60
+ timeout?: number;
61
+ timeoutMs?: number;
62
+ }): Promise<OpenComputerProcessResult>;
63
+ background?(command: string, opts?: {
64
+ cwd?: string;
65
+ env?: Record<string, string>;
66
+ timeout?: number;
67
+ timeoutMs?: number;
68
+ }): Promise<OpenComputerExecSession>;
69
+ };
70
+ readonly files: {
71
+ read(path: string): Promise<string>;
72
+ write(path: string, content: string): Promise<void>;
73
+ makeDir(path: string): Promise<void>;
74
+ list(path?: string): Promise<OpenComputerEntryInfo[]>;
75
+ exists(path: string): Promise<boolean>;
76
+ remove(path: string): Promise<void>;
77
+ };
78
+ getPreviewDomain(port: number): string;
79
+ createPreviewURL(opts: {
80
+ port: number;
81
+ domain?: string;
82
+ authConfig?: Record<string, unknown>;
83
+ }): Promise<OpenComputerPreviewURLResult>;
84
+ listPreviewURLs(): Promise<OpenComputerPreviewURLResult[]>;
85
+ kill(): Promise<void>;
86
+ isRunning(): Promise<boolean>;
87
+ createCheckpoint(name: string, opts?: {
88
+ kind?: 'full' | 'disk_only';
89
+ promoteToFull?: boolean;
90
+ retentionPolicy?: unknown;
91
+ }): Promise<OpenComputerCheckpointInfo>;
92
+ listCheckpoints(): Promise<OpenComputerCheckpointInfo[]>;
93
+ deleteCheckpoint(checkpointId: string): Promise<void>;
94
+ }
95
+ interface OpenComputerConfig {
96
+ /** OpenComputer API key - falls back to OPENCOMPUTER_API_KEY. */
97
+ apiKey?: string;
98
+ /** OpenComputer API URL - falls back to OPENCOMPUTER_API_URL, then production. */
99
+ apiUrl?: string;
100
+ /** Default template for new sandboxes. Defaults to OpenComputer's `base` template. */
101
+ template?: string;
102
+ /** Default idle timeout in milliseconds. OpenComputer receives this as seconds. */
103
+ timeout?: number;
104
+ /** Default environment variables for new sandboxes. */
105
+ envs?: Record<string, string>;
106
+ /** Default metadata for new sandboxes. */
107
+ metadata?: Record<string, string>;
108
+ /** OpenComputer CPU count for new sandboxes. */
109
+ cpuCount?: number;
110
+ /** OpenComputer memory size in MB for new sandboxes. */
111
+ memoryMB?: number;
112
+ /** OpenComputer workspace disk size in MB for new sandboxes. */
113
+ diskMB?: number;
114
+ /** Secret store to attach to new sandboxes. */
115
+ secretStore?: string;
116
+ /** Create Burst sandboxes by default. */
117
+ burst?: boolean;
118
+ /** Require bearer auth on preview URLs. */
119
+ previewAuth?: {
120
+ scheme?: 'bearer';
121
+ token?: 'auto' | string;
122
+ };
123
+ }
124
+ interface OpenComputerSnapshot {
125
+ id: string;
126
+ provider: 'opencomputer';
127
+ createdAt: Date;
128
+ metadata: {
129
+ sandboxId?: string;
130
+ orgId?: string;
131
+ name?: string;
132
+ status?: string;
133
+ sizeBytes?: number;
134
+ sandboxConfig?: Record<string, unknown>;
135
+ };
136
+ }
137
+ declare const opencomputer: (config?: OpenComputerConfig) => _computesdk_provider.Provider<OpenComputerNativeSandbox, any, OpenComputerSnapshot>;
138
+
139
+ export { type OpenComputerConfig, type OpenComputerNativeSandbox, type OpenComputerSnapshot, opencomputer };
package/dist/index.js ADDED
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ opencomputer: () => opencomputer
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_provider = require("@computesdk/provider");
37
+ var _SandboxClass = null;
38
+ async function loadSandbox() {
39
+ if (!_SandboxClass) {
40
+ const mod = await import("@opencomputer/sdk");
41
+ _SandboxClass = mod.Sandbox;
42
+ }
43
+ return _SandboxClass;
44
+ }
45
+ function env(name) {
46
+ return typeof process !== "undefined" ? process.env?.[name] : void 0;
47
+ }
48
+ function baseOpts(config) {
49
+ return {
50
+ apiKey: config.apiKey || env("OPENCOMPUTER_API_KEY"),
51
+ apiUrl: config.apiUrl || env("OPENCOMPUTER_API_URL")
52
+ };
53
+ }
54
+ function toSeconds(milliseconds) {
55
+ return milliseconds == null ? void 0 : Math.ceil(milliseconds / 1e3);
56
+ }
57
+ function stringifyMetadata(metadata) {
58
+ if (!metadata) return void 0;
59
+ const out = {};
60
+ for (const [key, value] of Object.entries(metadata)) {
61
+ if (value == null || typeof value === "function" || typeof value === "symbol") {
62
+ continue;
63
+ }
64
+ if (typeof value === "string") {
65
+ out[key] = value;
66
+ continue;
67
+ }
68
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
69
+ out[key] = String(value);
70
+ continue;
71
+ }
72
+ try {
73
+ const serialized = JSON.stringify(value);
74
+ if (serialized !== void 0) {
75
+ out[key] = serialized;
76
+ }
77
+ } catch {
78
+ }
79
+ }
80
+ return out;
81
+ }
82
+ function redactWebhooks(webhooks) {
83
+ return webhooks?.map((webhook) => ({
84
+ id: webhook.id,
85
+ url: webhook.url,
86
+ hasSecret: typeof webhook.secret === "string" && webhook.secret.length > 0
87
+ }));
88
+ }
89
+ function createOpts(config, options) {
90
+ return {
91
+ ...baseOpts(config),
92
+ template: options?.templateId || config.template,
93
+ timeout: toSeconds(options?.timeout ?? config.timeout),
94
+ envs: { ...config.envs, ...options?.envs },
95
+ metadata: { ...config.metadata, ...stringifyMetadata(options?.metadata) },
96
+ cpuCount: options?.cpuCount ?? config.cpuCount,
97
+ memoryMB: options?.memoryMB ?? options?.memory ?? config.memoryMB,
98
+ diskMB: options?.diskMB ?? config.diskMB,
99
+ secretStore: options?.secretStore ?? config.secretStore,
100
+ burst: options?.burst ?? config.burst,
101
+ sandboxFamily: options?.sandboxFamily,
102
+ previewAuth: options?.previewAuth ?? config.previewAuth,
103
+ webhooks: options?.webhooks
104
+ };
105
+ }
106
+ function snapshotToCompute(snapshot) {
107
+ const id = snapshot.sandboxId ? `${snapshot.sandboxId}:${snapshot.id}` : snapshot.id;
108
+ return {
109
+ id,
110
+ provider: "opencomputer",
111
+ createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : /* @__PURE__ */ new Date(),
112
+ metadata: {
113
+ sandboxId: snapshot.sandboxId,
114
+ orgId: snapshot.orgId,
115
+ name: snapshot.name,
116
+ status: snapshot.status,
117
+ sizeBytes: snapshot.sizeBytes,
118
+ sandboxConfig: snapshot.sandboxConfig
119
+ }
120
+ };
121
+ }
122
+ function sleep(ms) {
123
+ return new Promise((resolve) => setTimeout(resolve, ms));
124
+ }
125
+ async function waitForCheckpointReady(sandbox, checkpoint, timeoutMs = 3e5) {
126
+ if (checkpoint.status === "ready") return checkpoint;
127
+ if (checkpoint.status === "failed") {
128
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);
129
+ }
130
+ const deadline = Date.now() + timeoutMs;
131
+ let delay = 1e3;
132
+ for (; ; ) {
133
+ if (Date.now() >= deadline) {
134
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} was not ready after ${timeoutMs}ms.`);
135
+ }
136
+ const checkpoints = await sandbox.listCheckpoints();
137
+ const current = checkpoints.find((candidate) => candidate.id === checkpoint.id);
138
+ if (!current) {
139
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} disappeared while waiting for readiness.`);
140
+ }
141
+ if (current.status === "ready") return current;
142
+ if (current.status === "failed") {
143
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);
144
+ }
145
+ await sleep(delay);
146
+ delay = Math.min(delay * 1.5, 5e3);
147
+ }
148
+ }
149
+ function isCheckpointIndexMiss(error) {
150
+ if (!(error instanceof Error)) return false;
151
+ const message = error.message.toLowerCase();
152
+ return message.includes("404") && message.includes("checkpoint") && message.includes("not found");
153
+ }
154
+ async function createFromCheckpointWithRetry(Sandbox, checkpointId, opts, timeoutMs = 6e4) {
155
+ const deadline = Date.now() + timeoutMs;
156
+ let delay = 1e3;
157
+ for (; ; ) {
158
+ try {
159
+ return await Sandbox.createFromCheckpoint(checkpointId, opts);
160
+ } catch (error) {
161
+ if (!isCheckpointIndexMiss(error) || Date.now() >= deadline) {
162
+ throw error;
163
+ }
164
+ await sleep(delay);
165
+ delay = Math.min(delay * 1.5, 5e3);
166
+ }
167
+ }
168
+ }
169
+ async function createSandbox(config, options) {
170
+ const Sandbox = await loadSandbox();
171
+ const opts = createOpts(config, options);
172
+ if (options?.snapshotId) {
173
+ const checkpointId = options.snapshotId.includes(":") ? options.snapshotId.slice(options.snapshotId.indexOf(":") + 1) : options.snapshotId;
174
+ const sandbox2 = await createFromCheckpointWithRetry(Sandbox, checkpointId, {
175
+ ...baseOpts(config),
176
+ timeout: opts.timeout,
177
+ envs: opts.envs,
178
+ secretStore: opts.secretStore
179
+ });
180
+ return { sandbox: sandbox2, sandboxId: sandbox2.sandboxId || sandbox2.id };
181
+ }
182
+ const sandbox = await Sandbox.create(opts);
183
+ return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };
184
+ }
185
+ var _provider = (0, import_provider.defineProvider)({
186
+ name: "opencomputer",
187
+ methods: {
188
+ sandbox: {
189
+ create: createSandbox,
190
+ getById: async (config, sandboxId) => {
191
+ const Sandbox = await loadSandbox();
192
+ try {
193
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
194
+ return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id || sandboxId };
195
+ } catch (error) {
196
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("not found"))) {
197
+ return null;
198
+ }
199
+ throw new Error(`Failed to get OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);
200
+ }
201
+ },
202
+ list: async () => {
203
+ throw new Error("OpenComputer provider does not support listing sandboxes via the TypeScript SDK.");
204
+ },
205
+ destroy: async (config, sandboxId) => {
206
+ const Sandbox = await loadSandbox();
207
+ try {
208
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
209
+ await sandbox.kill();
210
+ } catch (error) {
211
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("not found"))) {
212
+ return;
213
+ }
214
+ throw new Error(`Failed to destroy OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);
215
+ }
216
+ },
217
+ runCommand: async (sandbox, command, options) => {
218
+ const startTime = Date.now();
219
+ try {
220
+ const runOptions = {
221
+ cwd: options?.cwd,
222
+ env: options?.env,
223
+ timeout: toSeconds(options?.timeout),
224
+ timeoutMs: options?.timeout
225
+ };
226
+ if (options?.background && sandbox.exec?.background) {
227
+ const session = await sandbox.exec.background(command, runOptions);
228
+ return {
229
+ stdout: session.sessionId,
230
+ stderr: "",
231
+ exitCode: 0,
232
+ durationMs: Date.now() - startTime
233
+ };
234
+ }
235
+ const result = await (sandbox.exec ?? sandbox.commands).run(command, runOptions);
236
+ return {
237
+ stdout: result.stdout || "",
238
+ stderr: result.stderr || "",
239
+ exitCode: result.exitCode ?? 0,
240
+ durationMs: Date.now() - startTime
241
+ };
242
+ } catch (error) {
243
+ throw new Error(`OpenComputer command execution failed: ${error instanceof Error ? error.message : String(error)}`);
244
+ }
245
+ },
246
+ getInfo: async (sandbox) => {
247
+ let status = sandbox.status;
248
+ try {
249
+ status = await sandbox.isRunning() ? "running" : sandbox.status;
250
+ } catch {
251
+ status = sandbox.status;
252
+ }
253
+ return {
254
+ id: sandbox.sandboxId || sandbox.id,
255
+ provider: "opencomputer",
256
+ status: status === "running" ? "running" : status === "error" ? "error" : "stopped",
257
+ createdAt: /* @__PURE__ */ new Date(),
258
+ timeout: 0,
259
+ metadata: {
260
+ opencomputerSandboxId: sandbox.sandboxId || sandbox.id,
261
+ previewAuthEnabled: Boolean(sandbox.previewAuthToken),
262
+ webhooks: redactWebhooks(sandbox.webhooks)
263
+ }
264
+ };
265
+ },
266
+ getUrl: async (sandbox, options) => {
267
+ const protocol = options.protocol || "https";
268
+ const domain = sandbox.getPreviewDomain(options.port);
269
+ if (domain) {
270
+ return `${protocol}://${domain}`;
271
+ }
272
+ const preview = await sandbox.createPreviewURL({ port: options.port });
273
+ const hostname = preview.customHostname || preview.hostname;
274
+ if (!hostname) {
275
+ throw new Error(`OpenComputer did not return a preview hostname for port ${options.port}.`);
276
+ }
277
+ return `${protocol}://${hostname}`;
278
+ },
279
+ filesystem: {
280
+ readFile: async (sandbox, path) => sandbox.files.read(path),
281
+ writeFile: async (sandbox, path, content) => {
282
+ await sandbox.files.write(path, content);
283
+ },
284
+ mkdir: async (sandbox, path) => {
285
+ await sandbox.files.makeDir(path);
286
+ },
287
+ readdir: async (sandbox, path) => {
288
+ const entries = await sandbox.files.list(path);
289
+ return entries.map((entry) => ({
290
+ name: entry.name,
291
+ type: entry.isDir ? "directory" : "file",
292
+ size: entry.size,
293
+ modified: /* @__PURE__ */ new Date()
294
+ }));
295
+ },
296
+ exists: async (sandbox, path) => sandbox.files.exists(path),
297
+ remove: async (sandbox, path) => {
298
+ await sandbox.files.remove(path);
299
+ }
300
+ },
301
+ getInstance: (sandbox) => sandbox
302
+ },
303
+ snapshot: {
304
+ create: async (config, sandboxId, options) => {
305
+ const Sandbox = await loadSandbox();
306
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
307
+ const metadata = options?.metadata;
308
+ const kind = metadata?.kind ?? "disk_only";
309
+ const snapshot = await sandbox.createCheckpoint(options?.name || `snapshot-${Date.now()}`, {
310
+ kind,
311
+ promoteToFull: metadata?.promoteToFull ?? (kind === "disk_only" ? true : void 0),
312
+ retentionPolicy: metadata?.retentionPolicy
313
+ });
314
+ return snapshotToCompute(await waitForCheckpointReady(sandbox, snapshot));
315
+ },
316
+ list: async (config, options) => {
317
+ if (!options?.sandboxId) {
318
+ throw new Error("OpenComputer snapshots are scoped to a sandbox. Pass `sandboxId` to list snapshots.");
319
+ }
320
+ const Sandbox = await loadSandbox();
321
+ const sandbox = await Sandbox.connect(options.sandboxId, baseOpts(config));
322
+ const snapshots = await sandbox.listCheckpoints();
323
+ return snapshots.map(snapshotToCompute);
324
+ },
325
+ delete: async (config, snapshotId) => {
326
+ const sandboxId = snapshotId.split(":", 1)[0];
327
+ if (!sandboxId || sandboxId === snapshotId) {
328
+ throw new Error("OpenComputer snapshot deletion requires a sandbox-scoped id in the form `sandboxId:checkpointId`.");
329
+ }
330
+ const checkpointId = snapshotId.slice(sandboxId.length + 1);
331
+ const Sandbox = await loadSandbox();
332
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
333
+ await sandbox.deleteCheckpoint(checkpointId);
334
+ }
335
+ }
336
+ }
337
+ });
338
+ var opencomputer = (config = {}) => _provider(config);
339
+ // Annotate the CommonJS export names for ESM import in node:
340
+ 0 && (module.exports = {
341
+ opencomputer
342
+ });
343
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * OpenComputer Provider - Factory-based Implementation\n *\n * Wraps the official `@opencomputer/sdk` so OpenComputer sandboxes can be used\n * through the ComputeSDK provider interface.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\nimport type {\n CommandResult,\n CreateSandboxOptions,\n CreateSnapshotOptions,\n FileEntry,\n ListSnapshotsOptions,\n RunCommandOptions,\n SandboxInfo,\n} from '@computesdk/provider';\n\ninterface OpenComputerSandboxOpts {\n template?: string;\n timeout?: number;\n apiKey?: string;\n apiUrl?: string;\n envs?: Record<string, string>;\n metadata?: Record<string, string>;\n cpuCount?: number;\n memoryMB?: number;\n diskMB?: number;\n secretStore?: string;\n snapshot?: string;\n burst?: boolean;\n sandboxFamily?: 'spot';\n previewAuth?: { scheme?: 'bearer'; token?: 'auto' | string };\n webhooks?: Array<{ url: string; secret?: string; eventTypes?: string[] }>;\n}\n\ninterface OpenComputerProcessResult {\n stdout?: string;\n stderr?: string;\n exitCode?: number;\n}\n\ninterface OpenComputerExecSession {\n sessionId: string;\n}\n\ninterface OpenComputerEntryInfo {\n name: string;\n isDir: boolean;\n path: string;\n size: number;\n}\n\ninterface OpenComputerCheckpointInfo {\n id: string;\n sandboxId?: string;\n orgId?: string;\n name?: string;\n status?: string;\n sizeBytes?: number;\n createdAt?: string;\n sandboxConfig?: Record<string, unknown>;\n}\n\ninterface OpenComputerPreviewURLResult {\n hostname?: string;\n customHostname?: string;\n port: number;\n}\n\ninterface OpenComputerNativeSandbox {\n readonly sandboxId: string;\n readonly id: string;\n readonly status: string;\n readonly previewAuthToken?: string;\n readonly webhooks?: Array<{ id: string; url: string; secret?: string }>;\n readonly commands: {\n run(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerProcessResult>;\n };\n readonly exec?: {\n run(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerProcessResult>;\n background?(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerExecSession>;\n };\n readonly files: {\n read(path: string): Promise<string>;\n write(path: string, content: string): Promise<void>;\n makeDir(path: string): Promise<void>;\n list(path?: string): Promise<OpenComputerEntryInfo[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n };\n getPreviewDomain(port: number): string;\n createPreviewURL(opts: { port: number; domain?: string; authConfig?: Record<string, unknown> }): Promise<OpenComputerPreviewURLResult>;\n listPreviewURLs(): Promise<OpenComputerPreviewURLResult[]>;\n kill(): Promise<void>;\n isRunning(): Promise<boolean>;\n createCheckpoint(name: string, opts?: { kind?: 'full' | 'disk_only'; promoteToFull?: boolean; retentionPolicy?: unknown }): Promise<OpenComputerCheckpointInfo>;\n listCheckpoints(): Promise<OpenComputerCheckpointInfo[]>;\n deleteCheckpoint(checkpointId: string): Promise<void>;\n}\n\ninterface OpenComputerSandboxStatic {\n create(opts?: OpenComputerSandboxOpts): Promise<OpenComputerNativeSandbox>;\n connect(sandboxId: string, opts?: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl'>): Promise<OpenComputerNativeSandbox>;\n createFromCheckpoint(checkpointId: string, opts?: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl' | 'timeout' | 'envs' | 'secretStore'>): Promise<OpenComputerNativeSandbox>;\n}\n\nlet _SandboxClass: OpenComputerSandboxStatic | null = null;\n\nasync function loadSandbox(): Promise<OpenComputerSandboxStatic> {\n if (!_SandboxClass) {\n const mod = await import('@opencomputer/sdk');\n _SandboxClass = (mod as { Sandbox: OpenComputerSandboxStatic }).Sandbox;\n }\n return _SandboxClass;\n}\n\nexport interface OpenComputerConfig {\n /** OpenComputer API key - falls back to OPENCOMPUTER_API_KEY. */\n apiKey?: string;\n /** OpenComputer API URL - falls back to OPENCOMPUTER_API_URL, then production. */\n apiUrl?: string;\n /** Default template for new sandboxes. Defaults to OpenComputer's `base` template. */\n template?: string;\n /** Default idle timeout in milliseconds. OpenComputer receives this as seconds. */\n timeout?: number;\n /** Default environment variables for new sandboxes. */\n envs?: Record<string, string>;\n /** Default metadata for new sandboxes. */\n metadata?: Record<string, string>;\n /** OpenComputer CPU count for new sandboxes. */\n cpuCount?: number;\n /** OpenComputer memory size in MB for new sandboxes. */\n memoryMB?: number;\n /** OpenComputer workspace disk size in MB for new sandboxes. */\n diskMB?: number;\n /** Secret store to attach to new sandboxes. */\n secretStore?: string;\n /** Create Burst sandboxes by default. */\n burst?: boolean;\n /** Require bearer auth on preview URLs. */\n previewAuth?: { scheme?: 'bearer'; token?: 'auto' | string };\n}\n\nexport interface OpenComputerSnapshot {\n id: string;\n provider: 'opencomputer';\n createdAt: Date;\n metadata: {\n sandboxId?: string;\n orgId?: string;\n name?: string;\n status?: string;\n sizeBytes?: number;\n sandboxConfig?: Record<string, unknown>;\n };\n}\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined;\n}\n\nfunction baseOpts(config: OpenComputerConfig): Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl'> {\n return {\n apiKey: config.apiKey || env('OPENCOMPUTER_API_KEY'),\n apiUrl: config.apiUrl || env('OPENCOMPUTER_API_URL'),\n };\n}\n\nfunction toSeconds(milliseconds: number | undefined): number | undefined {\n return milliseconds == null ? undefined : Math.ceil(milliseconds / 1000);\n}\n\nfunction stringifyMetadata(metadata: Record<string, unknown> | undefined): Record<string, string> | undefined {\n if (!metadata) return undefined;\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (value == null || typeof value === 'function' || typeof value === 'symbol') {\n continue;\n }\n if (typeof value === 'string') {\n out[key] = value;\n continue;\n }\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n out[key] = String(value);\n continue;\n }\n try {\n const serialized = JSON.stringify(value);\n if (serialized !== undefined) {\n out[key] = serialized;\n }\n } catch {\n // Skip metadata values that cannot be represented as JSON strings.\n }\n }\n return out;\n}\n\nfunction redactWebhooks(webhooks: OpenComputerNativeSandbox['webhooks']): Array<{ id: string; url: string; hasSecret: boolean }> | undefined {\n return webhooks?.map((webhook) => ({\n id: webhook.id,\n url: webhook.url,\n hasSecret: typeof webhook.secret === 'string' && webhook.secret.length > 0,\n }));\n}\n\nfunction createOpts(config: OpenComputerConfig, options?: CreateSandboxOptions): OpenComputerSandboxOpts {\n return {\n ...baseOpts(config),\n template: options?.templateId || config.template,\n timeout: toSeconds(options?.timeout ?? config.timeout),\n envs: { ...config.envs, ...options?.envs },\n metadata: { ...config.metadata, ...stringifyMetadata(options?.metadata) },\n cpuCount: (options as any)?.cpuCount ?? config.cpuCount,\n memoryMB: (options as any)?.memoryMB ?? (options as any)?.memory ?? config.memoryMB,\n diskMB: (options as any)?.diskMB ?? config.diskMB,\n secretStore: (options as any)?.secretStore ?? config.secretStore,\n burst: (options as any)?.burst ?? config.burst,\n sandboxFamily: (options as any)?.sandboxFamily,\n previewAuth: (options as any)?.previewAuth ?? config.previewAuth,\n webhooks: (options as any)?.webhooks,\n };\n}\n\nfunction snapshotToCompute(snapshot: OpenComputerCheckpointInfo): OpenComputerSnapshot {\n const id = snapshot.sandboxId ? `${snapshot.sandboxId}:${snapshot.id}` : snapshot.id;\n return {\n id,\n provider: 'opencomputer',\n createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : new Date(),\n metadata: {\n sandboxId: snapshot.sandboxId,\n orgId: snapshot.orgId,\n name: snapshot.name,\n status: snapshot.status,\n sizeBytes: snapshot.sizeBytes,\n sandboxConfig: snapshot.sandboxConfig,\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function waitForCheckpointReady(\n sandbox: OpenComputerNativeSandbox,\n checkpoint: OpenComputerCheckpointInfo,\n timeoutMs = 300_000,\n): Promise<OpenComputerCheckpointInfo> {\n if (checkpoint.status === 'ready') return checkpoint;\n if (checkpoint.status === 'failed') {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);\n }\n\n const deadline = Date.now() + timeoutMs;\n let delay = 1_000;\n\n for (;;) {\n if (Date.now() >= deadline) {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} was not ready after ${timeoutMs}ms.`);\n }\n\n const checkpoints = await sandbox.listCheckpoints();\n const current = checkpoints.find((candidate) => candidate.id === checkpoint.id);\n if (!current) {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} disappeared while waiting for readiness.`);\n }\n if (current.status === 'ready') return current;\n if (current.status === 'failed') {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);\n }\n\n await sleep(delay);\n delay = Math.min(delay * 1.5, 5_000);\n }\n}\n\nfunction isCheckpointIndexMiss(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const message = error.message.toLowerCase();\n return message.includes('404') && message.includes('checkpoint') && message.includes('not found');\n}\n\nasync function createFromCheckpointWithRetry(\n Sandbox: OpenComputerSandboxStatic,\n checkpointId: string,\n opts: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl' | 'timeout' | 'envs' | 'secretStore'>,\n timeoutMs = 60_000,\n): Promise<OpenComputerNativeSandbox> {\n const deadline = Date.now() + timeoutMs;\n let delay = 1_000;\n\n for (;;) {\n try {\n return await Sandbox.createFromCheckpoint(checkpointId, opts);\n } catch (error) {\n if (!isCheckpointIndexMiss(error) || Date.now() >= deadline) {\n throw error;\n }\n await sleep(delay);\n delay = Math.min(delay * 1.5, 5_000);\n }\n }\n}\n\nasync function createSandbox(config: OpenComputerConfig, options?: CreateSandboxOptions) {\n const Sandbox = await loadSandbox();\n const opts = createOpts(config, options);\n\n if (options?.snapshotId) {\n const checkpointId = options.snapshotId.includes(':')\n ? options.snapshotId.slice(options.snapshotId.indexOf(':') + 1)\n : options.snapshotId;\n const sandbox = await createFromCheckpointWithRetry(Sandbox, checkpointId, {\n ...baseOpts(config),\n timeout: opts.timeout,\n envs: opts.envs,\n secretStore: opts.secretStore,\n });\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };\n }\n\n const sandbox = await Sandbox.create(opts);\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };\n}\n\nconst _provider = defineProvider<OpenComputerNativeSandbox, OpenComputerConfig, any, OpenComputerSnapshot>({\n name: 'opencomputer',\n methods: {\n sandbox: {\n create: createSandbox,\n\n getById: async (config: OpenComputerConfig, sandboxId: string) => {\n const Sandbox = await loadSandbox();\n try {\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id || sandboxId };\n } catch (error) {\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('not found'))) {\n return null;\n }\n throw new Error(`Failed to get OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n list: async () => {\n throw new Error('OpenComputer provider does not support listing sandboxes via the TypeScript SDK.');\n },\n\n destroy: async (config: OpenComputerConfig, sandboxId: string) => {\n const Sandbox = await loadSandbox();\n try {\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n await sandbox.kill();\n } catch (error) {\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('not found'))) {\n return;\n }\n throw new Error(`Failed to destroy OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (sandbox: OpenComputerNativeSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const runOptions = {\n cwd: options?.cwd,\n env: options?.env,\n timeout: toSeconds(options?.timeout),\n timeoutMs: options?.timeout,\n };\n if (options?.background && sandbox.exec?.background) {\n const session = await sandbox.exec.background(command, runOptions);\n return {\n stdout: session.sessionId,\n stderr: '',\n exitCode: 0,\n durationMs: Date.now() - startTime,\n };\n }\n\n const result = await (sandbox.exec ?? sandbox.commands).run(command, runOptions);\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode ?? 0,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n throw new Error(`OpenComputer command execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getInfo: async (sandbox: OpenComputerNativeSandbox): Promise<SandboxInfo> => {\n let status = sandbox.status;\n try {\n status = (await sandbox.isRunning()) ? 'running' : sandbox.status;\n } catch {\n status = sandbox.status;\n }\n\n return {\n id: sandbox.sandboxId || sandbox.id,\n provider: 'opencomputer',\n status: status === 'running' ? 'running' : status === 'error' ? 'error' : 'stopped',\n createdAt: new Date(),\n timeout: 0,\n metadata: {\n opencomputerSandboxId: sandbox.sandboxId || sandbox.id,\n previewAuthEnabled: Boolean(sandbox.previewAuthToken),\n webhooks: redactWebhooks(sandbox.webhooks),\n },\n };\n },\n\n getUrl: async (sandbox: OpenComputerNativeSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n const domain = sandbox.getPreviewDomain(options.port);\n if (domain) {\n return `${protocol}://${domain}`;\n }\n\n const preview = await sandbox.createPreviewURL({ port: options.port });\n const hostname = preview.customHostname || preview.hostname;\n if (!hostname) {\n throw new Error(`OpenComputer did not return a preview hostname for port ${options.port}.`);\n }\n return `${protocol}://${hostname}`;\n },\n\n filesystem: {\n readFile: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<string> =>\n sandbox.files.read(path),\n writeFile: async (sandbox: OpenComputerNativeSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n mkdir: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n readdir: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n return entries.map((entry) => ({\n name: entry.name,\n type: entry.isDir ? 'directory' as const : 'file' as const,\n size: entry.size,\n modified: new Date(),\n }));\n },\n exists: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<boolean> =>\n sandbox.files.exists(path),\n remove: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n },\n },\n\n getInstance: (sandbox: OpenComputerNativeSandbox): OpenComputerNativeSandbox => sandbox,\n },\n\n snapshot: {\n create: async (config: OpenComputerConfig, sandboxId: string, options?: CreateSnapshotOptions) => {\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n const metadata = options?.metadata as\n | { kind?: 'full' | 'disk_only'; promoteToFull?: boolean; retentionPolicy?: unknown }\n | undefined;\n const kind = metadata?.kind ?? 'disk_only';\n const snapshot = await sandbox.createCheckpoint(options?.name || `snapshot-${Date.now()}`, {\n kind,\n promoteToFull: metadata?.promoteToFull ?? (kind === 'disk_only' ? true : undefined),\n retentionPolicy: metadata?.retentionPolicy,\n });\n return snapshotToCompute(await waitForCheckpointReady(sandbox, snapshot));\n },\n list: async (config: OpenComputerConfig, options?: ListSnapshotsOptions) => {\n if (!options?.sandboxId) {\n throw new Error('OpenComputer snapshots are scoped to a sandbox. Pass `sandboxId` to list snapshots.');\n }\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(options.sandboxId, baseOpts(config));\n const snapshots = await sandbox.listCheckpoints();\n return snapshots.map(snapshotToCompute);\n },\n delete: async (config: OpenComputerConfig, snapshotId: string) => {\n const sandboxId = snapshotId.split(':', 1)[0];\n if (!sandboxId || sandboxId === snapshotId) {\n throw new Error('OpenComputer snapshot deletion requires a sandbox-scoped id in the form `sandboxId:checkpointId`.');\n }\n const checkpointId = snapshotId.slice(sandboxId.length + 1);\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n await sandbox.deleteCheckpoint(checkpointId);\n },\n },\n },\n});\n\nexport const opencomputer = (config: OpenComputerConfig = {}) => _provider(config);\nexport type { OpenComputerNativeSandbox };\n"],"mappings":"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","names":["sandbox"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,308 @@
1
+ // src/index.ts
2
+ import { defineProvider } from "@computesdk/provider";
3
+ var _SandboxClass = null;
4
+ async function loadSandbox() {
5
+ if (!_SandboxClass) {
6
+ const mod = await import("@opencomputer/sdk");
7
+ _SandboxClass = mod.Sandbox;
8
+ }
9
+ return _SandboxClass;
10
+ }
11
+ function env(name) {
12
+ return typeof process !== "undefined" ? process.env?.[name] : void 0;
13
+ }
14
+ function baseOpts(config) {
15
+ return {
16
+ apiKey: config.apiKey || env("OPENCOMPUTER_API_KEY"),
17
+ apiUrl: config.apiUrl || env("OPENCOMPUTER_API_URL")
18
+ };
19
+ }
20
+ function toSeconds(milliseconds) {
21
+ return milliseconds == null ? void 0 : Math.ceil(milliseconds / 1e3);
22
+ }
23
+ function stringifyMetadata(metadata) {
24
+ if (!metadata) return void 0;
25
+ const out = {};
26
+ for (const [key, value] of Object.entries(metadata)) {
27
+ if (value == null || typeof value === "function" || typeof value === "symbol") {
28
+ continue;
29
+ }
30
+ if (typeof value === "string") {
31
+ out[key] = value;
32
+ continue;
33
+ }
34
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
35
+ out[key] = String(value);
36
+ continue;
37
+ }
38
+ try {
39
+ const serialized = JSON.stringify(value);
40
+ if (serialized !== void 0) {
41
+ out[key] = serialized;
42
+ }
43
+ } catch {
44
+ }
45
+ }
46
+ return out;
47
+ }
48
+ function redactWebhooks(webhooks) {
49
+ return webhooks?.map((webhook) => ({
50
+ id: webhook.id,
51
+ url: webhook.url,
52
+ hasSecret: typeof webhook.secret === "string" && webhook.secret.length > 0
53
+ }));
54
+ }
55
+ function createOpts(config, options) {
56
+ return {
57
+ ...baseOpts(config),
58
+ template: options?.templateId || config.template,
59
+ timeout: toSeconds(options?.timeout ?? config.timeout),
60
+ envs: { ...config.envs, ...options?.envs },
61
+ metadata: { ...config.metadata, ...stringifyMetadata(options?.metadata) },
62
+ cpuCount: options?.cpuCount ?? config.cpuCount,
63
+ memoryMB: options?.memoryMB ?? options?.memory ?? config.memoryMB,
64
+ diskMB: options?.diskMB ?? config.diskMB,
65
+ secretStore: options?.secretStore ?? config.secretStore,
66
+ burst: options?.burst ?? config.burst,
67
+ sandboxFamily: options?.sandboxFamily,
68
+ previewAuth: options?.previewAuth ?? config.previewAuth,
69
+ webhooks: options?.webhooks
70
+ };
71
+ }
72
+ function snapshotToCompute(snapshot) {
73
+ const id = snapshot.sandboxId ? `${snapshot.sandboxId}:${snapshot.id}` : snapshot.id;
74
+ return {
75
+ id,
76
+ provider: "opencomputer",
77
+ createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : /* @__PURE__ */ new Date(),
78
+ metadata: {
79
+ sandboxId: snapshot.sandboxId,
80
+ orgId: snapshot.orgId,
81
+ name: snapshot.name,
82
+ status: snapshot.status,
83
+ sizeBytes: snapshot.sizeBytes,
84
+ sandboxConfig: snapshot.sandboxConfig
85
+ }
86
+ };
87
+ }
88
+ function sleep(ms) {
89
+ return new Promise((resolve) => setTimeout(resolve, ms));
90
+ }
91
+ async function waitForCheckpointReady(sandbox, checkpoint, timeoutMs = 3e5) {
92
+ if (checkpoint.status === "ready") return checkpoint;
93
+ if (checkpoint.status === "failed") {
94
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);
95
+ }
96
+ const deadline = Date.now() + timeoutMs;
97
+ let delay = 1e3;
98
+ for (; ; ) {
99
+ if (Date.now() >= deadline) {
100
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} was not ready after ${timeoutMs}ms.`);
101
+ }
102
+ const checkpoints = await sandbox.listCheckpoints();
103
+ const current = checkpoints.find((candidate) => candidate.id === checkpoint.id);
104
+ if (!current) {
105
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} disappeared while waiting for readiness.`);
106
+ }
107
+ if (current.status === "ready") return current;
108
+ if (current.status === "failed") {
109
+ throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);
110
+ }
111
+ await sleep(delay);
112
+ delay = Math.min(delay * 1.5, 5e3);
113
+ }
114
+ }
115
+ function isCheckpointIndexMiss(error) {
116
+ if (!(error instanceof Error)) return false;
117
+ const message = error.message.toLowerCase();
118
+ return message.includes("404") && message.includes("checkpoint") && message.includes("not found");
119
+ }
120
+ async function createFromCheckpointWithRetry(Sandbox, checkpointId, opts, timeoutMs = 6e4) {
121
+ const deadline = Date.now() + timeoutMs;
122
+ let delay = 1e3;
123
+ for (; ; ) {
124
+ try {
125
+ return await Sandbox.createFromCheckpoint(checkpointId, opts);
126
+ } catch (error) {
127
+ if (!isCheckpointIndexMiss(error) || Date.now() >= deadline) {
128
+ throw error;
129
+ }
130
+ await sleep(delay);
131
+ delay = Math.min(delay * 1.5, 5e3);
132
+ }
133
+ }
134
+ }
135
+ async function createSandbox(config, options) {
136
+ const Sandbox = await loadSandbox();
137
+ const opts = createOpts(config, options);
138
+ if (options?.snapshotId) {
139
+ const checkpointId = options.snapshotId.includes(":") ? options.snapshotId.slice(options.snapshotId.indexOf(":") + 1) : options.snapshotId;
140
+ const sandbox2 = await createFromCheckpointWithRetry(Sandbox, checkpointId, {
141
+ ...baseOpts(config),
142
+ timeout: opts.timeout,
143
+ envs: opts.envs,
144
+ secretStore: opts.secretStore
145
+ });
146
+ return { sandbox: sandbox2, sandboxId: sandbox2.sandboxId || sandbox2.id };
147
+ }
148
+ const sandbox = await Sandbox.create(opts);
149
+ return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };
150
+ }
151
+ var _provider = defineProvider({
152
+ name: "opencomputer",
153
+ methods: {
154
+ sandbox: {
155
+ create: createSandbox,
156
+ getById: async (config, sandboxId) => {
157
+ const Sandbox = await loadSandbox();
158
+ try {
159
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
160
+ return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id || sandboxId };
161
+ } catch (error) {
162
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("not found"))) {
163
+ return null;
164
+ }
165
+ throw new Error(`Failed to get OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);
166
+ }
167
+ },
168
+ list: async () => {
169
+ throw new Error("OpenComputer provider does not support listing sandboxes via the TypeScript SDK.");
170
+ },
171
+ destroy: async (config, sandboxId) => {
172
+ const Sandbox = await loadSandbox();
173
+ try {
174
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
175
+ await sandbox.kill();
176
+ } catch (error) {
177
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("not found"))) {
178
+ return;
179
+ }
180
+ throw new Error(`Failed to destroy OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);
181
+ }
182
+ },
183
+ runCommand: async (sandbox, command, options) => {
184
+ const startTime = Date.now();
185
+ try {
186
+ const runOptions = {
187
+ cwd: options?.cwd,
188
+ env: options?.env,
189
+ timeout: toSeconds(options?.timeout),
190
+ timeoutMs: options?.timeout
191
+ };
192
+ if (options?.background && sandbox.exec?.background) {
193
+ const session = await sandbox.exec.background(command, runOptions);
194
+ return {
195
+ stdout: session.sessionId,
196
+ stderr: "",
197
+ exitCode: 0,
198
+ durationMs: Date.now() - startTime
199
+ };
200
+ }
201
+ const result = await (sandbox.exec ?? sandbox.commands).run(command, runOptions);
202
+ return {
203
+ stdout: result.stdout || "",
204
+ stderr: result.stderr || "",
205
+ exitCode: result.exitCode ?? 0,
206
+ durationMs: Date.now() - startTime
207
+ };
208
+ } catch (error) {
209
+ throw new Error(`OpenComputer command execution failed: ${error instanceof Error ? error.message : String(error)}`);
210
+ }
211
+ },
212
+ getInfo: async (sandbox) => {
213
+ let status = sandbox.status;
214
+ try {
215
+ status = await sandbox.isRunning() ? "running" : sandbox.status;
216
+ } catch {
217
+ status = sandbox.status;
218
+ }
219
+ return {
220
+ id: sandbox.sandboxId || sandbox.id,
221
+ provider: "opencomputer",
222
+ status: status === "running" ? "running" : status === "error" ? "error" : "stopped",
223
+ createdAt: /* @__PURE__ */ new Date(),
224
+ timeout: 0,
225
+ metadata: {
226
+ opencomputerSandboxId: sandbox.sandboxId || sandbox.id,
227
+ previewAuthEnabled: Boolean(sandbox.previewAuthToken),
228
+ webhooks: redactWebhooks(sandbox.webhooks)
229
+ }
230
+ };
231
+ },
232
+ getUrl: async (sandbox, options) => {
233
+ const protocol = options.protocol || "https";
234
+ const domain = sandbox.getPreviewDomain(options.port);
235
+ if (domain) {
236
+ return `${protocol}://${domain}`;
237
+ }
238
+ const preview = await sandbox.createPreviewURL({ port: options.port });
239
+ const hostname = preview.customHostname || preview.hostname;
240
+ if (!hostname) {
241
+ throw new Error(`OpenComputer did not return a preview hostname for port ${options.port}.`);
242
+ }
243
+ return `${protocol}://${hostname}`;
244
+ },
245
+ filesystem: {
246
+ readFile: async (sandbox, path) => sandbox.files.read(path),
247
+ writeFile: async (sandbox, path, content) => {
248
+ await sandbox.files.write(path, content);
249
+ },
250
+ mkdir: async (sandbox, path) => {
251
+ await sandbox.files.makeDir(path);
252
+ },
253
+ readdir: async (sandbox, path) => {
254
+ const entries = await sandbox.files.list(path);
255
+ return entries.map((entry) => ({
256
+ name: entry.name,
257
+ type: entry.isDir ? "directory" : "file",
258
+ size: entry.size,
259
+ modified: /* @__PURE__ */ new Date()
260
+ }));
261
+ },
262
+ exists: async (sandbox, path) => sandbox.files.exists(path),
263
+ remove: async (sandbox, path) => {
264
+ await sandbox.files.remove(path);
265
+ }
266
+ },
267
+ getInstance: (sandbox) => sandbox
268
+ },
269
+ snapshot: {
270
+ create: async (config, sandboxId, options) => {
271
+ const Sandbox = await loadSandbox();
272
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
273
+ const metadata = options?.metadata;
274
+ const kind = metadata?.kind ?? "disk_only";
275
+ const snapshot = await sandbox.createCheckpoint(options?.name || `snapshot-${Date.now()}`, {
276
+ kind,
277
+ promoteToFull: metadata?.promoteToFull ?? (kind === "disk_only" ? true : void 0),
278
+ retentionPolicy: metadata?.retentionPolicy
279
+ });
280
+ return snapshotToCompute(await waitForCheckpointReady(sandbox, snapshot));
281
+ },
282
+ list: async (config, options) => {
283
+ if (!options?.sandboxId) {
284
+ throw new Error("OpenComputer snapshots are scoped to a sandbox. Pass `sandboxId` to list snapshots.");
285
+ }
286
+ const Sandbox = await loadSandbox();
287
+ const sandbox = await Sandbox.connect(options.sandboxId, baseOpts(config));
288
+ const snapshots = await sandbox.listCheckpoints();
289
+ return snapshots.map(snapshotToCompute);
290
+ },
291
+ delete: async (config, snapshotId) => {
292
+ const sandboxId = snapshotId.split(":", 1)[0];
293
+ if (!sandboxId || sandboxId === snapshotId) {
294
+ throw new Error("OpenComputer snapshot deletion requires a sandbox-scoped id in the form `sandboxId:checkpointId`.");
295
+ }
296
+ const checkpointId = snapshotId.slice(sandboxId.length + 1);
297
+ const Sandbox = await loadSandbox();
298
+ const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));
299
+ await sandbox.deleteCheckpoint(checkpointId);
300
+ }
301
+ }
302
+ }
303
+ });
304
+ var opencomputer = (config = {}) => _provider(config);
305
+ export {
306
+ opencomputer
307
+ };
308
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * OpenComputer Provider - Factory-based Implementation\n *\n * Wraps the official `@opencomputer/sdk` so OpenComputer sandboxes can be used\n * through the ComputeSDK provider interface.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\nimport type {\n CommandResult,\n CreateSandboxOptions,\n CreateSnapshotOptions,\n FileEntry,\n ListSnapshotsOptions,\n RunCommandOptions,\n SandboxInfo,\n} from '@computesdk/provider';\n\ninterface OpenComputerSandboxOpts {\n template?: string;\n timeout?: number;\n apiKey?: string;\n apiUrl?: string;\n envs?: Record<string, string>;\n metadata?: Record<string, string>;\n cpuCount?: number;\n memoryMB?: number;\n diskMB?: number;\n secretStore?: string;\n snapshot?: string;\n burst?: boolean;\n sandboxFamily?: 'spot';\n previewAuth?: { scheme?: 'bearer'; token?: 'auto' | string };\n webhooks?: Array<{ url: string; secret?: string; eventTypes?: string[] }>;\n}\n\ninterface OpenComputerProcessResult {\n stdout?: string;\n stderr?: string;\n exitCode?: number;\n}\n\ninterface OpenComputerExecSession {\n sessionId: string;\n}\n\ninterface OpenComputerEntryInfo {\n name: string;\n isDir: boolean;\n path: string;\n size: number;\n}\n\ninterface OpenComputerCheckpointInfo {\n id: string;\n sandboxId?: string;\n orgId?: string;\n name?: string;\n status?: string;\n sizeBytes?: number;\n createdAt?: string;\n sandboxConfig?: Record<string, unknown>;\n}\n\ninterface OpenComputerPreviewURLResult {\n hostname?: string;\n customHostname?: string;\n port: number;\n}\n\ninterface OpenComputerNativeSandbox {\n readonly sandboxId: string;\n readonly id: string;\n readonly status: string;\n readonly previewAuthToken?: string;\n readonly webhooks?: Array<{ id: string; url: string; secret?: string }>;\n readonly commands: {\n run(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerProcessResult>;\n };\n readonly exec?: {\n run(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerProcessResult>;\n background?(command: string, opts?: { cwd?: string; env?: Record<string, string>; timeout?: number; timeoutMs?: number }): Promise<OpenComputerExecSession>;\n };\n readonly files: {\n read(path: string): Promise<string>;\n write(path: string, content: string): Promise<void>;\n makeDir(path: string): Promise<void>;\n list(path?: string): Promise<OpenComputerEntryInfo[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n };\n getPreviewDomain(port: number): string;\n createPreviewURL(opts: { port: number; domain?: string; authConfig?: Record<string, unknown> }): Promise<OpenComputerPreviewURLResult>;\n listPreviewURLs(): Promise<OpenComputerPreviewURLResult[]>;\n kill(): Promise<void>;\n isRunning(): Promise<boolean>;\n createCheckpoint(name: string, opts?: { kind?: 'full' | 'disk_only'; promoteToFull?: boolean; retentionPolicy?: unknown }): Promise<OpenComputerCheckpointInfo>;\n listCheckpoints(): Promise<OpenComputerCheckpointInfo[]>;\n deleteCheckpoint(checkpointId: string): Promise<void>;\n}\n\ninterface OpenComputerSandboxStatic {\n create(opts?: OpenComputerSandboxOpts): Promise<OpenComputerNativeSandbox>;\n connect(sandboxId: string, opts?: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl'>): Promise<OpenComputerNativeSandbox>;\n createFromCheckpoint(checkpointId: string, opts?: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl' | 'timeout' | 'envs' | 'secretStore'>): Promise<OpenComputerNativeSandbox>;\n}\n\nlet _SandboxClass: OpenComputerSandboxStatic | null = null;\n\nasync function loadSandbox(): Promise<OpenComputerSandboxStatic> {\n if (!_SandboxClass) {\n const mod = await import('@opencomputer/sdk');\n _SandboxClass = (mod as { Sandbox: OpenComputerSandboxStatic }).Sandbox;\n }\n return _SandboxClass;\n}\n\nexport interface OpenComputerConfig {\n /** OpenComputer API key - falls back to OPENCOMPUTER_API_KEY. */\n apiKey?: string;\n /** OpenComputer API URL - falls back to OPENCOMPUTER_API_URL, then production. */\n apiUrl?: string;\n /** Default template for new sandboxes. Defaults to OpenComputer's `base` template. */\n template?: string;\n /** Default idle timeout in milliseconds. OpenComputer receives this as seconds. */\n timeout?: number;\n /** Default environment variables for new sandboxes. */\n envs?: Record<string, string>;\n /** Default metadata for new sandboxes. */\n metadata?: Record<string, string>;\n /** OpenComputer CPU count for new sandboxes. */\n cpuCount?: number;\n /** OpenComputer memory size in MB for new sandboxes. */\n memoryMB?: number;\n /** OpenComputer workspace disk size in MB for new sandboxes. */\n diskMB?: number;\n /** Secret store to attach to new sandboxes. */\n secretStore?: string;\n /** Create Burst sandboxes by default. */\n burst?: boolean;\n /** Require bearer auth on preview URLs. */\n previewAuth?: { scheme?: 'bearer'; token?: 'auto' | string };\n}\n\nexport interface OpenComputerSnapshot {\n id: string;\n provider: 'opencomputer';\n createdAt: Date;\n metadata: {\n sandboxId?: string;\n orgId?: string;\n name?: string;\n status?: string;\n sizeBytes?: number;\n sandboxConfig?: Record<string, unknown>;\n };\n}\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined;\n}\n\nfunction baseOpts(config: OpenComputerConfig): Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl'> {\n return {\n apiKey: config.apiKey || env('OPENCOMPUTER_API_KEY'),\n apiUrl: config.apiUrl || env('OPENCOMPUTER_API_URL'),\n };\n}\n\nfunction toSeconds(milliseconds: number | undefined): number | undefined {\n return milliseconds == null ? undefined : Math.ceil(milliseconds / 1000);\n}\n\nfunction stringifyMetadata(metadata: Record<string, unknown> | undefined): Record<string, string> | undefined {\n if (!metadata) return undefined;\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (value == null || typeof value === 'function' || typeof value === 'symbol') {\n continue;\n }\n if (typeof value === 'string') {\n out[key] = value;\n continue;\n }\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n out[key] = String(value);\n continue;\n }\n try {\n const serialized = JSON.stringify(value);\n if (serialized !== undefined) {\n out[key] = serialized;\n }\n } catch {\n // Skip metadata values that cannot be represented as JSON strings.\n }\n }\n return out;\n}\n\nfunction redactWebhooks(webhooks: OpenComputerNativeSandbox['webhooks']): Array<{ id: string; url: string; hasSecret: boolean }> | undefined {\n return webhooks?.map((webhook) => ({\n id: webhook.id,\n url: webhook.url,\n hasSecret: typeof webhook.secret === 'string' && webhook.secret.length > 0,\n }));\n}\n\nfunction createOpts(config: OpenComputerConfig, options?: CreateSandboxOptions): OpenComputerSandboxOpts {\n return {\n ...baseOpts(config),\n template: options?.templateId || config.template,\n timeout: toSeconds(options?.timeout ?? config.timeout),\n envs: { ...config.envs, ...options?.envs },\n metadata: { ...config.metadata, ...stringifyMetadata(options?.metadata) },\n cpuCount: (options as any)?.cpuCount ?? config.cpuCount,\n memoryMB: (options as any)?.memoryMB ?? (options as any)?.memory ?? config.memoryMB,\n diskMB: (options as any)?.diskMB ?? config.diskMB,\n secretStore: (options as any)?.secretStore ?? config.secretStore,\n burst: (options as any)?.burst ?? config.burst,\n sandboxFamily: (options as any)?.sandboxFamily,\n previewAuth: (options as any)?.previewAuth ?? config.previewAuth,\n webhooks: (options as any)?.webhooks,\n };\n}\n\nfunction snapshotToCompute(snapshot: OpenComputerCheckpointInfo): OpenComputerSnapshot {\n const id = snapshot.sandboxId ? `${snapshot.sandboxId}:${snapshot.id}` : snapshot.id;\n return {\n id,\n provider: 'opencomputer',\n createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : new Date(),\n metadata: {\n sandboxId: snapshot.sandboxId,\n orgId: snapshot.orgId,\n name: snapshot.name,\n status: snapshot.status,\n sizeBytes: snapshot.sizeBytes,\n sandboxConfig: snapshot.sandboxConfig,\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function waitForCheckpointReady(\n sandbox: OpenComputerNativeSandbox,\n checkpoint: OpenComputerCheckpointInfo,\n timeoutMs = 300_000,\n): Promise<OpenComputerCheckpointInfo> {\n if (checkpoint.status === 'ready') return checkpoint;\n if (checkpoint.status === 'failed') {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);\n }\n\n const deadline = Date.now() + timeoutMs;\n let delay = 1_000;\n\n for (;;) {\n if (Date.now() >= deadline) {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} was not ready after ${timeoutMs}ms.`);\n }\n\n const checkpoints = await sandbox.listCheckpoints();\n const current = checkpoints.find((candidate) => candidate.id === checkpoint.id);\n if (!current) {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} disappeared while waiting for readiness.`);\n }\n if (current.status === 'ready') return current;\n if (current.status === 'failed') {\n throw new Error(`OpenComputer checkpoint ${checkpoint.id} failed.`);\n }\n\n await sleep(delay);\n delay = Math.min(delay * 1.5, 5_000);\n }\n}\n\nfunction isCheckpointIndexMiss(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const message = error.message.toLowerCase();\n return message.includes('404') && message.includes('checkpoint') && message.includes('not found');\n}\n\nasync function createFromCheckpointWithRetry(\n Sandbox: OpenComputerSandboxStatic,\n checkpointId: string,\n opts: Pick<OpenComputerSandboxOpts, 'apiKey' | 'apiUrl' | 'timeout' | 'envs' | 'secretStore'>,\n timeoutMs = 60_000,\n): Promise<OpenComputerNativeSandbox> {\n const deadline = Date.now() + timeoutMs;\n let delay = 1_000;\n\n for (;;) {\n try {\n return await Sandbox.createFromCheckpoint(checkpointId, opts);\n } catch (error) {\n if (!isCheckpointIndexMiss(error) || Date.now() >= deadline) {\n throw error;\n }\n await sleep(delay);\n delay = Math.min(delay * 1.5, 5_000);\n }\n }\n}\n\nasync function createSandbox(config: OpenComputerConfig, options?: CreateSandboxOptions) {\n const Sandbox = await loadSandbox();\n const opts = createOpts(config, options);\n\n if (options?.snapshotId) {\n const checkpointId = options.snapshotId.includes(':')\n ? options.snapshotId.slice(options.snapshotId.indexOf(':') + 1)\n : options.snapshotId;\n const sandbox = await createFromCheckpointWithRetry(Sandbox, checkpointId, {\n ...baseOpts(config),\n timeout: opts.timeout,\n envs: opts.envs,\n secretStore: opts.secretStore,\n });\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };\n }\n\n const sandbox = await Sandbox.create(opts);\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id };\n}\n\nconst _provider = defineProvider<OpenComputerNativeSandbox, OpenComputerConfig, any, OpenComputerSnapshot>({\n name: 'opencomputer',\n methods: {\n sandbox: {\n create: createSandbox,\n\n getById: async (config: OpenComputerConfig, sandboxId: string) => {\n const Sandbox = await loadSandbox();\n try {\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n return { sandbox, sandboxId: sandbox.sandboxId || sandbox.id || sandboxId };\n } catch (error) {\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('not found'))) {\n return null;\n }\n throw new Error(`Failed to get OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n list: async () => {\n throw new Error('OpenComputer provider does not support listing sandboxes via the TypeScript SDK.');\n },\n\n destroy: async (config: OpenComputerConfig, sandboxId: string) => {\n const Sandbox = await loadSandbox();\n try {\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n await sandbox.kill();\n } catch (error) {\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('not found'))) {\n return;\n }\n throw new Error(`Failed to destroy OpenComputer sandbox ${sandboxId}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (sandbox: OpenComputerNativeSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const runOptions = {\n cwd: options?.cwd,\n env: options?.env,\n timeout: toSeconds(options?.timeout),\n timeoutMs: options?.timeout,\n };\n if (options?.background && sandbox.exec?.background) {\n const session = await sandbox.exec.background(command, runOptions);\n return {\n stdout: session.sessionId,\n stderr: '',\n exitCode: 0,\n durationMs: Date.now() - startTime,\n };\n }\n\n const result = await (sandbox.exec ?? sandbox.commands).run(command, runOptions);\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode ?? 0,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n throw new Error(`OpenComputer command execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getInfo: async (sandbox: OpenComputerNativeSandbox): Promise<SandboxInfo> => {\n let status = sandbox.status;\n try {\n status = (await sandbox.isRunning()) ? 'running' : sandbox.status;\n } catch {\n status = sandbox.status;\n }\n\n return {\n id: sandbox.sandboxId || sandbox.id,\n provider: 'opencomputer',\n status: status === 'running' ? 'running' : status === 'error' ? 'error' : 'stopped',\n createdAt: new Date(),\n timeout: 0,\n metadata: {\n opencomputerSandboxId: sandbox.sandboxId || sandbox.id,\n previewAuthEnabled: Boolean(sandbox.previewAuthToken),\n webhooks: redactWebhooks(sandbox.webhooks),\n },\n };\n },\n\n getUrl: async (sandbox: OpenComputerNativeSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n const domain = sandbox.getPreviewDomain(options.port);\n if (domain) {\n return `${protocol}://${domain}`;\n }\n\n const preview = await sandbox.createPreviewURL({ port: options.port });\n const hostname = preview.customHostname || preview.hostname;\n if (!hostname) {\n throw new Error(`OpenComputer did not return a preview hostname for port ${options.port}.`);\n }\n return `${protocol}://${hostname}`;\n },\n\n filesystem: {\n readFile: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<string> =>\n sandbox.files.read(path),\n writeFile: async (sandbox: OpenComputerNativeSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n mkdir: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n readdir: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n return entries.map((entry) => ({\n name: entry.name,\n type: entry.isDir ? 'directory' as const : 'file' as const,\n size: entry.size,\n modified: new Date(),\n }));\n },\n exists: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<boolean> =>\n sandbox.files.exists(path),\n remove: async (sandbox: OpenComputerNativeSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n },\n },\n\n getInstance: (sandbox: OpenComputerNativeSandbox): OpenComputerNativeSandbox => sandbox,\n },\n\n snapshot: {\n create: async (config: OpenComputerConfig, sandboxId: string, options?: CreateSnapshotOptions) => {\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n const metadata = options?.metadata as\n | { kind?: 'full' | 'disk_only'; promoteToFull?: boolean; retentionPolicy?: unknown }\n | undefined;\n const kind = metadata?.kind ?? 'disk_only';\n const snapshot = await sandbox.createCheckpoint(options?.name || `snapshot-${Date.now()}`, {\n kind,\n promoteToFull: metadata?.promoteToFull ?? (kind === 'disk_only' ? true : undefined),\n retentionPolicy: metadata?.retentionPolicy,\n });\n return snapshotToCompute(await waitForCheckpointReady(sandbox, snapshot));\n },\n list: async (config: OpenComputerConfig, options?: ListSnapshotsOptions) => {\n if (!options?.sandboxId) {\n throw new Error('OpenComputer snapshots are scoped to a sandbox. Pass `sandboxId` to list snapshots.');\n }\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(options.sandboxId, baseOpts(config));\n const snapshots = await sandbox.listCheckpoints();\n return snapshots.map(snapshotToCompute);\n },\n delete: async (config: OpenComputerConfig, snapshotId: string) => {\n const sandboxId = snapshotId.split(':', 1)[0];\n if (!sandboxId || sandboxId === snapshotId) {\n throw new Error('OpenComputer snapshot deletion requires a sandbox-scoped id in the form `sandboxId:checkpointId`.');\n }\n const checkpointId = snapshotId.slice(sandboxId.length + 1);\n const Sandbox = await loadSandbox();\n const sandbox = await Sandbox.connect(sandboxId, baseOpts(config));\n await sandbox.deleteCheckpoint(checkpointId);\n },\n },\n },\n});\n\nexport const opencomputer = (config: OpenComputerConfig = {}) => _provider(config);\nexport type { OpenComputerNativeSandbox };\n"],"mappings":"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","names":["sandbox"]}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@computesdk/opencomputer",
3
+ "version": "1.0.1",
4
+ "description": "OpenComputer provider for ComputeSDK - persistent cloud VMs with checkpoints, preview URLs, command execution, and filesystem access",
5
+ "author": "ComputeSDK",
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
+ "keywords": [
21
+ "computesdk",
22
+ "opencomputer",
23
+ "sandbox",
24
+ "checkpoint",
25
+ "code-execution",
26
+ "cloud",
27
+ "compute",
28
+ "provider"
29
+ ],
30
+ "dependencies": {
31
+ "@opencomputer/sdk": "^0.12.4",
32
+ "@computesdk/provider": "2.1.4",
33
+ "computesdk": "4.1.4"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.0.0",
37
+ "@vitest/coverage-v8": "^1.0.0",
38
+ "eslint": "^8.37.0",
39
+ "rimraf": "^5.0.0",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5.0.0",
42
+ "vitest": "^1.0.0",
43
+ "@computesdk/test-utils": "2.0.0"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/computesdk/computesdk.git",
48
+ "directory": "packages/opencomputer"
49
+ },
50
+ "homepage": "https://www.computesdk.com",
51
+ "bugs": {
52
+ "url": "https://github.com/computesdk/computesdk/issues"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup",
56
+ "clean": "rimraf dist",
57
+ "dev": "tsup --watch",
58
+ "test": "vitest run",
59
+ "test:watch": "vitest watch",
60
+ "test:coverage": "vitest run --coverage",
61
+ "typecheck": "tsc --noEmit",
62
+ "lint": "eslint"
63
+ }
64
+ }