@cloudflare/sandbox 0.1.4 → 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.
- package/CHANGELOG.md +12 -0
- package/Dockerfile +37 -11
- package/README.md +229 -5
- package/container_src/bun.lock +122 -0
- package/container_src/handler/exec.ts +4 -2
- package/container_src/handler/process.ts +1 -1
- package/container_src/index.ts +171 -1
- package/container_src/jupyter-server.ts +336 -0
- package/container_src/mime-processor.ts +255 -0
- package/container_src/package.json +9 -0
- package/container_src/startup.sh +52 -0
- package/dist/{chunk-YVZ3K26G.js → chunk-CUHYLCMT.js} +9 -21
- package/dist/chunk-CUHYLCMT.js.map +1 -0
- package/dist/chunk-EGC5IYXA.js +108 -0
- package/dist/chunk-EGC5IYXA.js.map +1 -0
- package/dist/chunk-FKBV7CZS.js +113 -0
- package/dist/chunk-FKBV7CZS.js.map +1 -0
- package/dist/{chunk-ZJN2PQOS.js → chunk-IATLC32Y.js} +173 -74
- package/dist/chunk-IATLC32Y.js.map +1 -0
- package/dist/{chunk-6THNBO4S.js → chunk-S5FFBU4Y.js} +1 -1
- package/dist/{chunk-6THNBO4S.js.map → chunk-S5FFBU4Y.js.map} +1 -1
- package/dist/chunk-SYMWNYWA.js +185 -0
- package/dist/chunk-SYMWNYWA.js.map +1 -0
- package/dist/{client-BXYlxy-j.d.ts → client-C7rKCYBD.d.ts} +42 -4
- package/dist/client.d.ts +2 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +10 -4
- package/dist/interpreter-types.d.ts +259 -0
- package/dist/interpreter-types.js +9 -0
- package/dist/interpreter-types.js.map +1 -0
- package/dist/interpreter.d.ts +33 -0
- package/dist/interpreter.js +8 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/jupyter-client.d.ts +4 -0
- package/dist/jupyter-client.js +8 -0
- package/dist/jupyter-client.js.map +1 -0
- package/dist/request-handler.d.ts +2 -1
- package/dist/request-handler.js +7 -3
- package/dist/sandbox.d.ts +2 -1
- package/dist/sandbox.js +7 -3
- package/dist/types.d.ts +8 -0
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/src/client.ts +37 -54
- package/src/index.ts +13 -4
- package/src/interpreter-types.ts +383 -0
- package/src/interpreter.ts +150 -0
- package/src/jupyter-client.ts +266 -0
- package/src/sandbox.ts +281 -153
- package/src/types.ts +15 -0
- package/dist/chunk-YVZ3K26G.js.map +0 -1
- package/dist/chunk-ZJN2PQOS.js.map +0 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
export interface ExecutionResult {
|
|
2
|
+
type: 'result' | 'stdout' | 'stderr' | 'error' | 'execution_complete';
|
|
3
|
+
text?: string;
|
|
4
|
+
html?: string;
|
|
5
|
+
png?: string; // base64
|
|
6
|
+
jpeg?: string; // base64
|
|
7
|
+
svg?: string;
|
|
8
|
+
latex?: string;
|
|
9
|
+
markdown?: string;
|
|
10
|
+
javascript?: string;
|
|
11
|
+
json?: any;
|
|
12
|
+
chart?: ChartData;
|
|
13
|
+
data?: any;
|
|
14
|
+
metadata?: any;
|
|
15
|
+
execution_count?: number;
|
|
16
|
+
ename?: string;
|
|
17
|
+
evalue?: string;
|
|
18
|
+
traceback?: string[];
|
|
19
|
+
timestamp: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ChartData {
|
|
23
|
+
type: 'line' | 'bar' | 'scatter' | 'pie' | 'histogram' | 'heatmap' | 'unknown';
|
|
24
|
+
title?: string;
|
|
25
|
+
data: any;
|
|
26
|
+
layout?: any;
|
|
27
|
+
config?: any;
|
|
28
|
+
library?: 'matplotlib' | 'plotly' | 'altair' | 'seaborn' | 'unknown';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function processJupyterMessage(msg: any): ExecutionResult | null {
|
|
32
|
+
const msgType = msg.header?.msg_type || msg.msg_type;
|
|
33
|
+
|
|
34
|
+
switch (msgType) {
|
|
35
|
+
case 'execute_result':
|
|
36
|
+
case 'display_data':
|
|
37
|
+
return processDisplayData(msg.content.data, msg.content.metadata);
|
|
38
|
+
|
|
39
|
+
case 'stream':
|
|
40
|
+
return {
|
|
41
|
+
type: msg.content.name === 'stdout' ? 'stdout' : 'stderr',
|
|
42
|
+
text: msg.content.text,
|
|
43
|
+
timestamp: Date.now()
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
case 'error':
|
|
47
|
+
return {
|
|
48
|
+
type: 'error',
|
|
49
|
+
ename: msg.content.ename,
|
|
50
|
+
evalue: msg.content.evalue,
|
|
51
|
+
traceback: msg.content.traceback,
|
|
52
|
+
timestamp: Date.now()
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function processDisplayData(data: any, metadata?: any): ExecutionResult {
|
|
61
|
+
const result: ExecutionResult = {
|
|
62
|
+
type: 'result',
|
|
63
|
+
timestamp: Date.now(),
|
|
64
|
+
metadata
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Process different MIME types in order of preference
|
|
68
|
+
|
|
69
|
+
// Interactive/Rich formats
|
|
70
|
+
if (data['application/vnd.plotly.v1+json']) {
|
|
71
|
+
result.chart = extractPlotlyChart(data['application/vnd.plotly.v1+json']);
|
|
72
|
+
result.json = data['application/vnd.plotly.v1+json'];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (data['application/vnd.vega.v5+json']) {
|
|
76
|
+
result.chart = extractVegaChart(data['application/vnd.vega.v5+json'], 'vega');
|
|
77
|
+
result.json = data['application/vnd.vega.v5+json'];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (data['application/vnd.vegalite.v4+json'] || data['application/vnd.vegalite.v5+json']) {
|
|
81
|
+
const vegaData = data['application/vnd.vegalite.v4+json'] || data['application/vnd.vegalite.v5+json'];
|
|
82
|
+
result.chart = extractVegaChart(vegaData, 'vega-lite');
|
|
83
|
+
result.json = vegaData;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// HTML content (tables, formatted output)
|
|
87
|
+
if (data['text/html']) {
|
|
88
|
+
result.html = data['text/html'];
|
|
89
|
+
|
|
90
|
+
// Check if it's a pandas DataFrame
|
|
91
|
+
if (isPandasDataFrame(data['text/html'])) {
|
|
92
|
+
result.data = { type: 'dataframe', html: data['text/html'] };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Images
|
|
97
|
+
if (data['image/png']) {
|
|
98
|
+
result.png = data['image/png'];
|
|
99
|
+
|
|
100
|
+
// Try to detect if it's a chart
|
|
101
|
+
if (isLikelyChart(data, metadata)) {
|
|
102
|
+
result.chart = {
|
|
103
|
+
type: 'unknown',
|
|
104
|
+
library: 'matplotlib',
|
|
105
|
+
data: { image: data['image/png'] }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (data['image/jpeg']) {
|
|
111
|
+
result.jpeg = data['image/jpeg'];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (data['image/svg+xml']) {
|
|
115
|
+
result.svg = data['image/svg+xml'];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Mathematical content
|
|
119
|
+
if (data['text/latex']) {
|
|
120
|
+
result.latex = data['text/latex'];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Code
|
|
124
|
+
if (data['application/javascript']) {
|
|
125
|
+
result.javascript = data['application/javascript'];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Structured data
|
|
129
|
+
if (data['application/json']) {
|
|
130
|
+
result.json = data['application/json'];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Markdown
|
|
134
|
+
if (data['text/markdown']) {
|
|
135
|
+
result.markdown = data['text/markdown'];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Plain text (fallback)
|
|
139
|
+
if (data['text/plain']) {
|
|
140
|
+
result.text = data['text/plain'];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function extractPlotlyChart(plotlyData: any): ChartData {
|
|
147
|
+
const data = plotlyData.data || plotlyData;
|
|
148
|
+
const layout = plotlyData.layout || {};
|
|
149
|
+
|
|
150
|
+
// Try to detect chart type from traces
|
|
151
|
+
let chartType: ChartData['type'] = 'unknown';
|
|
152
|
+
if (data && data.length > 0) {
|
|
153
|
+
const firstTrace = data[0];
|
|
154
|
+
if (firstTrace.type === 'scatter') {
|
|
155
|
+
chartType = firstTrace.mode?.includes('lines') ? 'line' : 'scatter';
|
|
156
|
+
} else if (firstTrace.type === 'bar') {
|
|
157
|
+
chartType = 'bar';
|
|
158
|
+
} else if (firstTrace.type === 'pie') {
|
|
159
|
+
chartType = 'pie';
|
|
160
|
+
} else if (firstTrace.type === 'histogram') {
|
|
161
|
+
chartType = 'histogram';
|
|
162
|
+
} else if (firstTrace.type === 'heatmap') {
|
|
163
|
+
chartType = 'heatmap';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
type: chartType,
|
|
169
|
+
title: layout.title?.text || layout.title,
|
|
170
|
+
data: data,
|
|
171
|
+
layout: layout,
|
|
172
|
+
config: plotlyData.config,
|
|
173
|
+
library: 'plotly'
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function extractVegaChart(vegaData: any, format: 'vega' | 'vega-lite'): ChartData {
|
|
178
|
+
// Try to detect chart type from mark or encoding
|
|
179
|
+
let chartType: ChartData['type'] = 'unknown';
|
|
180
|
+
|
|
181
|
+
if (format === 'vega-lite' && vegaData.mark) {
|
|
182
|
+
const mark = typeof vegaData.mark === 'string' ? vegaData.mark : vegaData.mark.type;
|
|
183
|
+
switch (mark) {
|
|
184
|
+
case 'line':
|
|
185
|
+
chartType = 'line';
|
|
186
|
+
break;
|
|
187
|
+
case 'bar':
|
|
188
|
+
chartType = 'bar';
|
|
189
|
+
break;
|
|
190
|
+
case 'point':
|
|
191
|
+
case 'circle':
|
|
192
|
+
chartType = 'scatter';
|
|
193
|
+
break;
|
|
194
|
+
case 'arc':
|
|
195
|
+
chartType = 'pie';
|
|
196
|
+
break;
|
|
197
|
+
case 'rect':
|
|
198
|
+
if (vegaData.encoding?.color) {
|
|
199
|
+
chartType = 'heatmap';
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
type: chartType,
|
|
207
|
+
title: vegaData.title,
|
|
208
|
+
data: vegaData,
|
|
209
|
+
library: 'altair' // Altair outputs Vega-Lite
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function isPandasDataFrame(html: string): boolean {
|
|
214
|
+
// Simple heuristic to detect pandas DataFrame HTML
|
|
215
|
+
return html.includes('dataframe') ||
|
|
216
|
+
(html.includes('<table') && html.includes('<thead') && html.includes('<tbody'));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isLikelyChart(data: any, metadata?: any): boolean {
|
|
220
|
+
// Check metadata for hints
|
|
221
|
+
if (metadata?.needs?.includes('matplotlib')) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Check if other chart formats are present
|
|
226
|
+
if (data['application/vnd.plotly.v1+json'] ||
|
|
227
|
+
data['application/vnd.vega.v5+json'] ||
|
|
228
|
+
data['application/vnd.vegalite.v4+json']) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// If only image output without text, likely a chart
|
|
233
|
+
if ((data['image/png'] || data['image/svg+xml']) && !data['text/plain']) {
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function extractFormats(result: ExecutionResult): string[] {
|
|
241
|
+
const formats: string[] = [];
|
|
242
|
+
|
|
243
|
+
if (result.text) formats.push('text');
|
|
244
|
+
if (result.html) formats.push('html');
|
|
245
|
+
if (result.png) formats.push('png');
|
|
246
|
+
if (result.jpeg) formats.push('jpeg');
|
|
247
|
+
if (result.svg) formats.push('svg');
|
|
248
|
+
if (result.latex) formats.push('latex');
|
|
249
|
+
if (result.markdown) formats.push('markdown');
|
|
250
|
+
if (result.javascript) formats.push('javascript');
|
|
251
|
+
if (result.json) formats.push('json');
|
|
252
|
+
if (result.chart) formats.push('chart');
|
|
253
|
+
|
|
254
|
+
return formats;
|
|
255
|
+
}
|
|
@@ -5,5 +5,14 @@
|
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "bun run index.ts"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@jupyterlab/services": "^7.0.0",
|
|
11
|
+
"ws": "^8.16.0",
|
|
12
|
+
"uuid": "^9.0.1"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/ws": "^8.5.10",
|
|
16
|
+
"@types/uuid": "^9.0.7"
|
|
8
17
|
}
|
|
9
18
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Start Jupyter notebook server in background
|
|
4
|
+
echo "[Startup] Starting Jupyter server..."
|
|
5
|
+
jupyter notebook \
|
|
6
|
+
--ip=0.0.0.0 \
|
|
7
|
+
--port=8888 \
|
|
8
|
+
--no-browser \
|
|
9
|
+
--allow-root \
|
|
10
|
+
--NotebookApp.token='' \
|
|
11
|
+
--NotebookApp.password='' \
|
|
12
|
+
--NotebookApp.allow_origin='*' \
|
|
13
|
+
--NotebookApp.disable_check_xsrf=True \
|
|
14
|
+
--NotebookApp.allow_remote_access=True \
|
|
15
|
+
--NotebookApp.allow_credentials=True \
|
|
16
|
+
> /tmp/jupyter.log 2>&1 &
|
|
17
|
+
|
|
18
|
+
JUPYTER_PID=$!
|
|
19
|
+
|
|
20
|
+
# Wait for Jupyter to be ready
|
|
21
|
+
echo "[Startup] Waiting for Jupyter to become ready..."
|
|
22
|
+
MAX_ATTEMPTS=30
|
|
23
|
+
ATTEMPT=0
|
|
24
|
+
|
|
25
|
+
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
|
|
26
|
+
if curl -s http://localhost:8888/api > /dev/null 2>&1; then
|
|
27
|
+
echo "[Startup] Jupyter server is ready!"
|
|
28
|
+
break
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check if Jupyter process is still running
|
|
32
|
+
if ! kill -0 $JUPYTER_PID 2>/dev/null; then
|
|
33
|
+
echo "[Startup] ERROR: Jupyter process died. Check /tmp/jupyter.log for details"
|
|
34
|
+
cat /tmp/jupyter.log
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
ATTEMPT=$((ATTEMPT + 1))
|
|
39
|
+
echo "[Startup] Waiting for Jupyter... (attempt $ATTEMPT/$MAX_ATTEMPTS)"
|
|
40
|
+
sleep 1
|
|
41
|
+
done
|
|
42
|
+
|
|
43
|
+
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
|
|
44
|
+
echo "[Startup] ERROR: Jupyter failed to start within 30 seconds"
|
|
45
|
+
echo "[Startup] Jupyter logs:"
|
|
46
|
+
cat /tmp/jupyter.log
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Start the main Bun server
|
|
51
|
+
echo "[Startup] Starting Bun server..."
|
|
52
|
+
exec bun index.ts
|
|
@@ -91,7 +91,7 @@ var HttpClient = class {
|
|
|
91
91
|
}),
|
|
92
92
|
headers: {
|
|
93
93
|
"Content-Type": "application/json",
|
|
94
|
-
|
|
94
|
+
Accept: "text/event-stream"
|
|
95
95
|
},
|
|
96
96
|
method: "POST"
|
|
97
97
|
});
|
|
@@ -104,9 +104,7 @@ var HttpClient = class {
|
|
|
104
104
|
if (!response.body) {
|
|
105
105
|
throw new Error("No response body for streaming request");
|
|
106
106
|
}
|
|
107
|
-
console.log(
|
|
108
|
-
`[HTTP Client] Started command stream: ${command}`
|
|
109
|
-
);
|
|
107
|
+
console.log(`[HTTP Client] Started command stream: ${command}`);
|
|
110
108
|
return response.body;
|
|
111
109
|
} catch (error) {
|
|
112
110
|
console.error("[HTTP Client] Error in command stream:", error);
|
|
@@ -395,9 +393,7 @@ var HttpClient = class {
|
|
|
395
393
|
);
|
|
396
394
|
}
|
|
397
395
|
const data = await response.json();
|
|
398
|
-
console.log(
|
|
399
|
-
`[HTTP Client] Got ${data.count} exposed ports`
|
|
400
|
-
);
|
|
396
|
+
console.log(`[HTTP Client] Got ${data.count} exposed ports`);
|
|
401
397
|
return data;
|
|
402
398
|
} catch (error) {
|
|
403
399
|
console.error("[HTTP Client] Error getting exposed ports:", error);
|
|
@@ -501,9 +497,7 @@ var HttpClient = class {
|
|
|
501
497
|
);
|
|
502
498
|
}
|
|
503
499
|
const data = await response.json();
|
|
504
|
-
console.log(
|
|
505
|
-
`[HTTP Client] Listed ${data.processes.length} processes`
|
|
506
|
-
);
|
|
500
|
+
console.log(`[HTTP Client] Listed ${data.processes.length} processes`);
|
|
507
501
|
return data;
|
|
508
502
|
} catch (error) {
|
|
509
503
|
console.error("[HTTP Client] Error listing processes:", error);
|
|
@@ -549,9 +543,7 @@ var HttpClient = class {
|
|
|
549
543
|
);
|
|
550
544
|
}
|
|
551
545
|
const data = await response.json();
|
|
552
|
-
console.log(
|
|
553
|
-
`[HTTP Client] Killed process ${processId}`
|
|
554
|
-
);
|
|
546
|
+
console.log(`[HTTP Client] Killed process ${processId}`);
|
|
555
547
|
return data;
|
|
556
548
|
} catch (error) {
|
|
557
549
|
console.error("[HTTP Client] Error killing process:", error);
|
|
@@ -573,9 +565,7 @@ var HttpClient = class {
|
|
|
573
565
|
);
|
|
574
566
|
}
|
|
575
567
|
const data = await response.json();
|
|
576
|
-
console.log(
|
|
577
|
-
`[HTTP Client] Killed ${data.killedCount} processes`
|
|
578
|
-
);
|
|
568
|
+
console.log(`[HTTP Client] Killed ${data.killedCount} processes`);
|
|
579
569
|
return data;
|
|
580
570
|
} catch (error) {
|
|
581
571
|
console.error("[HTTP Client] Error killing all processes:", error);
|
|
@@ -597,9 +587,7 @@ var HttpClient = class {
|
|
|
597
587
|
);
|
|
598
588
|
}
|
|
599
589
|
const data = await response.json();
|
|
600
|
-
console.log(
|
|
601
|
-
`[HTTP Client] Got logs for process ${processId}`
|
|
602
|
-
);
|
|
590
|
+
console.log(`[HTTP Client] Got logs for process ${processId}`);
|
|
603
591
|
return data;
|
|
604
592
|
} catch (error) {
|
|
605
593
|
console.error("[HTTP Client] Error getting process logs:", error);
|
|
@@ -610,7 +598,7 @@ var HttpClient = class {
|
|
|
610
598
|
try {
|
|
611
599
|
const response = await this.doFetch(`/api/process/${processId}/stream`, {
|
|
612
600
|
headers: {
|
|
613
|
-
|
|
601
|
+
Accept: "text/event-stream",
|
|
614
602
|
"Cache-Control": "no-cache"
|
|
615
603
|
},
|
|
616
604
|
method: "GET"
|
|
@@ -638,4 +626,4 @@ var HttpClient = class {
|
|
|
638
626
|
export {
|
|
639
627
|
HttpClient
|
|
640
628
|
};
|
|
641
|
-
//# sourceMappingURL=chunk-
|
|
629
|
+
//# sourceMappingURL=chunk-CUHYLCMT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { ExecuteRequest } from \"../container_src/types\";\nimport type { Sandbox } from \"./index\";\nimport type {\n BaseExecOptions,\n GetProcessLogsResponse,\n GetProcessResponse,\n ListProcessesResponse,\n StartProcessRequest,\n StartProcessResponse,\n} from \"./types\";\n\nexport interface ExecuteResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n command: string;\n timestamp: string;\n}\n\ninterface CommandsResponse {\n availableCommands: string[];\n timestamp: string;\n}\n\ninterface GitCheckoutRequest {\n repoUrl: string;\n branch?: string;\n targetDir?: string;\n sessionId?: string;\n}\n\nexport interface GitCheckoutResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n repoUrl: string;\n branch: string;\n targetDir: string;\n timestamp: string;\n}\n\ninterface MkdirRequest {\n path: string;\n recursive?: boolean;\n sessionId?: string;\n}\n\nexport interface MkdirResponse {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number;\n path: string;\n recursive: boolean;\n timestamp: string;\n}\n\ninterface WriteFileRequest {\n path: string;\n content: string;\n encoding?: string;\n sessionId?: string;\n}\n\nexport interface WriteFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n timestamp: string;\n}\n\ninterface ReadFileRequest {\n path: string;\n encoding?: string;\n sessionId?: string;\n}\n\nexport interface ReadFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n content: string;\n timestamp: string;\n}\n\ninterface DeleteFileRequest {\n path: string;\n sessionId?: string;\n}\n\nexport interface DeleteFileResponse {\n success: boolean;\n exitCode: number;\n path: string;\n timestamp: string;\n}\n\ninterface RenameFileRequest {\n oldPath: string;\n newPath: string;\n sessionId?: string;\n}\n\nexport interface RenameFileResponse {\n success: boolean;\n exitCode: number;\n oldPath: string;\n newPath: string;\n timestamp: string;\n}\n\ninterface MoveFileRequest {\n sourcePath: string;\n destinationPath: string;\n sessionId?: string;\n}\n\nexport interface MoveFileResponse {\n success: boolean;\n exitCode: number;\n sourcePath: string;\n destinationPath: string;\n timestamp: string;\n}\n\ninterface PreviewInfo {\n url: string;\n port: number;\n name?: string;\n}\n\ninterface ExposedPort extends PreviewInfo {\n exposedAt: string;\n timestamp: string;\n}\n\ninterface ExposePortResponse {\n success: boolean;\n port: number;\n name?: string;\n exposedAt: string;\n timestamp: string;\n}\n\ninterface UnexposePortResponse {\n success: boolean;\n port: number;\n timestamp: string;\n}\n\ninterface GetExposedPortsResponse {\n ports: ExposedPort[];\n count: number;\n timestamp: string;\n}\n\ninterface PingResponse {\n message: string;\n timestamp: string;\n}\n\ninterface HttpClientOptions {\n stub?: Sandbox;\n baseUrl?: string;\n port?: number;\n onCommandStart?: (command: string) => void;\n onOutput?: (\n stream: \"stdout\" | \"stderr\",\n data: string,\n command: string\n ) => void;\n onCommandComplete?: (\n success: boolean,\n exitCode: number,\n stdout: string,\n stderr: string,\n command: string\n ) => void;\n onError?: (error: string, command?: string) => void;\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private options: HttpClientOptions;\n private sessionId: string | null = null;\n\n constructor(options: HttpClientOptions = {}) {\n this.options = {\n ...options,\n };\n this.baseUrl = this.options.baseUrl!;\n }\n\n protected async doFetch(\n path: string,\n options?: RequestInit\n ): Promise<Response> {\n const url = this.options.stub\n ? `http://localhost:${this.options.port}${path}`\n : `${this.baseUrl}${path}`;\n const method = options?.method || \"GET\";\n\n console.log(`[HTTP Client] Making ${method} request to ${url}`);\n\n try {\n let response: Response;\n\n if (this.options.stub) {\n response = await this.options.stub.containerFetch(\n url,\n options,\n this.options.port\n );\n } else {\n response = await fetch(url, options);\n }\n\n console.log(\n `[HTTP Client] Response: ${response.status} ${response.statusText}`\n );\n\n if (!response.ok) {\n console.error(\n `[HTTP Client] Request failed: ${method} ${url} - ${response.status} ${response.statusText}`\n );\n }\n\n return response;\n } catch (error) {\n console.error(`[HTTP Client] Request error: ${method} ${url}`, error);\n throw error;\n }\n }\n\n async execute(\n command: string,\n options: Pick<BaseExecOptions, \"sessionId\" | \"cwd\" | \"env\">\n ): Promise<ExecuteResponse> {\n try {\n const targetSessionId = options.sessionId || this.sessionId;\n const executeRequest = {\n command,\n sessionId: targetSessionId,\n cwd: options.cwd,\n env: options.env,\n } satisfies ExecuteRequest;\n\n const response = await this.doFetch(`/api/execute`, {\n body: JSON.stringify(executeRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ExecuteResponse = await response.json();\n console.log(\n `[HTTP Client] Command executed: ${command}, Success: ${data.success}`\n );\n\n // Call the callback if provided\n this.options.onCommandComplete?.(\n data.success,\n data.exitCode,\n data.stdout,\n data.stderr,\n data.command\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error executing command:\", error);\n this.options.onError?.(\n error instanceof Error ? error.message : \"Unknown error\",\n command\n );\n throw error;\n }\n }\n\n async executeCommandStream(\n command: string,\n sessionId?: string\n ): Promise<ReadableStream<Uint8Array>> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/execute/stream`, {\n body: JSON.stringify({\n command,\n sessionId: targetSessionId,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n if (!response.body) {\n throw new Error(\"No response body for streaming request\");\n }\n\n console.log(`[HTTP Client] Started command stream: ${command}`);\n\n return response.body;\n } catch (error) {\n console.error(\"[HTTP Client] Error in command stream:\", error);\n throw error;\n }\n }\n\n async gitCheckout(\n repoUrl: string,\n branch: string = \"main\",\n targetDir?: string,\n sessionId?: string\n ): Promise<GitCheckoutResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/git/checkout`, {\n body: JSON.stringify({\n branch,\n repoUrl,\n sessionId: targetSessionId,\n targetDir,\n } as GitCheckoutRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GitCheckoutResponse = await response.json();\n console.log(\n `[HTTP Client] Git checkout completed: ${repoUrl}, Success: ${data.success}, Target: ${data.targetDir}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error in git checkout:\", error);\n throw error;\n }\n }\n\n async mkdir(\n path: string,\n recursive: boolean = false,\n sessionId?: string\n ): Promise<MkdirResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/mkdir`, {\n body: JSON.stringify({\n path,\n recursive,\n sessionId: targetSessionId,\n } as MkdirRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: MkdirResponse = await response.json();\n console.log(\n `[HTTP Client] Directory created: ${path}, Success: ${data.success}, Recursive: ${data.recursive}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error creating directory:\", error);\n throw error;\n }\n }\n\n async writeFile(\n path: string,\n content: string,\n encoding: string = \"utf-8\",\n sessionId?: string\n ): Promise<WriteFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/write`, {\n body: JSON.stringify({\n content,\n encoding,\n path,\n sessionId: targetSessionId,\n } as WriteFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: WriteFileResponse = await response.json();\n console.log(\n `[HTTP Client] File written: ${path}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error writing file:\", error);\n throw error;\n }\n }\n\n async readFile(\n path: string,\n encoding: string = \"utf-8\",\n sessionId?: string\n ): Promise<ReadFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/read`, {\n body: JSON.stringify({\n encoding,\n path,\n sessionId: targetSessionId,\n } as ReadFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ReadFileResponse = await response.json();\n console.log(\n `[HTTP Client] File read: ${path}, Success: ${data.success}, Content length: ${data.content.length}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error reading file:\", error);\n throw error;\n }\n }\n\n async deleteFile(\n path: string,\n sessionId?: string\n ): Promise<DeleteFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/delete`, {\n body: JSON.stringify({\n path,\n sessionId: targetSessionId,\n } as DeleteFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: DeleteFileResponse = await response.json();\n console.log(\n `[HTTP Client] File deleted: ${path}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error deleting file:\", error);\n throw error;\n }\n }\n\n async renameFile(\n oldPath: string,\n newPath: string,\n sessionId?: string\n ): Promise<RenameFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/rename`, {\n body: JSON.stringify({\n newPath,\n oldPath,\n sessionId: targetSessionId,\n } as RenameFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: RenameFileResponse = await response.json();\n console.log(\n `[HTTP Client] File renamed: ${oldPath} -> ${newPath}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error renaming file:\", error);\n throw error;\n }\n }\n\n async moveFile(\n sourcePath: string,\n destinationPath: string,\n sessionId?: string\n ): Promise<MoveFileResponse> {\n try {\n const targetSessionId = sessionId || this.sessionId;\n\n const response = await this.doFetch(`/api/move`, {\n body: JSON.stringify({\n destinationPath,\n sessionId: targetSessionId,\n sourcePath,\n } as MoveFileRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: MoveFileResponse = await response.json();\n console.log(\n `[HTTP Client] File moved: ${sourcePath} -> ${destinationPath}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error moving file:\", error);\n throw error;\n }\n }\n\n async exposePort(port: number, name?: string): Promise<ExposePortResponse> {\n try {\n const response = await this.doFetch(`/api/expose-port`, {\n body: JSON.stringify({\n port,\n name,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n console.log(errorData);\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ExposePortResponse = await response.json();\n console.log(\n `[HTTP Client] Port exposed: ${port}${\n name ? ` (${name})` : \"\"\n }, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error exposing port:\", error);\n throw error;\n }\n }\n\n async unexposePort(port: number): Promise<UnexposePortResponse> {\n try {\n const response = await this.doFetch(`/api/unexpose-port`, {\n body: JSON.stringify({\n port,\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: UnexposePortResponse = await response.json();\n console.log(\n `[HTTP Client] Port unexposed: ${port}, Success: ${data.success}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error unexposing port:\", error);\n throw error;\n }\n }\n\n async getExposedPorts(): Promise<GetExposedPortsResponse> {\n try {\n const response = await this.doFetch(`/api/exposed-ports`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetExposedPortsResponse = await response.json();\n console.log(`[HTTP Client] Got ${data.count} exposed ports`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting exposed ports:\", error);\n throw error;\n }\n }\n\n async ping(): Promise<string> {\n try {\n const response = await this.doFetch(`/api/ping`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data: PingResponse = await response.json();\n console.log(`[HTTP Client] Ping response: ${data.message}`);\n return data.timestamp;\n } catch (error) {\n console.error(\"[HTTP Client] Error pinging server:\", error);\n throw error;\n }\n }\n\n async getCommands(): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseUrl}/api/commands`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data: CommandsResponse = await response.json();\n console.log(\n `[HTTP Client] Available commands: ${data.availableCommands.length}`\n );\n return data.availableCommands;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting commands:\", error);\n throw error;\n }\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n setSessionId(sessionId: string): void {\n this.sessionId = sessionId;\n }\n\n clearSession(): void {\n this.sessionId = null;\n }\n\n // Process management methods\n async startProcess(\n command: string,\n options?: {\n processId?: string;\n sessionId?: string;\n timeout?: number;\n env?: Record<string, string>;\n cwd?: string;\n encoding?: string;\n autoCleanup?: boolean;\n }\n ): Promise<StartProcessResponse> {\n try {\n const targetSessionId = options?.sessionId || this.sessionId;\n\n const response = await this.doFetch(\"/api/process/start\", {\n body: JSON.stringify({\n command,\n options: {\n ...options,\n sessionId: targetSessionId,\n },\n } as StartProcessRequest),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: StartProcessResponse = await response.json();\n console.log(\n `[HTTP Client] Process started: ${command}, ID: ${data.process.id}`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error starting process:\", error);\n throw error;\n }\n }\n\n async listProcesses(): Promise<ListProcessesResponse> {\n try {\n const response = await this.doFetch(\"/api/process/list\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: ListProcessesResponse = await response.json();\n console.log(`[HTTP Client] Listed ${data.processes.length} processes`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error listing processes:\", error);\n throw error;\n }\n }\n\n async getProcess(processId: string): Promise<GetProcessResponse> {\n try {\n const response = await this.doFetch(`/api/process/${processId}`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetProcessResponse = await response.json();\n console.log(\n `[HTTP Client] Got process ${processId}: ${\n data.process?.status || \"not found\"\n }`\n );\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting process:\", error);\n throw error;\n }\n }\n\n async killProcess(\n processId: string\n ): Promise<{ success: boolean; message: string }> {\n try {\n const response = await this.doFetch(`/api/process/${processId}`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data = (await response.json()) as {\n success: boolean;\n message: string;\n };\n console.log(`[HTTP Client] Killed process ${processId}`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error killing process:\", error);\n throw error;\n }\n }\n\n async killAllProcesses(): Promise<{\n success: boolean;\n killedCount: number;\n message: string;\n }> {\n try {\n const response = await this.doFetch(\"/api/process/kill-all\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"DELETE\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data = (await response.json()) as {\n success: boolean;\n killedCount: number;\n message: string;\n };\n console.log(`[HTTP Client] Killed ${data.killedCount} processes`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error killing all processes:\", error);\n throw error;\n }\n }\n\n async getProcessLogs(processId: string): Promise<GetProcessLogsResponse> {\n try {\n const response = await this.doFetch(`/api/process/${processId}/logs`, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n const data: GetProcessLogsResponse = await response.json();\n console.log(`[HTTP Client] Got logs for process ${processId}`);\n\n return data;\n } catch (error) {\n console.error(\"[HTTP Client] Error getting process logs:\", error);\n throw error;\n }\n }\n\n async streamProcessLogs(\n processId: string\n ): Promise<ReadableStream<Uint8Array>> {\n try {\n const response = await this.doFetch(`/api/process/${processId}/stream`, {\n headers: {\n Accept: \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(\n errorData.error || `HTTP error! status: ${response.status}`\n );\n }\n\n if (!response.body) {\n throw new Error(\"No response body for streaming request\");\n }\n\n console.log(\n `[HTTP Client] Started streaming logs for process ${processId}`\n );\n\n return response.body;\n } catch (error) {\n console.error(\"[HTTP Client] Error streaming process logs:\", error);\n throw error;\n }\n }\n}\n"],"mappings":";AAuLO,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA,YAA2B;AAAA,EAEnC,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,UAAU;AAAA,MACb,GAAG;AAAA,IACL;AACA,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA,EAEA,MAAgB,QACd,MACA,SACmB;AACnB,UAAM,MAAM,KAAK,QAAQ,OACrB,oBAAoB,KAAK,QAAQ,IAAI,GAAG,IAAI,KAC5C,GAAG,KAAK,OAAO,GAAG,IAAI;AAC1B,UAAM,SAAS,SAAS,UAAU;AAElC,YAAQ,IAAI,wBAAwB,MAAM,eAAe,GAAG,EAAE;AAE9D,QAAI;AACF,UAAI;AAEJ,UAAI,KAAK,QAAQ,MAAM;AACrB,mBAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,UACjC;AAAA,UACA;AAAA,UACA,KAAK,QAAQ;AAAA,QACf;AAAA,MACF,OAAO;AACL,mBAAW,MAAM,MAAM,KAAK,OAAO;AAAA,MACrC;AAEA,cAAQ;AAAA,QACN,2BAA2B,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACnE;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ;AAAA,UACN,iCAAiC,MAAM,IAAI,GAAG,MAAM,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QAC5F;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,gCAAgC,MAAM,IAAI,GAAG,IAAI,KAAK;AACpE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,QACJ,SACA,SAC0B;AAC1B,QAAI;AACF,YAAM,kBAAkB,QAAQ,aAAa,KAAK;AAClD,YAAM,iBAAiB;AAAA,QACrB;AAAA,QACA,WAAW;AAAA,QACX,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,MACf;AAEA,YAAM,WAAW,MAAM,KAAK,QAAQ,gBAAgB;AAAA,QAClD,MAAM,KAAK,UAAU,cAAc;AAAA,QACnC,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAwB,MAAM,SAAS,KAAK;AAClD,cAAQ;AAAA,QACN,mCAAmC,OAAO,cAAc,KAAK,OAAO;AAAA,MACtE;AAGA,WAAK,QAAQ;AAAA,QACX,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,0CAA0C,KAAK;AAC7D,WAAK,QAAQ;AAAA,QACX,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACzC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,qBACJ,SACA,WACqC;AACrC,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,uBAAuB;AAAA,QACzD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,WAAW;AAAA,QACb,CAAC;AAAA,QACD,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,MAAM;AAClB,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AAEA,cAAQ,IAAI,yCAAyC,OAAO,EAAE;AAE9D,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,cAAQ,MAAM,0CAA0C,KAAK;AAC7D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,YACJ,SACA,SAAiB,QACjB,WACA,WAC8B;AAC9B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,qBAAqB;AAAA,QACvD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX;AAAA,QACF,CAAuB;AAAA,QACvB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA4B,MAAM,SAAS,KAAK;AACtD,cAAQ;AAAA,QACN,yCAAyC,OAAO,cAAc,KAAK,OAAO,aAAa,KAAK,SAAS;AAAA,MACvG;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,MACJ,MACA,YAAqB,OACrB,WACwB;AACxB,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,cAAc;AAAA,QAChD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAiB;AAAA,QACjB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAsB,MAAM,SAAS,KAAK;AAChD,cAAQ;AAAA,QACN,oCAAoC,IAAI,cAAc,KAAK,OAAO,gBAAgB,KAAK,SAAS;AAAA,MAClG;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,2CAA2C,KAAK;AAC9D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,UACJ,MACA,SACA,WAAmB,SACnB,WAC4B;AAC5B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,cAAc;AAAA,QAChD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAqB;AAAA,QACrB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA0B,MAAM,SAAS,KAAK;AACpD,cAAQ;AAAA,QACN,+BAA+B,IAAI,cAAc,KAAK,OAAO;AAAA,MAC/D;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,qCAAqC,KAAK;AACxD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,MACA,WAAmB,SACnB,WAC2B;AAC3B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC/C,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAoB;AAAA,QACpB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAyB,MAAM,SAAS,KAAK;AACnD,cAAQ;AAAA,QACN,4BAA4B,IAAI,cAAc,KAAK,OAAO,qBAAqB,KAAK,QAAQ,MAAM;AAAA,MACpG;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,qCAAqC,KAAK;AACxD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,MACA,WAC6B;AAC7B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,eAAe;AAAA,QACjD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,WAAW;AAAA,QACb,CAAsB;AAAA,QACtB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA2B,MAAM,SAAS,KAAK;AACrD,cAAQ;AAAA,QACN,+BAA+B,IAAI,cAAc,KAAK,OAAO;AAAA,MAC/D;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,SACA,SACA,WAC6B;AAC7B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,eAAe;AAAA,QACjD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAsB;AAAA,QACtB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA2B,MAAM,SAAS,KAAK;AACrD,cAAQ;AAAA,QACN,+BAA+B,OAAO,OAAO,OAAO,cAAc,KAAK,OAAO;AAAA,MAChF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,YACA,iBACA,WAC2B;AAC3B,QAAI;AACF,YAAM,kBAAkB,aAAa,KAAK;AAE1C,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC/C,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,WAAW;AAAA,UACX;AAAA,QACF,CAAoB;AAAA,QACpB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAyB,MAAM,SAAS,KAAK;AACnD,cAAQ;AAAA,QACN,6BAA6B,UAAU,OAAO,eAAe,cAAc,KAAK,OAAO;AAAA,MACzF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,MAAc,MAA4C;AACzE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,oBAAoB;AAAA,QACtD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,gBAAQ,IAAI,SAAS;AACrB,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA2B,MAAM,SAAS,KAAK;AACrD,cAAQ;AAAA,QACN,+BAA+B,IAAI,GACjC,OAAO,KAAK,IAAI,MAAM,EACxB,cAAc,KAAK,OAAO;AAAA,MAC5B;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,MAA6C;AAC9D,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,sBAAsB;AAAA,QACxD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,QACF,CAAC;AAAA,QACD,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA6B,MAAM,SAAS,KAAK;AACvD,cAAQ;AAAA,QACN,iCAAiC,IAAI,cAAc,KAAK,OAAO;AAAA,MACjE;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,kBAAoD;AACxD,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,sBAAsB;AAAA,QACxD,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAgC,MAAM,SAAS,KAAK;AAC1D,cAAQ,IAAI,qBAAqB,KAAK,KAAK,gBAAgB;AAE3D,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,8CAA8C,KAAK;AACjE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAwB;AAC5B,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC/C,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,EAAE;AAAA,MAC1D;AAEA,YAAM,OAAqB,MAAM,SAAS,KAAK;AAC/C,cAAQ,IAAI,gCAAgC,KAAK,OAAO,EAAE;AAC1D,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,cAAQ,MAAM,uCAAuC,KAAK;AAC1D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,cAAiC;AACrC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,iBAAiB;AAAA,QAC3D,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,EAAE;AAAA,MAC1D;AAEA,YAAM,OAAyB,MAAM,SAAS,KAAK;AACnD,cAAQ;AAAA,QACN,qCAAqC,KAAK,kBAAkB,MAAM;AAAA,MACpE;AACA,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAyC,KAAK;AAC5D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,eAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAa,WAAyB;AACpC,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,eAAqB;AACnB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA,EAGA,MAAM,aACJ,SACA,SAS+B;AAC/B,QAAI;AACF,YAAM,kBAAkB,SAAS,aAAa,KAAK;AAEnD,YAAM,WAAW,MAAM,KAAK,QAAQ,sBAAsB;AAAA,QACxD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,SAAS;AAAA,YACP,GAAG;AAAA,YACH,WAAW;AAAA,UACb;AAAA,QACF,CAAwB;AAAA,QACxB,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA6B,MAAM,SAAS,KAAK;AACvD,cAAQ;AAAA,QACN,kCAAkC,OAAO,SAAS,KAAK,QAAQ,EAAE;AAAA,MACnE;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAyC,KAAK;AAC5D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgD;AACpD,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,qBAAqB;AAAA,QACvD,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA8B,MAAM,SAAS,KAAK;AACxD,cAAQ,IAAI,wBAAwB,KAAK,UAAU,MAAM,YAAY;AAErE,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,0CAA0C,KAAK;AAC7D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,WAAgD;AAC/D,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,gBAAgB,SAAS,IAAI;AAAA,QAC/D,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA2B,MAAM,SAAS,KAAK;AACrD,cAAQ;AAAA,QACN,6BAA6B,SAAS,KACpC,KAAK,SAAS,UAAU,WAC1B;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,YACJ,WACgD;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,gBAAgB,SAAS,IAAI;AAAA,QAC/D,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAIlC,cAAQ,IAAI,gCAAgC,SAAS,EAAE;AAEvD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,mBAIH;AACD,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,yBAAyB;AAAA,QAC3D,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAKlC,cAAQ,IAAI,wBAAwB,KAAK,WAAW,YAAY;AAEhE,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,8CAA8C,KAAK;AACjE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,WAAoD;AACvE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,gBAAgB,SAAS,SAAS;AAAA,QACpE,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,OAA+B,MAAM,SAAS,KAAK;AACzD,cAAQ,IAAI,sCAAsC,SAAS,EAAE;AAE7D,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,6CAA6C,KAAK;AAChE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,kBACJ,WACqC;AACrC,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,gBAAgB,SAAS,WAAW;AAAA,QACtE,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,iBAAiB;AAAA,QACnB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAa,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGzD,cAAM,IAAI;AAAA,UACR,UAAU,SAAS,uBAAuB,SAAS,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,MAAM;AAClB,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AAEA,cAAQ;AAAA,QACN,oDAAoD,SAAS;AAAA,MAC/D;AAEA,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,cAAQ,MAAM,+CAA+C,KAAK;AAClE,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// src/interpreter-types.ts
|
|
2
|
+
var Execution = class {
|
|
3
|
+
constructor(code, context) {
|
|
4
|
+
this.code = code;
|
|
5
|
+
this.context = context;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* All results from the execution
|
|
9
|
+
*/
|
|
10
|
+
results = [];
|
|
11
|
+
/**
|
|
12
|
+
* Accumulated stdout and stderr
|
|
13
|
+
*/
|
|
14
|
+
logs = {
|
|
15
|
+
stdout: [],
|
|
16
|
+
stderr: []
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Execution error if any
|
|
20
|
+
*/
|
|
21
|
+
error;
|
|
22
|
+
/**
|
|
23
|
+
* Execution count (for Jupyter)
|
|
24
|
+
*/
|
|
25
|
+
executionCount;
|
|
26
|
+
/**
|
|
27
|
+
* Convert to a plain object for serialization
|
|
28
|
+
*/
|
|
29
|
+
toJSON() {
|
|
30
|
+
return {
|
|
31
|
+
code: this.code,
|
|
32
|
+
logs: this.logs,
|
|
33
|
+
error: this.error,
|
|
34
|
+
executionCount: this.executionCount,
|
|
35
|
+
results: this.results.map((result) => ({
|
|
36
|
+
text: result.text,
|
|
37
|
+
html: result.html,
|
|
38
|
+
png: result.png,
|
|
39
|
+
jpeg: result.jpeg,
|
|
40
|
+
svg: result.svg,
|
|
41
|
+
latex: result.latex,
|
|
42
|
+
markdown: result.markdown,
|
|
43
|
+
javascript: result.javascript,
|
|
44
|
+
json: result.json,
|
|
45
|
+
chart: result.chart,
|
|
46
|
+
data: result.data
|
|
47
|
+
}))
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var ResultImpl = class {
|
|
52
|
+
constructor(raw) {
|
|
53
|
+
this.raw = raw;
|
|
54
|
+
}
|
|
55
|
+
get text() {
|
|
56
|
+
return this.raw.text || this.raw.data?.["text/plain"];
|
|
57
|
+
}
|
|
58
|
+
get html() {
|
|
59
|
+
return this.raw.html || this.raw.data?.["text/html"];
|
|
60
|
+
}
|
|
61
|
+
get png() {
|
|
62
|
+
return this.raw.png || this.raw.data?.["image/png"];
|
|
63
|
+
}
|
|
64
|
+
get jpeg() {
|
|
65
|
+
return this.raw.jpeg || this.raw.data?.["image/jpeg"];
|
|
66
|
+
}
|
|
67
|
+
get svg() {
|
|
68
|
+
return this.raw.svg || this.raw.data?.["image/svg+xml"];
|
|
69
|
+
}
|
|
70
|
+
get latex() {
|
|
71
|
+
return this.raw.latex || this.raw.data?.["text/latex"];
|
|
72
|
+
}
|
|
73
|
+
get markdown() {
|
|
74
|
+
return this.raw.markdown || this.raw.data?.["text/markdown"];
|
|
75
|
+
}
|
|
76
|
+
get javascript() {
|
|
77
|
+
return this.raw.javascript || this.raw.data?.["application/javascript"];
|
|
78
|
+
}
|
|
79
|
+
get json() {
|
|
80
|
+
return this.raw.json || this.raw.data?.["application/json"];
|
|
81
|
+
}
|
|
82
|
+
get chart() {
|
|
83
|
+
return this.raw.chart;
|
|
84
|
+
}
|
|
85
|
+
get data() {
|
|
86
|
+
return this.raw.data;
|
|
87
|
+
}
|
|
88
|
+
formats() {
|
|
89
|
+
const formats = [];
|
|
90
|
+
if (this.text) formats.push("text");
|
|
91
|
+
if (this.html) formats.push("html");
|
|
92
|
+
if (this.png) formats.push("png");
|
|
93
|
+
if (this.jpeg) formats.push("jpeg");
|
|
94
|
+
if (this.svg) formats.push("svg");
|
|
95
|
+
if (this.latex) formats.push("latex");
|
|
96
|
+
if (this.markdown) formats.push("markdown");
|
|
97
|
+
if (this.javascript) formats.push("javascript");
|
|
98
|
+
if (this.json) formats.push("json");
|
|
99
|
+
if (this.chart) formats.push("chart");
|
|
100
|
+
return formats;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export {
|
|
105
|
+
Execution,
|
|
106
|
+
ResultImpl
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=chunk-EGC5IYXA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/interpreter-types.ts"],"sourcesContent":["// Context Management\nexport interface CreateContextOptions {\n /**\n * Programming language for the context\n * @default 'python'\n */\n language?: 'python' | 'javascript' | 'typescript';\n \n /**\n * Working directory for the context\n * @default '/workspace'\n */\n cwd?: string;\n \n /**\n * Environment variables for the context\n */\n envVars?: Record<string, string>;\n \n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n}\n\nexport interface CodeContext {\n /**\n * Unique identifier for the context\n */\n readonly id: string;\n \n /**\n * Programming language of the context\n */\n readonly language: string;\n \n /**\n * Current working directory\n */\n readonly cwd: string;\n \n /**\n * When the context was created\n */\n readonly createdAt: Date;\n \n /**\n * When the context was last used\n */\n readonly lastUsed: Date;\n}\n\n// Execution Options\nexport interface RunCodeOptions {\n /**\n * Context to run the code in. If not provided, uses default context for the language\n */\n context?: CodeContext;\n \n /**\n * Language to use if context is not provided\n * @default 'python'\n */\n language?: 'python' | 'javascript' | 'typescript';\n \n /**\n * Environment variables for this execution\n */\n envVars?: Record<string, string>;\n \n /**\n * Execution timeout in milliseconds\n * @default 60000\n */\n timeout?: number;\n \n /**\n * AbortSignal for cancelling execution\n */\n signal?: AbortSignal;\n \n /**\n * Callback for stdout output\n */\n onStdout?: (output: OutputMessage) => void | Promise<void>;\n \n /**\n * Callback for stderr output\n */\n onStderr?: (output: OutputMessage) => void | Promise<void>;\n \n /**\n * Callback for execution results (charts, tables, etc)\n */\n onResult?: (result: Result) => void | Promise<void>;\n \n /**\n * Callback for execution errors\n */\n onError?: (error: ExecutionError) => void | Promise<void>;\n}\n\n// Output Messages\nexport interface OutputMessage {\n /**\n * The output text\n */\n text: string;\n \n /**\n * Timestamp of the output\n */\n timestamp: number;\n}\n\n// Execution Results\nexport interface Result {\n /**\n * Plain text representation\n */\n text?: string;\n \n /**\n * HTML representation (tables, formatted output)\n */\n html?: string;\n \n /**\n * PNG image data (base64 encoded)\n */\n png?: string;\n \n /**\n * JPEG image data (base64 encoded)\n */\n jpeg?: string;\n \n /**\n * SVG image data\n */\n svg?: string;\n \n /**\n * LaTeX representation\n */\n latex?: string;\n \n /**\n * Markdown representation\n */\n markdown?: string;\n \n /**\n * JavaScript code to execute\n */\n javascript?: string;\n \n /**\n * JSON data\n */\n json?: any;\n \n /**\n * Chart data if the result is a visualization\n */\n chart?: ChartData;\n \n /**\n * Raw data object\n */\n data?: any;\n \n /**\n * Available output formats\n */\n formats(): string[];\n}\n\n// Chart Data\nexport interface ChartData {\n /**\n * Type of chart\n */\n type: 'line' | 'bar' | 'scatter' | 'pie' | 'histogram' | 'heatmap' | 'unknown';\n \n /**\n * Chart title\n */\n title?: string;\n \n /**\n * Chart data (format depends on library)\n */\n data: any;\n \n /**\n * Chart layout/configuration\n */\n layout?: any;\n \n /**\n * Additional configuration\n */\n config?: any;\n \n /**\n * Library that generated the chart\n */\n library?: 'matplotlib' | 'plotly' | 'altair' | 'seaborn' | 'unknown';\n \n /**\n * Base64 encoded image if available\n */\n image?: string;\n}\n\n// Execution Error\nexport interface ExecutionError {\n /**\n * Error name/type (e.g., 'NameError', 'SyntaxError')\n */\n name: string;\n \n /**\n * Error message\n */\n value: string;\n \n /**\n * Stack trace\n */\n traceback: string[];\n \n /**\n * Line number where error occurred\n */\n lineNumber?: number;\n}\n\n// Serializable execution result\nexport interface ExecutionResult {\n code: string;\n logs: {\n stdout: string[];\n stderr: string[];\n };\n error?: ExecutionError;\n executionCount?: number;\n results: Array<{\n text?: string;\n html?: string;\n png?: string;\n jpeg?: string;\n svg?: string;\n latex?: string;\n markdown?: string;\n javascript?: string;\n json?: any;\n chart?: ChartData;\n data?: any;\n }>;\n}\n\n// Execution Result Container\nexport class Execution {\n /**\n * All results from the execution\n */\n public results: Result[] = [];\n \n /**\n * Accumulated stdout and stderr\n */\n public logs = {\n stdout: [] as string[],\n stderr: [] as string[]\n };\n \n /**\n * Execution error if any\n */\n public error?: ExecutionError;\n \n /**\n * Execution count (for Jupyter)\n */\n public executionCount?: number;\n \n constructor(\n public readonly code: string,\n public readonly context: CodeContext\n ) {}\n \n /**\n * Convert to a plain object for serialization\n */\n toJSON(): ExecutionResult {\n return {\n code: this.code,\n logs: this.logs,\n error: this.error,\n executionCount: this.executionCount,\n results: this.results.map(result => ({\n text: result.text,\n html: result.html,\n png: result.png,\n jpeg: result.jpeg,\n svg: result.svg,\n latex: result.latex,\n markdown: result.markdown,\n javascript: result.javascript,\n json: result.json,\n chart: result.chart,\n data: result.data\n }))\n };\n }\n}\n\n// Implementation of Result\nexport class ResultImpl implements Result {\n constructor(private raw: any) {}\n \n get text(): string | undefined { \n return this.raw.text || this.raw.data?.['text/plain']; \n }\n \n get html(): string | undefined { \n return this.raw.html || this.raw.data?.['text/html']; \n }\n \n get png(): string | undefined { \n return this.raw.png || this.raw.data?.['image/png']; \n }\n \n get jpeg(): string | undefined { \n return this.raw.jpeg || this.raw.data?.['image/jpeg']; \n }\n \n get svg(): string | undefined { \n return this.raw.svg || this.raw.data?.['image/svg+xml']; \n }\n \n get latex(): string | undefined { \n return this.raw.latex || this.raw.data?.['text/latex']; \n }\n \n get markdown(): string | undefined { \n return this.raw.markdown || this.raw.data?.['text/markdown']; \n }\n \n get javascript(): string | undefined { \n return this.raw.javascript || this.raw.data?.['application/javascript']; \n }\n \n get json(): any { \n return this.raw.json || this.raw.data?.['application/json']; \n }\n \n get chart(): ChartData | undefined { \n return this.raw.chart; \n }\n \n get data(): any { \n return this.raw.data; \n }\n \n formats(): string[] {\n const formats: string[] = [];\n if (this.text) formats.push('text');\n if (this.html) formats.push('html');\n if (this.png) formats.push('png');\n if (this.jpeg) formats.push('jpeg');\n if (this.svg) formats.push('svg');\n if (this.latex) formats.push('latex');\n if (this.markdown) formats.push('markdown');\n if (this.javascript) formats.push('javascript');\n if (this.json) formats.push('json');\n if (this.chart) formats.push('chart');\n return formats;\n }\n}"],"mappings":";AAyQO,IAAM,YAAN,MAAgB;AAAA,EAwBrB,YACkB,MACA,SAChB;AAFgB;AACA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAvBI,UAAoB,CAAC;AAAA;AAAA;AAAA;AAAA,EAKrB,OAAO;AAAA,IACZ,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKO;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAUP,SAA0B;AACxB,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,gBAAgB,KAAK;AAAA,MACrB,SAAS,KAAK,QAAQ,IAAI,aAAW;AAAA,QACnC,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,KAAK,OAAO;AAAA,QACZ,MAAM,OAAO;AAAA,QACb,KAAK,OAAO;AAAA,QACZ,OAAO,OAAO;AAAA,QACd,UAAU,OAAO;AAAA,QACjB,YAAY,OAAO;AAAA,QACnB,MAAM,OAAO;AAAA,QACb,OAAO,OAAO;AAAA,QACd,MAAM,OAAO;AAAA,MACf,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AAGO,IAAM,aAAN,MAAmC;AAAA,EACxC,YAAoB,KAAU;AAAV;AAAA,EAAW;AAAA,EAE/B,IAAI,OAA2B;AAC7B,WAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,OAAO,YAAY;AAAA,EACtD;AAAA,EAEA,IAAI,OAA2B;AAC7B,WAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,OAAO,WAAW;AAAA,EACrD;AAAA,EAEA,IAAI,MAA0B;AAC5B,WAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,WAAW;AAAA,EACpD;AAAA,EAEA,IAAI,OAA2B;AAC7B,WAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,OAAO,YAAY;AAAA,EACtD;AAAA,EAEA,IAAI,MAA0B;AAC5B,WAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,eAAe;AAAA,EACxD;AAAA,EAEA,IAAI,QAA4B;AAC9B,WAAO,KAAK,IAAI,SAAS,KAAK,IAAI,OAAO,YAAY;AAAA,EACvD;AAAA,EAEA,IAAI,WAA+B;AACjC,WAAO,KAAK,IAAI,YAAY,KAAK,IAAI,OAAO,eAAe;AAAA,EAC7D;AAAA,EAEA,IAAI,aAAiC;AACnC,WAAO,KAAK,IAAI,cAAc,KAAK,IAAI,OAAO,wBAAwB;AAAA,EACxE;AAAA,EAEA,IAAI,OAAY;AACd,WAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,OAAO,kBAAkB;AAAA,EAC5D;AAAA,EAEA,IAAI,QAA+B;AACjC,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,IAAI,OAAY;AACd,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,UAAoB;AAClB,UAAM,UAAoB,CAAC;AAC3B,QAAI,KAAK,KAAM,SAAQ,KAAK,MAAM;AAClC,QAAI,KAAK,KAAM,SAAQ,KAAK,MAAM;AAClC,QAAI,KAAK,IAAK,SAAQ,KAAK,KAAK;AAChC,QAAI,KAAK,KAAM,SAAQ,KAAK,MAAM;AAClC,QAAI,KAAK,IAAK,SAAQ,KAAK,KAAK;AAChC,QAAI,KAAK,MAAO,SAAQ,KAAK,OAAO;AACpC,QAAI,KAAK,SAAU,SAAQ,KAAK,UAAU;AAC1C,QAAI,KAAK,WAAY,SAAQ,KAAK,YAAY;AAC9C,QAAI,KAAK,KAAM,SAAQ,KAAK,MAAM;AAClC,QAAI,KAAK,MAAO,SAAQ,KAAK,OAAO;AACpC,WAAO;AAAA,EACT;AACF;","names":[]}
|