computesdk 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,746 @@
1
+ # ComputeSDK
2
+
3
+ A unified abstraction layer for executing code in secure, isolated sandboxed environments across multiple cloud providers.
4
+
5
+ Similar to how Vercel's AI SDK abstracts different LLM providers, ComputeSDK abstracts different compute sandbox providers into a single, consistent TypeScript interface.
6
+
7
+ ## Features
8
+
9
+ - 🚀 **Multi-provider support** - E2B, Vercel, Daytona
10
+ - 📁 **Filesystem operations** - Read, write, create directories across providers
11
+ - 🖥️ **Terminal support** - Interactive PTY terminals (E2B)
12
+ - ⚡ **Command execution** - Run shell commands directly
13
+ - 🔄 **Auto-detection** - Automatically selects providers based on environment variables
14
+ - 🛡️ **Type-safe** - Full TypeScript support with comprehensive error handling
15
+ - 📦 **Modular** - Install only the providers you need
16
+ - 🔧 **Extensible** - Easy to add custom providers
17
+
18
+ ## Supported Providers
19
+
20
+ | Provider | Code Execution | Filesystem | Terminal | Use Cases |
21
+ |----------|----------------|------------|----------|-----------|
22
+ | **E2B** | Python | ✅ Full | ✅ PTY | Data science, AI/ML, interactive development |
23
+ | **Vercel** | Node.js, Python | ✅ Full | ❌ | Web apps, APIs, serverless functions |
24
+ | **Daytona** | Python, Node.js | ✅ Full | ❌ | Development workspaces, custom environments |
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ # Core SDK
30
+ npm install computesdk
31
+
32
+ # Provider packages (install only what you need)
33
+ npm install @computesdk/e2b # E2B provider
34
+ npm install @computesdk/vercel # Vercel provider
35
+ npm install @computesdk/daytona # Daytona provider
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ### Auto-detection (Recommended)
41
+
42
+ ComputeSDK automatically detects available providers based on environment variables:
43
+
44
+ ```typescript
45
+ import { ComputeSDK } from 'computesdk';
46
+
47
+ // Automatically detects and uses the first available provider
48
+ const sandbox = ComputeSDK.createSandbox();
49
+
50
+ const result = await sandbox.execute('print("Hello World!")');
51
+ console.log(result.stdout); // "Hello World!"
52
+
53
+ await sandbox.kill();
54
+ ```
55
+
56
+ ### Provider-specific Usage
57
+
58
+ ```typescript
59
+ import { executeSandbox } from 'computesdk';
60
+ import { e2b } from '@computesdk/e2b';
61
+
62
+ // Execute with specific provider
63
+ const result = await executeSandbox({
64
+ sandbox: e2b(),
65
+ code: 'print("Hello from E2B!")',
66
+ runtime: 'python'
67
+ });
68
+
69
+ console.log(result.stdout);
70
+ ```
71
+
72
+ ### Advanced Usage with Type Safety
73
+
74
+ ComputeSDK provides rich TypeScript interfaces for different provider capabilities:
75
+
76
+ ```typescript
77
+ import { ComputeSDK, FilesystemComputeSandbox, TerminalComputeSandbox } from 'computesdk';
78
+
79
+ const sandbox = ComputeSDK.createSandbox();
80
+
81
+ // Check provider capabilities at runtime
82
+ if ('filesystem' in sandbox) {
83
+ const fsSandbox = sandbox as FilesystemComputeSandbox;
84
+
85
+ // Use filesystem operations
86
+ await fsSandbox.filesystem.writeFile('/tmp/data.txt', 'Hello World!');
87
+ const content = await fsSandbox.filesystem.readFile('/tmp/data.txt');
88
+ console.log(content); // "Hello World!"
89
+ }
90
+
91
+ if ('terminal' in sandbox) {
92
+ const termSandbox = sandbox as TerminalComputeSandbox;
93
+
94
+ // Create interactive terminal (E2B only)
95
+ const terminal = await termSandbox.terminal.create({
96
+ command: 'bash',
97
+ cols: 80,
98
+ rows: 24
99
+ });
100
+
101
+ await terminal.write('echo "Interactive terminal!"\n');
102
+ await terminal.kill();
103
+ }
104
+ ```
105
+
106
+ ## Environment Setup
107
+
108
+ Each provider requires specific environment variables for authentication:
109
+
110
+ ### E2B (Full Features)
111
+ ```bash
112
+ export E2B_API_KEY=e2b_your_api_key_here
113
+ ```
114
+ Get your API key from [e2b.dev](https://e2b.dev/)
115
+
116
+ ### Vercel (Filesystem + Code Execution)
117
+ ```bash
118
+ export VERCEL_TOKEN=your_vercel_token_here
119
+ export VERCEL_TEAM_ID=your_team_id_here
120
+ export VERCEL_PROJECT_ID=your_project_id_here
121
+ ```
122
+ Get your token from [Vercel Account Tokens](https://vercel.com/account/tokens)
123
+
124
+ ### Daytona (Development Workspaces)
125
+ ```bash
126
+ export DAYTONA_API_KEY=your_daytona_api_key_here
127
+ ```
128
+
129
+
130
+
131
+ ## API Reference
132
+
133
+ ### Core SDK
134
+
135
+ #### `ComputeSDK.createSandbox(config?)`
136
+
137
+ Creates a sandbox using auto-detection or specified configuration.
138
+
139
+ ```typescript
140
+ // Auto-detection
141
+ const sandbox = ComputeSDK.createSandbox();
142
+
143
+ // With configuration
144
+ const sandbox = ComputeSDK.createSandbox({
145
+ provider: 'e2b',
146
+ runtime: 'python',
147
+ timeout: 600000 // 10 minutes
148
+ });
149
+ ```
150
+
151
+ **Parameters:**
152
+ - `config` (optional): Sandbox configuration object
153
+
154
+ **Returns:** `ComputeSandbox` - The appropriate sandbox type based on provider capabilities
155
+
156
+ #### `ComputeSDK.detectProviders()`
157
+
158
+ Detects available providers based on environment variables.
159
+
160
+ ```typescript
161
+ const providers = ComputeSDK.detectProviders();
162
+ console.log('Available providers:', providers); // ['e2b', 'vercel']
163
+ ```
164
+
165
+ **Returns:** `ProviderType[]` - Array of available provider names
166
+
167
+ ### Utility Functions
168
+
169
+ #### `executeSandbox(params)`
170
+
171
+ Utility function for one-off code execution.
172
+
173
+ ```typescript
174
+ import { executeSandbox } from 'computesdk';
175
+ import { vercel } from '@computesdk/vercel';
176
+
177
+ const result = await executeSandbox({
178
+ sandbox: vercel({ runtime: 'node' }),
179
+ code: 'console.log("Hello from Node.js!");',
180
+ runtime: 'node'
181
+ });
182
+ ```
183
+
184
+ **Parameters:**
185
+ ```typescript
186
+ interface ExecuteSandboxParams {
187
+ sandbox: ComputeSandbox;
188
+ code: string;
189
+ runtime?: Runtime;
190
+ }
191
+ ```
192
+
193
+ ### Sandbox Interfaces
194
+
195
+ ComputeSDK provides a rich type system for different provider capabilities:
196
+
197
+ #### `BaseComputeSandbox`
198
+
199
+ Basic code execution capabilities (all providers support this):
200
+
201
+ ```typescript
202
+ interface BaseComputeSandbox {
203
+ provider: string;
204
+ sandboxId: string;
205
+
206
+ execute(code: string, runtime?: Runtime): Promise<ExecutionResult>;
207
+ runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;
208
+ runCommand(command: string, args?: string[]): Promise<ExecutionResult>;
209
+ kill(): Promise<void>;
210
+ getInfo(): Promise<SandboxInfo>;
211
+ }
212
+ ```
213
+
214
+ #### `FilesystemComputeSandbox`
215
+
216
+ Extends base capabilities with filesystem operations (E2B, Vercel, Daytona):
217
+
218
+ ```typescript
219
+ interface FilesystemComputeSandbox extends BaseComputeSandbox {
220
+ readonly filesystem: SandboxFileSystem;
221
+ }
222
+
223
+ interface SandboxFileSystem {
224
+ readFile(path: string): Promise<string>;
225
+ writeFile(path: string, content: string): Promise<void>;
226
+ mkdir(path: string): Promise<void>;
227
+ readdir(path: string): Promise<FileEntry[]>;
228
+ exists(path: string): Promise<boolean>;
229
+ remove(path: string): Promise<void>;
230
+ }
231
+ ```
232
+
233
+ #### `TerminalComputeSandbox`
234
+
235
+ Extends base capabilities with terminal operations (E2B only):
236
+
237
+ ```typescript
238
+ interface TerminalComputeSandbox extends BaseComputeSandbox {
239
+ readonly terminal: SandboxTerminal;
240
+ }
241
+
242
+ interface SandboxTerminal {
243
+ create(options?: TerminalCreateOptions): Promise<InteractiveTerminalSession>;
244
+ list(): Promise<InteractiveTerminalSession[]>;
245
+ }
246
+ ```
247
+
248
+ #### `FullComputeSandbox`
249
+
250
+ Full capabilities including filesystem and terminal (E2B only):
251
+
252
+ ```typescript
253
+ interface FullComputeSandbox extends FilesystemComputeSandbox, TerminalComputeSandbox {}
254
+ ```
255
+
256
+ ### Data Types
257
+
258
+ #### `ExecutionResult`
259
+
260
+ Result object returned by all execution methods:
261
+
262
+ ```typescript
263
+ interface ExecutionResult {
264
+ stdout: string;
265
+ stderr: string;
266
+ exitCode: number;
267
+ executionTime: number;
268
+ sandboxId: string;
269
+ provider: string;
270
+ }
271
+ ```
272
+
273
+ #### `SandboxInfo`
274
+
275
+ Information about a sandbox instance:
276
+
277
+ ```typescript
278
+ interface SandboxInfo {
279
+ id: string;
280
+ provider: string;
281
+ runtime: Runtime;
282
+ status: 'running' | 'stopped' | 'error';
283
+ createdAt: Date;
284
+ timeout: number;
285
+ metadata?: Record<string, any>;
286
+ }
287
+ ```
288
+
289
+ #### `FileEntry`
290
+
291
+ File system entry information:
292
+
293
+ ```typescript
294
+ interface FileEntry {
295
+ name: string;
296
+ path: string;
297
+ isDirectory: boolean;
298
+ size: number;
299
+ lastModified: Date;
300
+ }
301
+ ```
302
+
303
+ ## Examples
304
+
305
+ ### Cross-Provider Data Processing
306
+
307
+ ```typescript
308
+ import { ComputeSDK, FilesystemComputeSandbox } from 'computesdk';
309
+
310
+ async function processData() {
311
+ // Auto-detect best available provider
312
+ const sandbox = ComputeSDK.createSandbox();
313
+
314
+ if ('filesystem' in sandbox) {
315
+ const fsSandbox = sandbox as FilesystemComputeSandbox;
316
+
317
+ // Create project structure
318
+ await fsSandbox.filesystem.mkdir('/project/data');
319
+ await fsSandbox.filesystem.mkdir('/project/output');
320
+
321
+ // Write input data
322
+ const data = JSON.stringify([
323
+ { name: 'Alice', sales: 1000 },
324
+ { name: 'Bob', sales: 1500 },
325
+ { name: 'Charlie', sales: 800 }
326
+ ]);
327
+
328
+ await fsSandbox.filesystem.writeFile('/project/data/sales.json', data);
329
+
330
+ // Process data based on provider
331
+ let code: string;
332
+ if (sandbox.provider === 'e2b') {
333
+ // Python processing for E2B
334
+ code = `
335
+ import json
336
+ import pandas as pd
337
+
338
+ # Read data
339
+ with open('/project/data/sales.json', 'r') as f:
340
+ data = json.load(f)
341
+
342
+ # Process with pandas
343
+ df = pd.DataFrame(data)
344
+ total_sales = df['sales'].sum()
345
+ avg_sales = df['sales'].mean()
346
+
347
+ # Write results
348
+ results = {
349
+ 'total_sales': total_sales,
350
+ 'average_sales': avg_sales,
351
+ 'top_performer': df.loc[df['sales'].idxmax(), 'name']
352
+ }
353
+
354
+ with open('/project/output/results.json', 'w') as f:
355
+ json.dump(results, f, indent=2)
356
+
357
+ print(f"Total Sales: ${total_sales}")
358
+ print(f"Average Sales: ${avg_sales:.2f}")
359
+ print(f"Top Performer: {results['top_performer']}")
360
+ `;
361
+ } else {
362
+ // JavaScript processing for Vercel/Daytona
363
+ code = `
364
+ const fs = require('fs');
365
+
366
+ // Read data
367
+ const data = JSON.parse(fs.readFileSync('/project/data/sales.json', 'utf8'));
368
+
369
+ // Process data
370
+ const totalSales = data.reduce((sum, person) => sum + person.sales, 0);
371
+ const avgSales = totalSales / data.length;
372
+ const topPerformer = data.reduce((top, person) =>
373
+ person.sales > top.sales ? person : top
374
+ );
375
+
376
+ // Write results
377
+ const results = {
378
+ total_sales: totalSales,
379
+ average_sales: avgSales,
380
+ top_performer: topPerformer.name
381
+ };
382
+
383
+ fs.writeFileSync('/project/output/results.json', JSON.stringify(results, null, 2));
384
+
385
+ console.log(\`Total Sales: $\${totalSales}\`);
386
+ console.log(\`Average Sales: $\${avgSales.toFixed(2)}\`);
387
+ console.log(\`Top Performer: \${results.top_performer}\`);
388
+ `;
389
+ }
390
+
391
+ // Execute processing
392
+ const result = await fsSandbox.execute(code);
393
+ console.log('Processing Output:', result.stdout);
394
+
395
+ // Read results
396
+ const results = await fsSandbox.filesystem.readFile('/project/output/results.json');
397
+ console.log('Results:', JSON.parse(results));
398
+
399
+ // List generated files
400
+ const outputFiles = await fsSandbox.filesystem.readdir('/project/output');
401
+ console.log('Generated files:', outputFiles.map(f => f.name));
402
+ }
403
+
404
+ await sandbox.kill();
405
+ }
406
+
407
+ processData().catch(console.error);
408
+ ```
409
+
410
+ ### Interactive Development with E2B
411
+
412
+ ```typescript
413
+ import { e2b } from '@computesdk/e2b';
414
+ import { TerminalComputeSandbox, FilesystemComputeSandbox } from 'computesdk';
415
+
416
+ async function interactiveDevelopment() {
417
+ const sandbox = e2b() as TerminalComputeSandbox & FilesystemComputeSandbox;
418
+
419
+ // Set up development environment
420
+ await sandbox.filesystem.mkdir('/workspace');
421
+ await sandbox.filesystem.writeFile('/workspace/requirements.txt',
422
+ 'pandas\nnumpy\nmatplotlib\nscikit-learn'
423
+ );
424
+
425
+ // Create interactive terminal
426
+ const terminal = await sandbox.terminal.create({
427
+ command: 'bash',
428
+ cols: 120,
429
+ rows: 30
430
+ });
431
+
432
+ // Set up output handler
433
+ terminal.onData = (data: Uint8Array) => {
434
+ const output = new TextDecoder().decode(data);
435
+ console.log('Terminal:', output);
436
+ };
437
+
438
+ // Install dependencies
439
+ await terminal.write('cd /workspace\n');
440
+ await terminal.write('pip install -r requirements.txt\n');
441
+
442
+ // Start interactive Python session
443
+ await terminal.write('python3\n');
444
+ await terminal.write('import pandas as pd\n');
445
+ await terminal.write('import numpy as np\n');
446
+ await terminal.write('print("Development environment ready!")\n');
447
+
448
+ // Simulate interactive development
449
+ await new Promise(resolve => setTimeout(resolve, 5000));
450
+
451
+ // Clean up
452
+ await terminal.kill();
453
+ await sandbox.kill();
454
+ }
455
+
456
+ interactiveDevelopment().catch(console.error);
457
+ ```
458
+
459
+ ### Multi-Provider Comparison
460
+
461
+ ```typescript
462
+ import { executeSandbox } from 'computesdk';
463
+ import { e2b } from '@computesdk/e2b';
464
+ import { vercel } from '@computesdk/vercel';
465
+ import { daytona } from '@computesdk/daytona';
466
+
467
+ async function compareProviders() {
468
+ const testCode = `
469
+ import json
470
+ import time
471
+ start = time.time()
472
+
473
+ # Simple computation
474
+ result = sum(range(1000))
475
+ elapsed = time.time() - start
476
+
477
+ output = {
478
+ "result": result,
479
+ "elapsed_ms": round(elapsed * 1000, 2),
480
+ "provider": "will_be_set"
481
+ }
482
+
483
+ print(json.dumps(output))
484
+ `;
485
+
486
+ const providers = [
487
+ { name: 'E2B', factory: () => e2b() },
488
+ { name: 'Vercel', factory: () => vercel({ runtime: 'python' }) },
489
+ { name: 'Daytona', factory: () => daytona({ runtime: 'python' }) },
490
+ ];
491
+
492
+ console.log('Performance Comparison:');
493
+ console.log('='.repeat(50));
494
+
495
+ for (const { name, factory } of providers) {
496
+ try {
497
+ const start = Date.now();
498
+ const result = await executeSandbox({
499
+ sandbox: factory(),
500
+ code: testCode,
501
+ runtime: 'python'
502
+ });
503
+ const totalTime = Date.now() - start;
504
+
505
+ const output = JSON.parse(result.stdout);
506
+ console.log(`${name}:`);
507
+ console.log(` Computation: ${output.result}`);
508
+ console.log(` Execution time: ${output.elapsed_ms}ms`);
509
+ console.log(` Total time: ${totalTime}ms`);
510
+ console.log(` Provider overhead: ${totalTime - output.elapsed_ms}ms`);
511
+ console.log();
512
+
513
+ } catch (error) {
514
+ console.log(`${name}: Failed - ${error.message}`);
515
+ console.log();
516
+ }
517
+ }
518
+ }
519
+
520
+ compareProviders().catch(console.error);
521
+ ```
522
+
523
+ ## Error Handling
524
+
525
+ ComputeSDK provides comprehensive error handling with specific error types:
526
+
527
+ ```typescript
528
+ import { ComputeSDK } from 'computesdk';
529
+
530
+ try {
531
+ const sandbox = ComputeSDK.createSandbox();
532
+ const result = await sandbox.execute('invalid python code');
533
+ } catch (error) {
534
+ if (error.message.includes('Missing') && error.message.includes('API key')) {
535
+ console.error('Authentication Error: Check your environment variables');
536
+ console.error('Required: E2B_API_KEY, VERCEL_TOKEN, etc.');
537
+ } else if (error.message.includes('timeout')) {
538
+ console.error('Timeout Error: Execution took too long');
539
+ } else if (error.message.includes('quota') || error.message.includes('limit')) {
540
+ console.error('Quota Error: API usage limits exceeded');
541
+ } else if (error.message.includes('not installed')) {
542
+ console.error('Configuration Error: Provider package not installed');
543
+ console.error('Run: npm install @computesdk/[provider-name]');
544
+ } else {
545
+ console.error('Execution Error:', error.message);
546
+ }
547
+ }
548
+ ```
549
+
550
+ ## Provider-Specific Features
551
+
552
+ ### E2B - Full Development Environment
553
+
554
+ E2B provides the richest feature set with full filesystem and terminal support:
555
+
556
+ ```typescript
557
+ import { e2b } from '@computesdk/e2b';
558
+
559
+ const sandbox = e2b();
560
+
561
+ // Full Python environment with data science libraries
562
+ const result = await sandbox.execute(`
563
+ import pandas as pd
564
+ import matplotlib.pyplot as plt
565
+ import numpy as np
566
+
567
+ # Create and visualize data
568
+ data = np.random.randn(1000)
569
+ plt.hist(data, bins=50)
570
+ plt.savefig('/tmp/histogram.png')
571
+ print("Histogram saved!")
572
+ `);
573
+
574
+ // Check if file was created
575
+ const exists = await sandbox.filesystem.exists('/tmp/histogram.png');
576
+ console.log('Histogram created:', exists);
577
+ ```
578
+
579
+ ### Vercel - Scalable Serverless Execution
580
+
581
+ Vercel provides reliable execution with filesystem support:
582
+
583
+ ```typescript
584
+ import { vercel } from '@computesdk/vercel';
585
+
586
+ const sandbox = vercel({ runtime: 'node' });
587
+
588
+ // Process data with Node.js
589
+ const result = await sandbox.execute(`
590
+ const fs = require('fs');
591
+ const path = require('path');
592
+
593
+ // Create API simulation
594
+ const apiData = {
595
+ users: 1000,
596
+ active: 750,
597
+ revenue: 50000
598
+ };
599
+
600
+ // Write to filesystem
601
+ fs.writeFileSync('/tmp/api-data.json', JSON.stringify(apiData, null, 2));
602
+
603
+ console.log('API data processed and saved');
604
+ console.log('Active users:', apiData.active);
605
+ `);
606
+
607
+ // Read the generated data
608
+ const data = await sandbox.filesystem.readFile('/tmp/api-data.json');
609
+ console.log('Generated data:', JSON.parse(data));
610
+ ```
611
+
612
+ ### Daytona - Development Workspaces
613
+
614
+ Daytona provides development workspace environments with full filesystem support:
615
+
616
+ ```typescript
617
+ import { daytona } from '@computesdk/daytona';
618
+
619
+ const sandbox = daytona({ runtime: 'python' });
620
+
621
+ // Execute Python code in workspace
622
+ const result = await sandbox.execute(`
623
+ import json
624
+ import os
625
+
626
+ # Create project structure
627
+ os.makedirs('/workspace/src', exist_ok=True)
628
+ os.makedirs('/workspace/tests', exist_ok=True)
629
+
630
+ # Write project files
631
+ with open('/workspace/src/main.py', 'w') as f:
632
+ f.write('def hello():\\n return "Hello from Daytona!"\\n')
633
+
634
+ with open('/workspace/tests/test_main.py', 'w') as f:
635
+ f.write('from src.main import hello\\n\\ndef test_hello():\\n assert hello() == "Hello from Daytona!"\\n')
636
+
637
+ print("Project structure created!")
638
+ print("Files:", os.listdir('/workspace'))
639
+ `);
640
+
641
+ // Check created files
642
+ const files = await sandbox.filesystem.readdir('/workspace');
643
+ console.log('Workspace files:', files.map(f => f.name));
644
+
645
+ // Read project file
646
+ const mainPy = await sandbox.filesystem.readFile('/workspace/src/main.py');
647
+ console.log('main.py content:', mainPy);
648
+ ```
649
+
650
+
651
+
652
+ ## Best Practices
653
+
654
+ ### 1. Provider Selection
655
+
656
+ Choose providers based on your use case:
657
+
658
+ - **E2B**: Data science, ML, interactive development, full Python environment
659
+ - **Vercel**: Web applications, APIs, serverless functions, long-running tasks
660
+ - **Daytona**: Development workspaces, custom environments, team collaboration
661
+
662
+ ### 2. Resource Management
663
+
664
+ Always clean up resources:
665
+
666
+ ```typescript
667
+ const sandbox = ComputeSDK.createSandbox();
668
+ try {
669
+ // Your code here
670
+ const result = await sandbox.execute('print("Hello")');
671
+ } finally {
672
+ // Always clean up
673
+ await sandbox.kill();
674
+ }
675
+ ```
676
+
677
+ ### 3. Error Handling
678
+
679
+ Implement comprehensive error handling:
680
+
681
+ ```typescript
682
+ async function robustExecution(code: string) {
683
+ let sandbox;
684
+ try {
685
+ sandbox = ComputeSDK.createSandbox();
686
+ return await sandbox.execute(code);
687
+ } catch (error) {
688
+ console.error('Execution failed:', error.message);
689
+ throw error;
690
+ } finally {
691
+ if (sandbox) {
692
+ await sandbox.kill();
693
+ }
694
+ }
695
+ }
696
+ ```
697
+
698
+ ### 4. Type Safety
699
+
700
+ Use TypeScript interfaces for better development experience:
701
+
702
+ ```typescript
703
+ import { FilesystemComputeSandbox, TerminalComputeSandbox } from 'computesdk';
704
+
705
+ function requiresFilesystem(sandbox: FilesystemComputeSandbox) {
706
+ // TypeScript ensures filesystem operations are available
707
+ return sandbox.filesystem.readFile('/path/to/file');
708
+ }
709
+
710
+ function requiresTerminal(sandbox: TerminalComputeSandbox) {
711
+ // TypeScript ensures terminal operations are available
712
+ return sandbox.terminal.create({ command: 'bash' });
713
+ }
714
+ ```
715
+
716
+ ## Contributing
717
+
718
+ We welcome contributions! Please see our [Contributing Guide](https://github.com/computesdk/computesdk/blob/main/CONTRIBUTING.md) for details.
719
+
720
+ ### Adding New Providers
721
+
722
+ 1. Implement the appropriate `ComputeSpecification` interface:
723
+ - `BaseComputeSpecification` for basic execution
724
+ - `FilesystemComputeSpecification` for filesystem support
725
+ - `TerminalComputeSpecification` for terminal support
726
+ - `FullComputeSpecification` for complete functionality
727
+
728
+ 2. Add comprehensive tests covering all implemented interfaces
729
+
730
+ 3. Include documentation and examples
731
+
732
+ 4. Submit a pull request
733
+
734
+ ## License
735
+
736
+ MIT - see [LICENSE](https://github.com/computesdk/computesdk/blob/main/LICENSE) for details.
737
+
738
+ ## Support
739
+
740
+ - [GitHub Issues](https://github.com/computesdk/computesdk/issues)
741
+ - [Documentation](https://github.com/computesdk/computesdk)
742
+ - [Examples](https://github.com/computesdk/computesdk/tree/main/examples)
743
+
744
+ ---
745
+
746
+ Made with ❤️ by the ComputeSDK team