@ebowwa/sandbox 0.1.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.
Files changed (108) hide show
  1. package/dist/compilers/index.d.ts +24 -0
  2. package/dist/compilers/index.d.ts.map +1 -0
  3. package/dist/compilers/index.js +42 -0
  4. package/dist/compilers/index.js.map +1 -0
  5. package/dist/compilers/javascript.d.ts +117 -0
  6. package/dist/compilers/javascript.d.ts.map +1 -0
  7. package/dist/compilers/javascript.js +462 -0
  8. package/dist/compilers/javascript.js.map +1 -0
  9. package/dist/compilers/python.d.ts +140 -0
  10. package/dist/compilers/python.d.ts.map +1 -0
  11. package/dist/compilers/python.js +650 -0
  12. package/dist/compilers/python.js.map +1 -0
  13. package/dist/compilers/typescript.d.ts +99 -0
  14. package/dist/compilers/typescript.d.ts.map +1 -0
  15. package/dist/compilers/typescript.js +323 -0
  16. package/dist/compilers/typescript.js.map +1 -0
  17. package/dist/core/cell.d.ts +160 -0
  18. package/dist/core/cell.d.ts.map +1 -0
  19. package/dist/core/cell.js +319 -0
  20. package/dist/core/cell.js.map +1 -0
  21. package/dist/core/compiler.d.ts +126 -0
  22. package/dist/core/compiler.d.ts.map +1 -0
  23. package/dist/core/compiler.js +123 -0
  24. package/dist/core/compiler.js.map +1 -0
  25. package/dist/core/index.d.ts +19 -0
  26. package/dist/core/index.d.ts.map +1 -0
  27. package/dist/core/index.js +14 -0
  28. package/dist/core/index.js.map +1 -0
  29. package/dist/core/limits.d.ts +173 -0
  30. package/dist/core/limits.d.ts.map +1 -0
  31. package/dist/core/limits.js +440 -0
  32. package/dist/core/limits.js.map +1 -0
  33. package/dist/core/permissions.d.ts +103 -0
  34. package/dist/core/permissions.d.ts.map +1 -0
  35. package/dist/core/permissions.js +341 -0
  36. package/dist/core/permissions.js.map +1 -0
  37. package/dist/core/runtime.d.ts +127 -0
  38. package/dist/core/runtime.d.ts.map +1 -0
  39. package/dist/core/runtime.js +325 -0
  40. package/dist/core/runtime.js.map +1 -0
  41. package/dist/core/types.d.ts +380 -0
  42. package/dist/core/types.d.ts.map +1 -0
  43. package/dist/core/types.js +67 -0
  44. package/dist/core/types.js.map +1 -0
  45. package/dist/index.d.ts +145 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +279 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/multi/index.d.ts +9 -0
  50. package/dist/multi/index.d.ts.map +1 -0
  51. package/dist/multi/index.js +7 -0
  52. package/dist/multi/index.js.map +1 -0
  53. package/dist/multi/polyglot.d.ts +179 -0
  54. package/dist/multi/polyglot.d.ts.map +1 -0
  55. package/dist/multi/polyglot.js +319 -0
  56. package/dist/multi/polyglot.js.map +1 -0
  57. package/dist/runtimes/docker.d.ts +97 -0
  58. package/dist/runtimes/docker.d.ts.map +1 -0
  59. package/dist/runtimes/docker.js +368 -0
  60. package/dist/runtimes/docker.js.map +1 -0
  61. package/dist/runtimes/index.d.ts +11 -0
  62. package/dist/runtimes/index.d.ts.map +1 -0
  63. package/dist/runtimes/index.js +9 -0
  64. package/dist/runtimes/index.js.map +1 -0
  65. package/dist/runtimes/process.d.ts +47 -0
  66. package/dist/runtimes/process.d.ts.map +1 -0
  67. package/dist/runtimes/process.js +230 -0
  68. package/dist/runtimes/process.js.map +1 -0
  69. package/dist/session/index.d.ts +12 -0
  70. package/dist/session/index.d.ts.map +1 -0
  71. package/dist/session/index.js +9 -0
  72. package/dist/session/index.js.map +1 -0
  73. package/dist/session/kernel.d.ts +199 -0
  74. package/dist/session/kernel.d.ts.map +1 -0
  75. package/dist/session/kernel.js +400 -0
  76. package/dist/session/kernel.js.map +1 -0
  77. package/dist/session/notebook.d.ts +168 -0
  78. package/dist/session/notebook.d.ts.map +1 -0
  79. package/dist/session/notebook.js +499 -0
  80. package/dist/session/notebook.js.map +1 -0
  81. package/dist/session/repl.d.ts +159 -0
  82. package/dist/session/repl.d.ts.map +1 -0
  83. package/dist/session/repl.js +409 -0
  84. package/dist/session/repl.js.map +1 -0
  85. package/package.json +142 -0
  86. package/src/compilers/index.ts +80 -0
  87. package/src/compilers/javascript.ts +571 -0
  88. package/src/compilers/python.ts +785 -0
  89. package/src/compilers/typescript.ts +442 -0
  90. package/src/core/cell.ts +439 -0
  91. package/src/core/compiler.ts +250 -0
  92. package/src/core/index.ts +123 -0
  93. package/src/core/limits.ts +508 -0
  94. package/src/core/permissions.ts +409 -0
  95. package/src/core/runtime.ts +499 -0
  96. package/src/core/types.ts +528 -0
  97. package/src/global.d.ts +59 -0
  98. package/src/index.ts +515 -0
  99. package/src/multi/index.ts +22 -0
  100. package/src/multi/polyglot.ts +461 -0
  101. package/src/runtimes/docker.ts +501 -0
  102. package/src/runtimes/index.ts +21 -0
  103. package/src/runtimes/process.ts +316 -0
  104. package/src/session/index.ts +41 -0
  105. package/src/session/kernel.ts +553 -0
  106. package/src/session/notebook.ts +635 -0
  107. package/src/session/repl.ts +521 -0
  108. package/src/wasm2wasm.d.ts +35 -0
package/src/index.ts ADDED
@@ -0,0 +1,515 @@
1
+ /**
2
+ * @ebowwa/sandbox
3
+ *
4
+ * Composable sandbox primitives for multi-language code execution.
5
+ * Jupyter/REPL-style with Python+Rust+JS+TS+WASM support.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Sandbox, createNotebook, createREPL } from "@ebowwa/sandbox";
10
+ *
11
+ * // Quick execution
12
+ * const sandbox = new Sandbox();
13
+ * const result = await sandbox.execute("console.log('Hello')", "javascript");
14
+ *
15
+ * // Notebook
16
+ * const notebook = createNotebook({ name: "My Notebook" });
17
+ * notebook.addCell({ language: "javascript", source: "const x = 42" });
18
+ * notebook.runAll();
19
+ *
20
+ * // REPL
21
+ * const repl = createREPL({ language: "python" });
22
+ * repl.start();
23
+ * ```
24
+ */
25
+
26
+ // Core types - re-export for convenience
27
+ export type {
28
+ Language,
29
+ LanguageCapabilities,
30
+ PermissionLevel,
31
+ Permissions,
32
+ Limits,
33
+ Cell,
34
+ ExecutionResult,
35
+ ExecutionOptions,
36
+ ExecutionContext,
37
+ ExecutionError,
38
+ ExecutionMetrics,
39
+ DisplayOutput,
40
+ NotebookMetadata,
41
+ NotebookRunOptions,
42
+ NotebookResult,
43
+ PolyglotCell,
44
+ LanguageBridge,
45
+ Sandbox as SandboxInterface,
46
+ SandboxOptions,
47
+ SessionOptions,
48
+ NotebookOptions,
49
+ Session,
50
+ Notebook,
51
+ Kernel,
52
+ Compiler,
53
+ Runtime,
54
+ } from "./core/types.js";
55
+
56
+ // Type utilities
57
+ export {
58
+ permissionsFromLevel,
59
+ parseMemory,
60
+ parseTime,
61
+ } from "./core/types.js";
62
+
63
+ // Compiler exports
64
+ export type {
65
+ CompileResult,
66
+ ImportDefinition,
67
+ CompilerOptions,
68
+ ICompiler,
69
+ } from "./core/compiler.js";
70
+
71
+ export {
72
+ BaseCompiler,
73
+ WasmCompiler,
74
+ CompilerRegistry,
75
+ defaultCompilerRegistry,
76
+ } from "./core/compiler.js";
77
+
78
+ // Runtime exports
79
+ export type {
80
+ RuntimeOptions,
81
+ ExecutionRequest,
82
+ IRuntime,
83
+ RuntimeCapabilities,
84
+ } from "./core/runtime.js";
85
+
86
+ export {
87
+ Wasm2WasmRuntime,
88
+ NativeWasmRuntime,
89
+ RuntimeRegistry,
90
+ defaultRuntimeRegistry,
91
+ } from "./core/runtime.js";
92
+
93
+ // Elevated permission runtimes
94
+ export type {
95
+ ProcessRuntimeConfig,
96
+ DockerRuntimeConfig,
97
+ ContainerOptions,
98
+ } from "./runtimes/index.js";
99
+
100
+ export {
101
+ ProcessRuntime,
102
+ DockerRuntime,
103
+ } from "./runtimes/index.js";
104
+
105
+ // Permission exports
106
+ export {
107
+ PermissionChecker,
108
+ PermissionBuilder,
109
+ createPermissions,
110
+ mergePermissions,
111
+ impliesPermission,
112
+ upgradePermissions,
113
+ } from "./core/permissions.js";
114
+
115
+ // Limits exports
116
+ export type { ParsedLimits } from "./core/limits.js";
117
+
118
+ export {
119
+ DEFAULT_LIMITS,
120
+ LimitsParser,
121
+ LimitsEnforcer,
122
+ LimitsBuilder,
123
+ mergeLimits,
124
+ } from "./core/limits.js";
125
+
126
+ // Cell exports
127
+ export type {
128
+ CellMetadata,
129
+ CellState,
130
+ ExecutableCell,
131
+ } from "./core/cell.js";
132
+
133
+ export {
134
+ CellBuilder,
135
+ CellExecutor,
136
+ CellRegistry,
137
+ createCell,
138
+ createCellsFromMarkdown,
139
+ cellsToMarkdown,
140
+ } from "./core/cell.js";
141
+
142
+ // Session exports
143
+ export type {
144
+ KernelState,
145
+ KernelOptions,
146
+ KernelStats,
147
+ NotebookState,
148
+ NotebookEvents,
149
+ REPLOptions,
150
+ REPLHistoryEntry,
151
+ REPLState,
152
+ } from "./session/index.js";
153
+
154
+ export {
155
+ BaseKernel,
156
+ KernelManager,
157
+ BaseNotebook,
158
+ createNotebook,
159
+ BaseREPL,
160
+ createREPL,
161
+ } from "./session/index.js";
162
+
163
+ // Multi-language exports
164
+ export type {
165
+ PolyglotOptions,
166
+ VariableBinding,
167
+ PolyglotContext,
168
+ } from "./multi/index.js";
169
+
170
+ export {
171
+ PolyglotSession,
172
+ PolyglotNotebook,
173
+ createPolyglotSession,
174
+ createPolyglotNotebook,
175
+ } from "./multi/index.js";
176
+
177
+ // Import for implementation
178
+ import type {
179
+ Language,
180
+ Permissions,
181
+ Limits,
182
+ PermissionLevel,
183
+ ExecutionResult,
184
+ ExecutionOptions,
185
+ SandboxOptions,
186
+ SessionOptions,
187
+ NotebookOptions as NotebookOpts,
188
+ } from "./core/types.js";
189
+ import type { KernelOptions } from "./session/kernel.js";
190
+ import { BaseKernel, KernelManager } from "./session/kernel.js";
191
+ import { BaseNotebook, createNotebook } from "./session/notebook.js";
192
+ import { BaseREPL, createREPL } from "./session/repl.js";
193
+ import { PolyglotSession } from "./multi/polyglot.js";
194
+ import { defaultCompilerRegistry } from "./core/compiler.js";
195
+ import { defaultRuntimeRegistry } from "./core/runtime.js";
196
+ import { createPermissions, permissionsFromLevel } from "./core/permissions.js";
197
+ import { DEFAULT_LIMITS } from "./core/limits.js";
198
+ import { ProcessRuntime } from "./runtimes/process.js";
199
+ import { DockerRuntime } from "./runtimes/docker.js";
200
+
201
+ // Register elevated permission runtimes
202
+ defaultRuntimeRegistry.register(new ProcessRuntime());
203
+ defaultRuntimeRegistry.register(new DockerRuntime());
204
+
205
+ /**
206
+ * Normalize permissions to Permissions object
207
+ */
208
+ function normalizePermissions(
209
+ perms: PermissionLevel | Permissions | undefined
210
+ ): Permissions {
211
+ if (!perms) {
212
+ return createPermissions("isolated");
213
+ }
214
+ if (typeof perms === "string") {
215
+ return permissionsFromLevel(perms as PermissionLevel);
216
+ }
217
+ return perms;
218
+ }
219
+
220
+ /**
221
+ * Sandbox Implementation
222
+ *
223
+ * Main entry point for sandboxed execution.
224
+ */
225
+ export class Sandbox {
226
+ private kernelManager = new KernelManager();
227
+
228
+ constructor(private defaultOptions?: SandboxOptions) {}
229
+
230
+ /**
231
+ * Quick execute (isolated, no state)
232
+ */
233
+ async execute(
234
+ code: string,
235
+ language: Language = "javascript",
236
+ options?: SandboxOptions
237
+ ): Promise<ExecutionResult> {
238
+ const merged = this.mergeOptions(options);
239
+ const perms = normalizePermissions(merged.permissions);
240
+
241
+ // Get compiler and runtime
242
+ const compiler = defaultCompilerRegistry.get(language);
243
+ if (!compiler) {
244
+ throw new Error(`No compiler for language: ${language}`);
245
+ }
246
+
247
+ const runtime = defaultRuntimeRegistry.selectBest({
248
+ filesystem: perms.fs?.write,
249
+ network: perms.network?.outbound,
250
+ });
251
+ if (!runtime) {
252
+ throw new Error("No available runtime");
253
+ }
254
+
255
+ // Compile
256
+ const compiled = await compiler.compile(
257
+ code,
258
+ perms,
259
+ merged.limits ?? {}
260
+ );
261
+
262
+ // Execute
263
+ return runtime.execute(
264
+ { wasm: compiled },
265
+ {
266
+ permissions: perms,
267
+ limits: merged.limits ?? {},
268
+ env: merged.environment,
269
+ cwd: merged.workingDirectory,
270
+ }
271
+ );
272
+ }
273
+
274
+ /**
275
+ * Quick execute with preset
276
+ */
277
+ async quick(
278
+ code: string,
279
+ preset: "isolated" | "trusted" | "admin" = "isolated"
280
+ ): Promise<ExecutionResult> {
281
+ const levelMap: Record<string, PermissionLevel> = {
282
+ isolated: "isolated",
283
+ trusted: "filesystem",
284
+ admin: "admin",
285
+ };
286
+
287
+ const permissions = permissionsFromLevel(levelMap[preset] as PermissionLevel);
288
+ const limits = DEFAULT_LIMITS[preset];
289
+
290
+ return this.execute(code, "javascript", {
291
+ permissions,
292
+ limits: {
293
+ memory: limits.memoryBytes,
294
+ timeout: limits.timeoutMs,
295
+ cpuTime: limits.cpuTimeMs,
296
+ maxInstructions: limits.maxInstructions,
297
+ maxOutputSize: limits.maxOutputBytes,
298
+ maxStackDepth: limits.maxStackDepth,
299
+ },
300
+ });
301
+ }
302
+
303
+ /**
304
+ * Create a session for interactive use
305
+ */
306
+ createSession(options?: SessionOptions): SandboxSession {
307
+ const merged = this.mergeOptions(options);
308
+ return new SandboxSession(
309
+ this.kernelManager,
310
+ {
311
+ permissions: normalizePermissions(merged.permissions),
312
+ limits: merged.limits ?? {},
313
+ environment: merged.environment,
314
+ workingDirectory: merged.workingDirectory,
315
+ sharedMemory: options?.sharedMemory ?? false,
316
+ }
317
+ );
318
+ }
319
+
320
+ /**
321
+ * Create a notebook
322
+ */
323
+ createNotebook(options?: NotebookOpts): BaseNotebook {
324
+ const merged = this.mergeOptions(options);
325
+ return createNotebook({
326
+ name: options?.name,
327
+ defaultLanguage: options?.defaultLanguage,
328
+ permissions: normalizePermissions(merged.permissions),
329
+ limits: merged.limits,
330
+ kernelManager: this.kernelManager,
331
+ });
332
+ }
333
+
334
+ /**
335
+ * Create a REPL
336
+ */
337
+ createREPL(options?: SessionOptions & { language?: Language }): BaseREPL {
338
+ const merged = this.mergeOptions(options);
339
+ return createREPL({
340
+ language: options?.language,
341
+ permissions: normalizePermissions(merged.permissions),
342
+ limits: merged.limits,
343
+ kernelManager: this.kernelManager,
344
+ });
345
+ }
346
+
347
+ /**
348
+ * Create polyglot session
349
+ */
350
+ createPolyglot(options?: { permissions?: Permissions; limits?: Limits }): PolyglotSession {
351
+ const merged = this.mergeOptions(options);
352
+ return new PolyglotSession({
353
+ permissions: normalizePermissions(merged.permissions),
354
+ limits: merged.limits,
355
+ kernelManager: this.kernelManager,
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Merge options with defaults
361
+ */
362
+ private mergeOptions(options?: SandboxOptions): {
363
+ permissions: Permissions;
364
+ limits: Limits | undefined;
365
+ language: Language | undefined;
366
+ environment: Record<string, string>;
367
+ workingDirectory: string;
368
+ } {
369
+ const rawPerms = options?.permissions ?? this.defaultOptions?.permissions ?? "isolated";
370
+ return {
371
+ permissions: normalizePermissions(rawPerms),
372
+ limits: options?.limits ?? this.defaultOptions?.limits,
373
+ language: options?.language ?? this.defaultOptions?.language,
374
+ environment: options?.environment ?? this.defaultOptions?.environment ?? {},
375
+ workingDirectory: options?.workingDirectory ?? this.defaultOptions?.workingDirectory ?? process.cwd(),
376
+ };
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Sandbox Session
382
+ *
383
+ * Stateful execution context.
384
+ */
385
+ export class SandboxSession {
386
+ readonly id: string;
387
+ private kernelManager: KernelManager;
388
+ private kernels = new Map<Language, BaseKernel>();
389
+ private sharedState = new Map<string, unknown>();
390
+ private options: {
391
+ permissions: Permissions;
392
+ limits: Limits;
393
+ environment: Record<string, string>;
394
+ workingDirectory: string;
395
+ sharedMemory: boolean;
396
+ };
397
+
398
+ constructor(
399
+ kernelManager: KernelManager,
400
+ options: {
401
+ permissions: Permissions;
402
+ limits: Limits;
403
+ environment: Record<string, string>;
404
+ workingDirectory: string;
405
+ sharedMemory: boolean;
406
+ }
407
+ ) {
408
+ this.id = `session-${Date.now()}`;
409
+ this.kernelManager = kernelManager;
410
+ this.options = options;
411
+ }
412
+
413
+ /**
414
+ * Get kernel for language
415
+ */
416
+ getKernel(language: Language): BaseKernel | undefined {
417
+ return this.kernels.get(language);
418
+ }
419
+
420
+ /**
421
+ * Start kernel for language
422
+ */
423
+ async startKernel(language: Language): Promise<BaseKernel> {
424
+ let kernel = this.kernels.get(language);
425
+
426
+ if (!kernel) {
427
+ const compiler = defaultCompilerRegistry.get(language);
428
+ const runtime = defaultRuntimeRegistry.selectBest({});
429
+
430
+ if (!compiler || !runtime) {
431
+ throw new Error(`Cannot create kernel for ${language}`);
432
+ }
433
+
434
+ const kernelOptions: KernelOptions = {
435
+ language,
436
+ compiler,
437
+ runtime,
438
+ permissions: this.options.permissions,
439
+ limits: this.options.limits,
440
+ env: this.options.environment,
441
+ cwd: this.options.workingDirectory,
442
+ };
443
+
444
+ kernel = await this.kernelManager.createKernel(kernelOptions);
445
+ this.kernels.set(language, kernel);
446
+ }
447
+
448
+ return kernel;
449
+ }
450
+
451
+ /**
452
+ * Execute code
453
+ */
454
+ async execute(
455
+ code: string,
456
+ language: Language,
457
+ options?: ExecutionOptions
458
+ ): Promise<ExecutionResult> {
459
+ const kernel = await this.startKernel(language);
460
+ return kernel.execute(code, options);
461
+ }
462
+
463
+ /**
464
+ * Get shared state
465
+ */
466
+ getSharedState(): Map<string, unknown> {
467
+ return new Map(this.sharedState);
468
+ }
469
+
470
+ /**
471
+ * Set shared state
472
+ */
473
+ setSharedState(key: string, value: unknown): void {
474
+ this.sharedState.set(key, value);
475
+ }
476
+
477
+ /**
478
+ * Shutdown session
479
+ */
480
+ async shutdown(): Promise<void> {
481
+ for (const language of this.kernels.keys()) {
482
+ await this.kernelManager.shutdownKernel(
483
+ this.kernels.get(language)!.getId()
484
+ );
485
+ }
486
+ this.kernels.clear();
487
+ this.sharedState.clear();
488
+ }
489
+ }
490
+
491
+ /**
492
+ * Create default sandbox instance
493
+ */
494
+ export const sandbox = new Sandbox();
495
+
496
+ /**
497
+ * Quick execute helper
498
+ */
499
+ export async function execute(
500
+ code: string,
501
+ language: Language = "javascript",
502
+ options?: SandboxOptions
503
+ ): Promise<ExecutionResult> {
504
+ return sandbox.execute(code, language, options);
505
+ }
506
+
507
+ /**
508
+ * Quick execute with preset helper
509
+ */
510
+ export async function quick(
511
+ code: string,
512
+ preset: "isolated" | "trusted" | "admin" = "isolated"
513
+ ): Promise<ExecutionResult> {
514
+ return sandbox.quick(code, preset);
515
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Multi-Language Primitives
3
+ *
4
+ * Execute code across multiple languages with shared state.
5
+ */
6
+
7
+ // Polyglot - Multi-language execution
8
+ export type {
9
+ PolyglotOptions,
10
+ VariableBinding,
11
+ PolyglotContext,
12
+ } from "./polyglot.js";
13
+
14
+ export {
15
+ PolyglotSession,
16
+ PolyglotNotebook,
17
+ createPolyglotSession,
18
+ createPolyglotNotebook,
19
+ } from "./polyglot.js";
20
+
21
+ // Re-export bridge type
22
+ export type { LanguageBridge } from "../core/types.js";