Next.js 16, React 19, Monaco editor, Anthropic SDK, multi-provider AI, Wandbox Python execution, iframe HTML preview, SQLite auth + session persistence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
import type { ExecutionResult } from '@/types';
|
|
|
|
// Wandbox — free public code execution API, no auth required
|
|
// https://github.com/melpon/wandbox
|
|
const WANDBOX_API = 'https://wandbox.org/api/compile.json';
|
|
const TIMEOUT_MS = 15_000;
|
|
|
|
export async function executePython(code: string, stdin = ''): Promise<ExecutionResult> {
|
|
const controller = new AbortController();
|
|
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
|
|
try {
|
|
const res = await fetch(WANDBOX_API, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
signal: controller.signal,
|
|
body: JSON.stringify({
|
|
compiler: 'cpython-3.12.7',
|
|
code,
|
|
stdin,
|
|
}),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Execution service error: ${res.status}`);
|
|
}
|
|
|
|
const data = await res.json();
|
|
const exitCode = parseInt(data.status ?? '0', 10);
|
|
|
|
// Wandbox separates compiler errors from runtime errors
|
|
const stderr = [data.program_error, data.compiler_error]
|
|
.filter(Boolean)
|
|
.join('\n')
|
|
.trim();
|
|
|
|
return {
|
|
stdout: data.program_output ?? '',
|
|
stderr,
|
|
exitCode,
|
|
timedOut: !!data.signal,
|
|
};
|
|
} catch (err: unknown) {
|
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
return { stdout: '', stderr: '', exitCode: -1, timedOut: true, error: 'Execution timed out after 15 seconds.' };
|
|
}
|
|
return {
|
|
stdout: '',
|
|
stderr: '',
|
|
exitCode: -1,
|
|
timedOut: false,
|
|
error: err instanceof Error ? err.message : 'Unknown execution error',
|
|
};
|
|
} finally {
|
|
clearTimeout(timer);
|
|
}
|
|
}
|