@cloudflare/sandbox 0.2.0 → 0.2.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 (51) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/Dockerfile +31 -7
  3. package/README.md +226 -2
  4. package/container_src/bun.lock +122 -0
  5. package/container_src/index.ts +171 -1
  6. package/container_src/jupyter-server.ts +336 -0
  7. package/container_src/mime-processor.ts +255 -0
  8. package/container_src/package.json +9 -0
  9. package/container_src/startup.sh +52 -0
  10. package/dist/{chunk-YVZ3K26G.js → chunk-CUHYLCMT.js} +9 -21
  11. package/dist/chunk-CUHYLCMT.js.map +1 -0
  12. package/dist/chunk-EGC5IYXA.js +108 -0
  13. package/dist/chunk-EGC5IYXA.js.map +1 -0
  14. package/dist/chunk-FKBV7CZS.js +113 -0
  15. package/dist/chunk-FKBV7CZS.js.map +1 -0
  16. package/dist/{chunk-ZJN2PQOS.js → chunk-IATLC32Y.js} +173 -74
  17. package/dist/chunk-IATLC32Y.js.map +1 -0
  18. package/dist/{chunk-6THNBO4S.js → chunk-S5FFBU4Y.js} +1 -1
  19. package/dist/{chunk-6THNBO4S.js.map → chunk-S5FFBU4Y.js.map} +1 -1
  20. package/dist/chunk-SYMWNYWA.js +185 -0
  21. package/dist/chunk-SYMWNYWA.js.map +1 -0
  22. package/dist/{client-BXYlxy-j.d.ts → client-C7rKCYBD.d.ts} +42 -4
  23. package/dist/client.d.ts +2 -1
  24. package/dist/client.js +1 -1
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +10 -4
  27. package/dist/interpreter-types.d.ts +259 -0
  28. package/dist/interpreter-types.js +9 -0
  29. package/dist/interpreter-types.js.map +1 -0
  30. package/dist/interpreter.d.ts +33 -0
  31. package/dist/interpreter.js +8 -0
  32. package/dist/interpreter.js.map +1 -0
  33. package/dist/jupyter-client.d.ts +4 -0
  34. package/dist/jupyter-client.js +8 -0
  35. package/dist/jupyter-client.js.map +1 -0
  36. package/dist/request-handler.d.ts +2 -1
  37. package/dist/request-handler.js +7 -3
  38. package/dist/sandbox.d.ts +2 -1
  39. package/dist/sandbox.js +7 -3
  40. package/dist/types.d.ts +8 -0
  41. package/dist/types.js +1 -1
  42. package/package.json +1 -1
  43. package/src/client.ts +37 -54
  44. package/src/index.ts +13 -4
  45. package/src/interpreter-types.ts +383 -0
  46. package/src/interpreter.ts +150 -0
  47. package/src/jupyter-client.ts +266 -0
  48. package/src/sandbox.ts +281 -153
  49. package/src/types.ts +15 -0
  50. package/dist/chunk-YVZ3K26G.js.map +0 -1
  51. package/dist/chunk-ZJN2PQOS.js.map +0 -1
@@ -0,0 +1,185 @@
1
+ import {
2
+ HttpClient
3
+ } from "./chunk-CUHYLCMT.js";
4
+
5
+ // src/jupyter-client.ts
6
+ var JupyterClient = class extends HttpClient {
7
+ async createCodeContext(options = {}) {
8
+ const response = await this.doFetch("/api/contexts", {
9
+ method: "POST",
10
+ headers: { "Content-Type": "application/json" },
11
+ body: JSON.stringify({
12
+ language: options.language || "python",
13
+ cwd: options.cwd || "/workspace",
14
+ env_vars: options.envVars
15
+ })
16
+ });
17
+ if (!response.ok) {
18
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
19
+ throw new Error(errorData.error || `Failed to create context: ${response.status}`);
20
+ }
21
+ const data = await response.json();
22
+ return {
23
+ id: data.id,
24
+ language: data.language,
25
+ cwd: data.cwd,
26
+ createdAt: new Date(data.createdAt),
27
+ lastUsed: new Date(data.lastUsed)
28
+ };
29
+ }
30
+ async runCodeStream(contextId, code, language, callbacks) {
31
+ const response = await this.doFetch("/api/execute/code", {
32
+ method: "POST",
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ "Accept": "text/event-stream"
36
+ },
37
+ body: JSON.stringify({
38
+ context_id: contextId,
39
+ code,
40
+ language
41
+ })
42
+ });
43
+ if (!response.ok) {
44
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
45
+ throw new Error(errorData.error || `Failed to execute code: ${response.status}`);
46
+ }
47
+ if (!response.body) {
48
+ throw new Error("No response body for streaming execution");
49
+ }
50
+ for await (const chunk of this.readLines(response.body)) {
51
+ await this.parseExecutionResult(chunk, callbacks);
52
+ }
53
+ }
54
+ async *readLines(stream) {
55
+ const reader = stream.getReader();
56
+ let buffer = "";
57
+ try {
58
+ while (true) {
59
+ const { done, value } = await reader.read();
60
+ if (value) {
61
+ buffer += new TextDecoder().decode(value);
62
+ }
63
+ if (done) break;
64
+ let newlineIdx = buffer.indexOf("\n");
65
+ while (newlineIdx !== -1) {
66
+ yield buffer.slice(0, newlineIdx);
67
+ buffer = buffer.slice(newlineIdx + 1);
68
+ newlineIdx = buffer.indexOf("\n");
69
+ }
70
+ }
71
+ if (buffer.length > 0) {
72
+ yield buffer;
73
+ }
74
+ } finally {
75
+ reader.releaseLock();
76
+ }
77
+ }
78
+ async parseExecutionResult(line, callbacks) {
79
+ if (!line.trim()) return;
80
+ try {
81
+ const data = JSON.parse(line);
82
+ switch (data.type) {
83
+ case "stdout":
84
+ if (callbacks.onStdout && data.text) {
85
+ await callbacks.onStdout({
86
+ text: data.text,
87
+ timestamp: data.timestamp || Date.now()
88
+ });
89
+ }
90
+ break;
91
+ case "stderr":
92
+ if (callbacks.onStderr && data.text) {
93
+ await callbacks.onStderr({
94
+ text: data.text,
95
+ timestamp: data.timestamp || Date.now()
96
+ });
97
+ }
98
+ break;
99
+ case "result":
100
+ if (callbacks.onResult) {
101
+ const result = {
102
+ text: data.text,
103
+ html: data.html,
104
+ png: data.png,
105
+ jpeg: data.jpeg,
106
+ svg: data.svg,
107
+ latex: data.latex,
108
+ markdown: data.markdown,
109
+ javascript: data.javascript,
110
+ json: data.json,
111
+ chart: data.chart,
112
+ data: data.data,
113
+ formats: () => {
114
+ const formats = [];
115
+ if (data.text) formats.push("text");
116
+ if (data.html) formats.push("html");
117
+ if (data.png) formats.push("png");
118
+ if (data.jpeg) formats.push("jpeg");
119
+ if (data.svg) formats.push("svg");
120
+ if (data.latex) formats.push("latex");
121
+ if (data.markdown) formats.push("markdown");
122
+ if (data.javascript) formats.push("javascript");
123
+ if (data.json) formats.push("json");
124
+ if (data.chart) formats.push("chart");
125
+ return formats;
126
+ }
127
+ };
128
+ await callbacks.onResult(result);
129
+ }
130
+ break;
131
+ case "error":
132
+ if (callbacks.onError) {
133
+ await callbacks.onError({
134
+ name: data.ename || "Error",
135
+ value: data.evalue || data.text || "Unknown error",
136
+ traceback: data.traceback || [],
137
+ lineNumber: data.lineNumber
138
+ });
139
+ }
140
+ break;
141
+ case "execution_complete":
142
+ break;
143
+ }
144
+ } catch (error) {
145
+ console.error("[JupyterClient] Error parsing execution result:", error);
146
+ }
147
+ }
148
+ async listCodeContexts() {
149
+ const response = await this.doFetch("/api/contexts", {
150
+ method: "GET",
151
+ headers: { "Content-Type": "application/json" }
152
+ });
153
+ if (!response.ok) {
154
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
155
+ throw new Error(errorData.error || `Failed to list contexts: ${response.status}`);
156
+ }
157
+ const data = await response.json();
158
+ return data.contexts.map((ctx) => ({
159
+ id: ctx.id,
160
+ language: ctx.language,
161
+ cwd: ctx.cwd,
162
+ createdAt: new Date(ctx.createdAt),
163
+ lastUsed: new Date(ctx.lastUsed)
164
+ }));
165
+ }
166
+ async deleteCodeContext(contextId) {
167
+ const response = await this.doFetch(`/api/contexts/${contextId}`, {
168
+ method: "DELETE",
169
+ headers: { "Content-Type": "application/json" }
170
+ });
171
+ if (!response.ok) {
172
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
173
+ throw new Error(errorData.error || `Failed to delete context: ${response.status}`);
174
+ }
175
+ }
176
+ // Override parent doFetch to be public for this class
177
+ async doFetch(path, options) {
178
+ return super.doFetch(path, options);
179
+ }
180
+ };
181
+
182
+ export {
183
+ JupyterClient
184
+ };
185
+ //# sourceMappingURL=chunk-SYMWNYWA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jupyter-client.ts"],"sourcesContent":["import { HttpClient } from './client.js';\nimport type { \n CodeContext, \n CreateContextOptions, \n ExecutionError, \n OutputMessage,\n Result\n} from './interpreter-types.js';\n\n// API Response types\ninterface ContextResponse {\n id: string;\n language: string;\n cwd: string;\n createdAt: string; // ISO date string from JSON\n lastUsed: string; // ISO date string from JSON\n}\n\ninterface ContextListResponse {\n contexts: ContextResponse[];\n}\n\ninterface ErrorResponse {\n error: string;\n}\n\n// Streaming execution data from the server\ninterface StreamingExecutionData {\n type: 'result' | 'stdout' | 'stderr' | 'error' | 'execution_complete';\n text?: string;\n html?: string;\n png?: string; // base64\n jpeg?: string; // base64\n svg?: string;\n latex?: string;\n markdown?: string;\n javascript?: string;\n json?: any;\n chart?: any;\n data?: any;\n metadata?: any;\n execution_count?: number;\n ename?: string;\n evalue?: string;\n traceback?: string[];\n lineNumber?: number;\n timestamp?: number;\n}\n\nexport interface ExecutionCallbacks {\n onStdout?: (output: OutputMessage) => void | Promise<void>;\n onStderr?: (output: OutputMessage) => void | Promise<void>;\n onResult?: (result: Result) => void | Promise<void>;\n onError?: (error: ExecutionError) => void | Promise<void>;\n}\n\nexport class JupyterClient extends HttpClient {\n async createCodeContext(options: CreateContextOptions = {}): Promise<CodeContext> {\n const response = await this.doFetch('/api/contexts', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n language: options.language || 'python',\n cwd: options.cwd || '/workspace',\n env_vars: options.envVars\n }),\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as ErrorResponse;\n throw new Error(errorData.error || `Failed to create context: ${response.status}`);\n }\n \n const data = await response.json() as ContextResponse;\n return {\n id: data.id,\n language: data.language,\n cwd: data.cwd,\n createdAt: new Date(data.createdAt),\n lastUsed: new Date(data.lastUsed)\n };\n }\n \n async runCodeStream(\n contextId: string | undefined, \n code: string, \n language: string | undefined,\n callbacks: ExecutionCallbacks\n ): Promise<void> {\n const response = await this.doFetch('/api/execute/code', {\n method: 'POST',\n headers: { \n 'Content-Type': 'application/json',\n 'Accept': 'text/event-stream'\n },\n body: JSON.stringify({ \n context_id: contextId, \n code,\n language \n }),\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as ErrorResponse;\n throw new Error(errorData.error || `Failed to execute code: ${response.status}`);\n }\n \n if (!response.body) {\n throw new Error('No response body for streaming execution');\n }\n \n // Process streaming response\n for await (const chunk of this.readLines(response.body)) {\n await this.parseExecutionResult(chunk, callbacks);\n }\n }\n \n private async *readLines(stream: ReadableStream<Uint8Array>): AsyncGenerator<string> {\n const reader = stream.getReader();\n let buffer = '';\n \n try {\n while (true) {\n const { done, value } = await reader.read();\n if (value) {\n buffer += new TextDecoder().decode(value);\n }\n if (done) break;\n \n let newlineIdx = buffer.indexOf('\\n');\n while (newlineIdx !== -1) {\n yield buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + 1);\n newlineIdx = buffer.indexOf('\\n');\n }\n }\n \n // Yield any remaining data\n if (buffer.length > 0) {\n yield buffer;\n }\n } finally {\n reader.releaseLock();\n }\n }\n \n private async parseExecutionResult(line: string, callbacks: ExecutionCallbacks) {\n if (!line.trim()) return;\n \n try {\n const data = JSON.parse(line) as StreamingExecutionData;\n \n switch (data.type) {\n case 'stdout':\n if (callbacks.onStdout && data.text) {\n await callbacks.onStdout({\n text: data.text,\n timestamp: data.timestamp || Date.now()\n });\n }\n break;\n \n case 'stderr':\n if (callbacks.onStderr && data.text) {\n await callbacks.onStderr({\n text: data.text,\n timestamp: data.timestamp || Date.now()\n });\n }\n break;\n \n case 'result':\n if (callbacks.onResult) {\n // Convert raw result to Result interface\n const result: Result = {\n text: data.text,\n html: data.html,\n png: data.png,\n jpeg: data.jpeg,\n svg: data.svg,\n latex: data.latex,\n markdown: data.markdown,\n javascript: data.javascript,\n json: data.json,\n chart: data.chart,\n data: data.data,\n formats: () => {\n const formats: string[] = [];\n if (data.text) formats.push('text');\n if (data.html) formats.push('html');\n if (data.png) formats.push('png');\n if (data.jpeg) formats.push('jpeg');\n if (data.svg) formats.push('svg');\n if (data.latex) formats.push('latex');\n if (data.markdown) formats.push('markdown');\n if (data.javascript) formats.push('javascript');\n if (data.json) formats.push('json');\n if (data.chart) formats.push('chart');\n return formats;\n }\n };\n await callbacks.onResult(result);\n }\n break;\n \n case 'error':\n if (callbacks.onError) {\n await callbacks.onError({\n name: data.ename || 'Error',\n value: data.evalue || data.text || 'Unknown error',\n traceback: data.traceback || [],\n lineNumber: data.lineNumber\n });\n }\n break;\n \n case 'execution_complete':\n // Execution completed successfully\n break;\n }\n } catch (error) {\n console.error('[JupyterClient] Error parsing execution result:', error);\n }\n }\n \n async listCodeContexts(): Promise<CodeContext[]> {\n const response = await this.doFetch('/api/contexts', {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' }\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as ErrorResponse;\n throw new Error(errorData.error || `Failed to list contexts: ${response.status}`);\n }\n \n const data = await response.json() as ContextListResponse;\n return data.contexts.map((ctx) => ({\n id: ctx.id,\n language: ctx.language,\n cwd: ctx.cwd,\n createdAt: new Date(ctx.createdAt),\n lastUsed: new Date(ctx.lastUsed)\n }));\n }\n \n async deleteCodeContext(contextId: string): Promise<void> {\n const response = await this.doFetch(`/api/contexts/${contextId}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' }\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as ErrorResponse;\n throw new Error(errorData.error || `Failed to delete context: ${response.status}`);\n }\n }\n \n // Override parent doFetch to be public for this class\n public async doFetch(\n path: string,\n options?: RequestInit\n ): Promise<Response> {\n return super.doFetch(path, options);\n }\n}"],"mappings":"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","names":[]}
@@ -1,12 +1,30 @@
1
1
  import { Container } from '@cloudflare/containers';
2
+ import { CreateContextOptions, CodeContext, OutputMessage, Result, ExecutionError, RunCodeOptions, ExecutionResult } from './interpreter-types.js';
2
3
  import { ISandbox, ExecOptions, ExecResult, ProcessOptions, Process, StreamOptions, BaseExecOptions, StartProcessResponse, ListProcessesResponse, GetProcessResponse, GetProcessLogsResponse } from './types.js';
3
4
 
5
+ interface ExecutionCallbacks {
6
+ onStdout?: (output: OutputMessage) => void | Promise<void>;
7
+ onStderr?: (output: OutputMessage) => void | Promise<void>;
8
+ onResult?: (result: Result) => void | Promise<void>;
9
+ onError?: (error: ExecutionError) => void | Promise<void>;
10
+ }
11
+ declare class JupyterClient extends HttpClient {
12
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
13
+ runCodeStream(contextId: string | undefined, code: string, language: string | undefined, callbacks: ExecutionCallbacks): Promise<void>;
14
+ private readLines;
15
+ private parseExecutionResult;
16
+ listCodeContexts(): Promise<CodeContext[]>;
17
+ deleteCodeContext(contextId: string): Promise<void>;
18
+ doFetch(path: string, options?: RequestInit): Promise<Response>;
19
+ }
20
+
4
21
  declare function getSandbox(ns: DurableObjectNamespace<Sandbox>, id: string): DurableObjectStub<Sandbox<unknown>>;
5
22
  declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
6
23
  defaultPort: number;
7
24
  sleepAfter: string;
8
- client: HttpClient;
25
+ client: JupyterClient;
9
26
  private sandboxName;
27
+ private codeInterpreter;
10
28
  constructor(ctx: DurableObjectState, env: Env);
11
29
  setSandboxName(name: string): Promise<void>;
12
30
  setEnvVars(envVars: Record<string, string>): Promise<void>;
@@ -64,6 +82,26 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
64
82
  exposedAt: string;
65
83
  }[]>;
66
84
  private constructPreviewUrl;
85
+ /**
86
+ * Create a new code execution context
87
+ */
88
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
89
+ /**
90
+ * Run code with streaming callbacks
91
+ */
92
+ runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
93
+ /**
94
+ * Run code and return a streaming response
95
+ */
96
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
97
+ /**
98
+ * List all code contexts
99
+ */
100
+ listCodeContexts(): Promise<CodeContext[]>;
101
+ /**
102
+ * Delete a code context
103
+ */
104
+ deleteCodeContext(contextId: string): Promise<void>;
67
105
  }
68
106
 
69
107
  interface ExecuteResponse {
@@ -166,8 +204,8 @@ declare class HttpClient {
166
204
  private options;
167
205
  private sessionId;
168
206
  constructor(options?: HttpClientOptions);
169
- private doFetch;
170
- execute(command: string, options: Pick<BaseExecOptions, 'sessionId' | 'cwd' | 'env'>): Promise<ExecuteResponse>;
207
+ protected doFetch(path: string, options?: RequestInit): Promise<Response>;
208
+ execute(command: string, options: Pick<BaseExecOptions, "sessionId" | "cwd" | "env">): Promise<ExecuteResponse>;
171
209
  executeCommandStream(command: string, sessionId?: string): Promise<ReadableStream<Uint8Array>>;
172
210
  gitCheckout(repoUrl: string, branch?: string, targetDir?: string, sessionId?: string): Promise<GitCheckoutResponse>;
173
211
  mkdir(path: string, recursive?: boolean, sessionId?: string): Promise<MkdirResponse>;
@@ -208,4 +246,4 @@ declare class HttpClient {
208
246
  streamProcessLogs(processId: string): Promise<ReadableStream<Uint8Array>>;
209
247
  }
210
248
 
211
- export { type DeleteFileResponse as D, type ExecuteResponse as E, type GitCheckoutResponse as G, HttpClient as H, type MkdirResponse as M, type ReadFileResponse as R, Sandbox as S, type WriteFileResponse as W, type MoveFileResponse as a, type RenameFileResponse as b, getSandbox as g };
249
+ export { type DeleteFileResponse as D, type ExecuteResponse as E, type GitCheckoutResponse as G, HttpClient as H, JupyterClient as J, type MkdirResponse as M, type ReadFileResponse as R, Sandbox as S, type WriteFileResponse as W, type MoveFileResponse as a, type RenameFileResponse as b, type ExecutionCallbacks as c, getSandbox as g };
package/dist/client.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { D as DeleteFileResponse, E as ExecuteResponse, G as GitCheckoutResponse, H as HttpClient, M as MkdirResponse, a as MoveFileResponse, R as ReadFileResponse, b as RenameFileResponse, W as WriteFileResponse } from './client-BXYlxy-j.js';
1
+ export { D as DeleteFileResponse, E as ExecuteResponse, G as GitCheckoutResponse, H as HttpClient, M as MkdirResponse, a as MoveFileResponse, R as ReadFileResponse, b as RenameFileResponse, W as WriteFileResponse } from './client-C7rKCYBD.js';
2
2
  import './types.js';
3
3
  import '@cloudflare/containers';
4
+ import './interpreter-types.js';
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HttpClient
3
- } from "./chunk-YVZ3K26G.js";
3
+ } from "./chunk-CUHYLCMT.js";
4
4
  export {
5
5
  HttpClient
6
6
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { D as DeleteFileResponse, E as ExecuteResponse, G as GitCheckoutResponse, M as MkdirResponse, a as MoveFileResponse, R as ReadFileResponse, b as RenameFileResponse, S as Sandbox, W as WriteFileResponse, g as getSandbox } from './client-BXYlxy-j.js';
1
+ export { D as DeleteFileResponse, E as ExecuteResponse, G as GitCheckoutResponse, M as MkdirResponse, a as MoveFileResponse, R as ReadFileResponse, b as RenameFileResponse, S as Sandbox, W as WriteFileResponse, g as getSandbox } from './client-C7rKCYBD.js';
2
+ export { ChartData, CodeContext, CreateContextOptions, Execution, ExecutionError, OutputMessage, Result, ResultImpl, RunCodeOptions } from './interpreter-types.js';
2
3
  export { RouteInfo, SandboxEnv, proxyToSandbox } from './request-handler.js';
3
4
  export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } from './sse-parser.js';
4
5
  export { ExecEvent, LogEvent } from './types.js';
package/dist/index.js CHANGED
@@ -2,16 +2,22 @@ import {
2
2
  Sandbox,
3
3
  getSandbox,
4
4
  proxyToSandbox
5
- } from "./chunk-ZJN2PQOS.js";
6
- import "./chunk-YVZ3K26G.js";
7
- import "./chunk-6UAWTJ5S.js";
5
+ } from "./chunk-IATLC32Y.js";
8
6
  import {
9
7
  asyncIterableToSSEStream,
10
8
  parseSSEStream,
11
9
  responseToAsyncIterable
12
10
  } from "./chunk-NNGBXDMY.js";
13
- import "./chunk-6THNBO4S.js";
11
+ import "./chunk-S5FFBU4Y.js";
12
+ import "./chunk-FKBV7CZS.js";
13
+ import {
14
+ ResultImpl
15
+ } from "./chunk-EGC5IYXA.js";
16
+ import "./chunk-SYMWNYWA.js";
17
+ import "./chunk-CUHYLCMT.js";
18
+ import "./chunk-6UAWTJ5S.js";
14
19
  export {
20
+ ResultImpl,
15
21
  Sandbox,
16
22
  asyncIterableToSSEStream,
17
23
  getSandbox,
@@ -0,0 +1,259 @@
1
+ interface CreateContextOptions {
2
+ /**
3
+ * Programming language for the context
4
+ * @default 'python'
5
+ */
6
+ language?: 'python' | 'javascript' | 'typescript';
7
+ /**
8
+ * Working directory for the context
9
+ * @default '/workspace'
10
+ */
11
+ cwd?: string;
12
+ /**
13
+ * Environment variables for the context
14
+ */
15
+ envVars?: Record<string, string>;
16
+ /**
17
+ * Request timeout in milliseconds
18
+ * @default 30000
19
+ */
20
+ timeout?: number;
21
+ }
22
+ interface CodeContext {
23
+ /**
24
+ * Unique identifier for the context
25
+ */
26
+ readonly id: string;
27
+ /**
28
+ * Programming language of the context
29
+ */
30
+ readonly language: string;
31
+ /**
32
+ * Current working directory
33
+ */
34
+ readonly cwd: string;
35
+ /**
36
+ * When the context was created
37
+ */
38
+ readonly createdAt: Date;
39
+ /**
40
+ * When the context was last used
41
+ */
42
+ readonly lastUsed: Date;
43
+ }
44
+ interface RunCodeOptions {
45
+ /**
46
+ * Context to run the code in. If not provided, uses default context for the language
47
+ */
48
+ context?: CodeContext;
49
+ /**
50
+ * Language to use if context is not provided
51
+ * @default 'python'
52
+ */
53
+ language?: 'python' | 'javascript' | 'typescript';
54
+ /**
55
+ * Environment variables for this execution
56
+ */
57
+ envVars?: Record<string, string>;
58
+ /**
59
+ * Execution timeout in milliseconds
60
+ * @default 60000
61
+ */
62
+ timeout?: number;
63
+ /**
64
+ * AbortSignal for cancelling execution
65
+ */
66
+ signal?: AbortSignal;
67
+ /**
68
+ * Callback for stdout output
69
+ */
70
+ onStdout?: (output: OutputMessage) => void | Promise<void>;
71
+ /**
72
+ * Callback for stderr output
73
+ */
74
+ onStderr?: (output: OutputMessage) => void | Promise<void>;
75
+ /**
76
+ * Callback for execution results (charts, tables, etc)
77
+ */
78
+ onResult?: (result: Result) => void | Promise<void>;
79
+ /**
80
+ * Callback for execution errors
81
+ */
82
+ onError?: (error: ExecutionError) => void | Promise<void>;
83
+ }
84
+ interface OutputMessage {
85
+ /**
86
+ * The output text
87
+ */
88
+ text: string;
89
+ /**
90
+ * Timestamp of the output
91
+ */
92
+ timestamp: number;
93
+ }
94
+ interface Result {
95
+ /**
96
+ * Plain text representation
97
+ */
98
+ text?: string;
99
+ /**
100
+ * HTML representation (tables, formatted output)
101
+ */
102
+ html?: string;
103
+ /**
104
+ * PNG image data (base64 encoded)
105
+ */
106
+ png?: string;
107
+ /**
108
+ * JPEG image data (base64 encoded)
109
+ */
110
+ jpeg?: string;
111
+ /**
112
+ * SVG image data
113
+ */
114
+ svg?: string;
115
+ /**
116
+ * LaTeX representation
117
+ */
118
+ latex?: string;
119
+ /**
120
+ * Markdown representation
121
+ */
122
+ markdown?: string;
123
+ /**
124
+ * JavaScript code to execute
125
+ */
126
+ javascript?: string;
127
+ /**
128
+ * JSON data
129
+ */
130
+ json?: any;
131
+ /**
132
+ * Chart data if the result is a visualization
133
+ */
134
+ chart?: ChartData;
135
+ /**
136
+ * Raw data object
137
+ */
138
+ data?: any;
139
+ /**
140
+ * Available output formats
141
+ */
142
+ formats(): string[];
143
+ }
144
+ interface ChartData {
145
+ /**
146
+ * Type of chart
147
+ */
148
+ type: 'line' | 'bar' | 'scatter' | 'pie' | 'histogram' | 'heatmap' | 'unknown';
149
+ /**
150
+ * Chart title
151
+ */
152
+ title?: string;
153
+ /**
154
+ * Chart data (format depends on library)
155
+ */
156
+ data: any;
157
+ /**
158
+ * Chart layout/configuration
159
+ */
160
+ layout?: any;
161
+ /**
162
+ * Additional configuration
163
+ */
164
+ config?: any;
165
+ /**
166
+ * Library that generated the chart
167
+ */
168
+ library?: 'matplotlib' | 'plotly' | 'altair' | 'seaborn' | 'unknown';
169
+ /**
170
+ * Base64 encoded image if available
171
+ */
172
+ image?: string;
173
+ }
174
+ interface ExecutionError {
175
+ /**
176
+ * Error name/type (e.g., 'NameError', 'SyntaxError')
177
+ */
178
+ name: string;
179
+ /**
180
+ * Error message
181
+ */
182
+ value: string;
183
+ /**
184
+ * Stack trace
185
+ */
186
+ traceback: string[];
187
+ /**
188
+ * Line number where error occurred
189
+ */
190
+ lineNumber?: number;
191
+ }
192
+ interface ExecutionResult {
193
+ code: string;
194
+ logs: {
195
+ stdout: string[];
196
+ stderr: string[];
197
+ };
198
+ error?: ExecutionError;
199
+ executionCount?: number;
200
+ results: Array<{
201
+ text?: string;
202
+ html?: string;
203
+ png?: string;
204
+ jpeg?: string;
205
+ svg?: string;
206
+ latex?: string;
207
+ markdown?: string;
208
+ javascript?: string;
209
+ json?: any;
210
+ chart?: ChartData;
211
+ data?: any;
212
+ }>;
213
+ }
214
+ declare class Execution {
215
+ readonly code: string;
216
+ readonly context: CodeContext;
217
+ /**
218
+ * All results from the execution
219
+ */
220
+ results: Result[];
221
+ /**
222
+ * Accumulated stdout and stderr
223
+ */
224
+ logs: {
225
+ stdout: string[];
226
+ stderr: string[];
227
+ };
228
+ /**
229
+ * Execution error if any
230
+ */
231
+ error?: ExecutionError;
232
+ /**
233
+ * Execution count (for Jupyter)
234
+ */
235
+ executionCount?: number;
236
+ constructor(code: string, context: CodeContext);
237
+ /**
238
+ * Convert to a plain object for serialization
239
+ */
240
+ toJSON(): ExecutionResult;
241
+ }
242
+ declare class ResultImpl implements Result {
243
+ private raw;
244
+ constructor(raw: any);
245
+ get text(): string | undefined;
246
+ get html(): string | undefined;
247
+ get png(): string | undefined;
248
+ get jpeg(): string | undefined;
249
+ get svg(): string | undefined;
250
+ get latex(): string | undefined;
251
+ get markdown(): string | undefined;
252
+ get javascript(): string | undefined;
253
+ get json(): any;
254
+ get chart(): ChartData | undefined;
255
+ get data(): any;
256
+ formats(): string[];
257
+ }
258
+
259
+ export { type ChartData, type CodeContext, type CreateContextOptions, Execution, type ExecutionError, type ExecutionResult, type OutputMessage, type Result, ResultImpl, type RunCodeOptions };
@@ -0,0 +1,9 @@
1
+ import {
2
+ Execution,
3
+ ResultImpl
4
+ } from "./chunk-EGC5IYXA.js";
5
+ export {
6
+ Execution,
7
+ ResultImpl
8
+ };
9
+ //# sourceMappingURL=interpreter-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,33 @@
1
+ import { CreateContextOptions, CodeContext, RunCodeOptions, Execution } from './interpreter-types.js';
2
+ import { S as Sandbox } from './client-C7rKCYBD.js';
3
+ import '@cloudflare/containers';
4
+ import './types.js';
5
+
6
+ declare class CodeInterpreter {
7
+ private jupyterClient;
8
+ private contexts;
9
+ constructor(sandbox: Sandbox);
10
+ /**
11
+ * Create a new code execution context
12
+ */
13
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
14
+ /**
15
+ * Run code with optional context
16
+ */
17
+ runCode(code: string, options?: RunCodeOptions): Promise<Execution>;
18
+ /**
19
+ * Run code and return a streaming response
20
+ */
21
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
22
+ /**
23
+ * List all code contexts
24
+ */
25
+ listCodeContexts(): Promise<CodeContext[]>;
26
+ /**
27
+ * Delete a code context
28
+ */
29
+ deleteCodeContext(contextId: string): Promise<void>;
30
+ private getOrCreateDefaultContext;
31
+ }
32
+
33
+ export { CodeInterpreter };
@@ -0,0 +1,8 @@
1
+ import {
2
+ CodeInterpreter
3
+ } from "./chunk-FKBV7CZS.js";
4
+ import "./chunk-EGC5IYXA.js";
5
+ export {
6
+ CodeInterpreter
7
+ };
8
+ //# sourceMappingURL=interpreter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,4 @@
1
+ export { c as ExecutionCallbacks, J as JupyterClient } from './client-C7rKCYBD.js';
2
+ import './interpreter-types.js';
3
+ import '@cloudflare/containers';
4
+ import './types.js';
@@ -0,0 +1,8 @@
1
+ import {
2
+ JupyterClient
3
+ } from "./chunk-SYMWNYWA.js";
4
+ import "./chunk-CUHYLCMT.js";
5
+ export {
6
+ JupyterClient
7
+ };
8
+ //# sourceMappingURL=jupyter-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}