@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
@@ -0,0 +1,461 @@
1
+ /**
2
+ * Polyglot Primitive
3
+ *
4
+ * Execute code across multiple languages with shared state.
5
+ * Enables true multi-language programming with seamless data exchange.
6
+ */
7
+
8
+ import type {
9
+ Language,
10
+ Cell,
11
+ ExecutionResult,
12
+ Permissions,
13
+ Limits,
14
+ PolyglotCell,
15
+ LanguageBridge,
16
+ } from "../core/types.js";
17
+ import { BaseKernel, KernelManager } from "../session/kernel.js";
18
+ import { CellRegistry } from "../core/cell.js";
19
+ import type { ExecutableCell } from "../core/cell.js";
20
+ import { v4 as uuid } from "uuid";
21
+
22
+ /**
23
+ * Polyglot session options
24
+ */
25
+ export interface PolyglotOptions {
26
+ /** Available languages */
27
+ languages?: Language[];
28
+ /** Permissions */
29
+ permissions?: Permissions;
30
+ /** Resource limits */
31
+ limits?: Limits;
32
+ /** Kernel manager */
33
+ kernelManager?: KernelManager;
34
+ /** Kernel factory */
35
+ kernelFactory?: (language: Language) => Promise<BaseKernel>;
36
+ }
37
+
38
+ /**
39
+ * Language variable binding
40
+ */
41
+ export interface VariableBinding {
42
+ /** Variable name */
43
+ name: string;
44
+ /** Source language */
45
+ fromLanguage: Language;
46
+ /** Target language */
47
+ toLanguage: Language;
48
+ /** Serialized value */
49
+ serializedValue: Uint8Array;
50
+ /** Type information */
51
+ type?: string;
52
+ }
53
+
54
+ /**
55
+ * Polyglot execution context
56
+ */
57
+ export interface PolyglotContext {
58
+ /** Current language */
59
+ language: Language;
60
+ /** Variables from other languages */
61
+ bindings: Map<string, VariableBinding>;
62
+ /** Shared state */
63
+ sharedState: Map<string, unknown>;
64
+ /** Kernel for current language */
65
+ kernel: BaseKernel;
66
+ }
67
+
68
+ /**
69
+ * Built-in language bridges
70
+ */
71
+ const BUILTIN_BRIDGES: Partial<Record<`${Language}:${Language}`, LanguageBridge>> = {
72
+ // JSON is universal
73
+ "javascript:python": createJsonBridge("javascript", "python"),
74
+ "python:javascript": createJsonBridge("python", "javascript"),
75
+ "javascript:typescript": createJsonBridge("javascript", "typescript"),
76
+ "typescript:javascript": createJsonBridge("typescript", "javascript"),
77
+ "python:typescript": createJsonBridge("python", "typescript"),
78
+ "typescript:python": createJsonBridge("typescript", "python"),
79
+ };
80
+
81
+ /**
82
+ * Create JSON-based language bridge
83
+ */
84
+ function createJsonBridge(from: Language, to: Language): LanguageBridge {
85
+ return {
86
+ from,
87
+ to,
88
+ serialize(value: unknown): Uint8Array {
89
+ return new TextEncoder().encode(JSON.stringify(value));
90
+ },
91
+ deserialize(bytes: Uint8Array): unknown {
92
+ return JSON.parse(new TextDecoder().decode(bytes));
93
+ },
94
+ canBridge(type: string): boolean {
95
+ // JSON can bridge most primitive and composite types
96
+ return ["number", "string", "boolean", "object", "array"].includes(type);
97
+ },
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Polyglot Session
103
+ *
104
+ * Manages multi-language execution with variable sharing.
105
+ */
106
+ export class PolyglotSession {
107
+ private kernelManager: KernelManager;
108
+ private kernelFactory?: (language: Language) => Promise<BaseKernel>;
109
+ private kernels = new Map<Language, BaseKernel>();
110
+ private bridges: Map<`${Language}:${Language}`, LanguageBridge>;
111
+ private sharedState = new Map<string, unknown>();
112
+ private variableBindings = new Map<string, VariableBinding>();
113
+ private permissions: Permissions;
114
+ private limits: Limits;
115
+
116
+ constructor(options: PolyglotOptions = {}) {
117
+ this.kernelManager = options.kernelManager ?? new KernelManager();
118
+ this.kernelFactory = options.kernelFactory;
119
+ this.permissions = options.permissions ?? {};
120
+ this.limits = options.limits ?? {};
121
+ this.bridges = new Map(Object.entries(BUILTIN_BRIDGES) as Array<[`${Language}:${Language}`, LanguageBridge]>);
122
+ }
123
+
124
+ /**
125
+ * Execute code in a language
126
+ */
127
+ async execute(
128
+ code: string,
129
+ language: Language,
130
+ options?: {
131
+ imports?: Map<string, string>; // name -> language
132
+ }
133
+ ): Promise<ExecutionResult> {
134
+ const kernel = await this.getKernel(language);
135
+
136
+ // Import variables from other languages
137
+ if (options?.imports) {
138
+ const importCode = await this.generateImportCode(language, options.imports);
139
+ code = importCode + "\n" + code;
140
+ }
141
+
142
+ const result = await kernel.execute(code);
143
+
144
+ // Capture exports to shared state
145
+ if (result.success && result.exports) {
146
+ for (const [name, value] of result.exports) {
147
+ this.sharedState.set(`${language}:${name}`, value);
148
+ }
149
+ }
150
+
151
+ return result;
152
+ }
153
+
154
+ /**
155
+ * Execute polyglot cell (multiple language variants)
156
+ */
157
+ async executePolyglot(
158
+ cell: PolyglotCell,
159
+ preferredLanguage?: Language
160
+ ): Promise<{ language: Language; result: ExecutionResult }> {
161
+ // Try preferred language first
162
+ const langOrder = preferredLanguage
163
+ ? [preferredLanguage, ...cell.variants.keys()].filter(
164
+ (v, i, a) => a.indexOf(v) === i
165
+ )
166
+ : Array.from(cell.variants.keys());
167
+
168
+ for (const language of langOrder) {
169
+ const code = cell.variants.get(language);
170
+ if (!code) continue;
171
+
172
+ try {
173
+ const kernel = await this.getKernel(language);
174
+ if (!kernel.isRunning()) {
175
+ await kernel.start();
176
+ }
177
+
178
+ const result = await kernel.execute(code);
179
+ return { language, result };
180
+ } catch (error) {
181
+ // Try next language
182
+ continue;
183
+ }
184
+ }
185
+
186
+ throw new Error("No available language for polyglot cell");
187
+ }
188
+
189
+ /**
190
+ * Get or create kernel for language
191
+ */
192
+ private async getKernel(language: Language): Promise<BaseKernel> {
193
+ let kernel = this.kernels.get(language);
194
+
195
+ if (!kernel) {
196
+ if (this.kernelFactory) {
197
+ kernel = await this.kernelFactory(language);
198
+ } else {
199
+ throw new Error(`No kernel available for language: ${language}`);
200
+ }
201
+
202
+ this.kernels.set(language, kernel);
203
+ }
204
+
205
+ return kernel;
206
+ }
207
+
208
+ /**
209
+ * Generate import code for a language
210
+ */
211
+ private async generateImportCode(
212
+ targetLanguage: Language,
213
+ imports: Map<string, string>
214
+ ): Promise<string> {
215
+ const lines: string[] = [];
216
+
217
+ for (const [name, sourceLanguage] of imports) {
218
+ const value = this.sharedState.get(`${sourceLanguage}:${name}`);
219
+ if (value === undefined) continue;
220
+
221
+ const bridge = this.getBridge(sourceLanguage as Language, targetLanguage);
222
+ if (!bridge) {
223
+ throw new Error(
224
+ `No bridge from ${sourceLanguage} to ${targetLanguage}`
225
+ );
226
+ }
227
+
228
+ const serialized = bridge.serialize(value);
229
+ const deserialized = bridge.deserialize(serialized);
230
+
231
+ // Generate language-specific import
232
+ const importLine = this.generateVariableAssignment(
233
+ targetLanguage,
234
+ name,
235
+ deserialized
236
+ );
237
+ lines.push(importLine);
238
+ }
239
+
240
+ return lines.join("\n");
241
+ }
242
+
243
+ /**
244
+ * Generate variable assignment in target language
245
+ */
246
+ private generateVariableAssignment(
247
+ language: Language,
248
+ name: string,
249
+ value: unknown
250
+ ): string {
251
+ const json = JSON.stringify(value);
252
+
253
+ switch (language) {
254
+ case "javascript":
255
+ case "typescript":
256
+ return `const ${name} = ${json};`;
257
+
258
+ case "python":
259
+ return `${name} = ${json}`;
260
+
261
+ case "assemblyscript":
262
+ return `const ${name} = ${json};`;
263
+
264
+ case "json":
265
+ return json;
266
+
267
+ default:
268
+ return `// ${name} = ${json}`;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Get bridge between languages
274
+ */
275
+ getBridge(from: Language, to: Language): LanguageBridge | undefined {
276
+ return this.bridges.get(`${from}:${to}`);
277
+ }
278
+
279
+ /**
280
+ * Register custom bridge
281
+ */
282
+ registerBridge(bridge: LanguageBridge): void {
283
+ this.bridges.set(`${bridge.from}:${bridge.to}`, bridge);
284
+ }
285
+
286
+ /**
287
+ * Set shared variable
288
+ */
289
+ setVariable(language: Language, name: string, value: unknown): void {
290
+ this.sharedState.set(`${language}:${name}`, value);
291
+ }
292
+
293
+ /**
294
+ * Get shared variable
295
+ */
296
+ getVariable(language: Language, name: string): unknown {
297
+ return this.sharedState.get(`${language}:${name}`);
298
+ }
299
+
300
+ /**
301
+ * Transfer variable between languages
302
+ */
303
+ async transferVariable(
304
+ fromLanguage: Language,
305
+ name: string,
306
+ toLanguage: Language
307
+ ): Promise<unknown> {
308
+ const value = this.sharedState.get(`${fromLanguage}:${name}`);
309
+ if (value === undefined) {
310
+ throw new Error(`Variable ${name} not found in ${fromLanguage}`);
311
+ }
312
+
313
+ const bridge = this.getBridge(fromLanguage, toLanguage);
314
+ if (!bridge) {
315
+ throw new Error(`No bridge from ${fromLanguage} to ${toLanguage}`);
316
+ }
317
+
318
+ const serialized = bridge.serialize(value);
319
+ const transferred = bridge.deserialize(serialized);
320
+
321
+ // Store in target language
322
+ this.sharedState.set(`${toLanguage}:${name}`, transferred);
323
+
324
+ return transferred;
325
+ }
326
+
327
+ /**
328
+ * Get all shared variables
329
+ */
330
+ getSharedVariables(): Map<string, unknown> {
331
+ return new Map(this.sharedState);
332
+ }
333
+
334
+ /**
335
+ * Clear shared state
336
+ */
337
+ clearState(): void {
338
+ this.sharedState.clear();
339
+ this.variableBindings.clear();
340
+ }
341
+
342
+ /**
343
+ * Shutdown all kernels
344
+ */
345
+ async shutdown(): Promise<void> {
346
+ for (const kernel of this.kernels.values()) {
347
+ await kernel.shutdown();
348
+ }
349
+ this.kernels.clear();
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Polyglot Notebook
355
+ *
356
+ * Notebook with multi-language cells and variable sharing.
357
+ */
358
+ export class PolyglotNotebook {
359
+ private cells = new Map<string, PolyglotCell>();
360
+ private session: PolyglotSession;
361
+ private executionOrder: string[] = [];
362
+
363
+ constructor(options?: PolyglotOptions) {
364
+ this.session = new PolyglotSession(options);
365
+ }
366
+
367
+ /**
368
+ * Add polyglot cell
369
+ */
370
+ addCell(variants: Map<Language, string>, id?: string): PolyglotCell {
371
+ const cell: PolyglotCell = {
372
+ id: id ?? uuid(),
373
+ variants,
374
+ };
375
+
376
+ this.cells.set(cell.id, cell);
377
+ this.executionOrder.push(cell.id);
378
+
379
+ return cell;
380
+ }
381
+
382
+ /**
383
+ * Add single-language cell
384
+ */
385
+ addSingleCell(language: Language, code: string, id?: string): PolyglotCell {
386
+ const variants = new Map<Language, string>();
387
+ variants.set(language, code);
388
+ return this.addCell(variants, id);
389
+ }
390
+
391
+ /**
392
+ * Execute all cells
393
+ */
394
+ async runAll(): Promise<Array<{ cellId: string; language: Language; result: ExecutionResult }>> {
395
+ const results: Array<{ cellId: string; language: Language; result: ExecutionResult }> = [];
396
+
397
+ for (const cellId of this.executionOrder) {
398
+ const cell = this.cells.get(cellId);
399
+ if (!cell) continue;
400
+
401
+ const { language, result } = await this.session.executePolyglot(cell);
402
+ results.push({ cellId, language, result });
403
+
404
+ if (!result.success) {
405
+ break;
406
+ }
407
+ }
408
+
409
+ return results;
410
+ }
411
+
412
+ /**
413
+ * Execute single cell
414
+ */
415
+ async runCell(cellId: string, preferredLanguage?: Language): Promise<{
416
+ language: Language;
417
+ result: ExecutionResult;
418
+ }> {
419
+ const cell = this.cells.get(cellId);
420
+ if (!cell) {
421
+ throw new Error(`Cell not found: ${cellId}`);
422
+ }
423
+
424
+ return this.session.executePolyglot(cell, preferredLanguage);
425
+ }
426
+
427
+ /**
428
+ * Get cell
429
+ */
430
+ getCell(id: string): PolyglotCell | undefined {
431
+ return this.cells.get(id);
432
+ }
433
+
434
+ /**
435
+ * Get all cells
436
+ */
437
+ getCells(): PolyglotCell[] {
438
+ return this.executionOrder.map(id => this.cells.get(id)!).filter(Boolean);
439
+ }
440
+
441
+ /**
442
+ * Get session
443
+ */
444
+ getSession(): PolyglotSession {
445
+ return this.session;
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Create polyglot session
451
+ */
452
+ export function createPolyglotSession(options?: PolyglotOptions): PolyglotSession {
453
+ return new PolyglotSession(options);
454
+ }
455
+
456
+ /**
457
+ * Create polyglot notebook
458
+ */
459
+ export function createPolyglotNotebook(options?: PolyglotOptions): PolyglotNotebook {
460
+ return new PolyglotNotebook(options);
461
+ }