Компилятор¶
Запуск кода учеников: Python, JavaScript и C++.
Пользователь передаёт токен из раздела «Авторизация», ученик без учётной записи работает гостем.
Встроенный демо-вход POST {COMPILER_URL}/v1/auth/login в «Корифее» выключен и отвечает 404.
Объект «Проект»¶
| Параметр | Тип | Описание |
|---|---|---|
id* |
string | id проекта |
user_id* |
string | Владелец |
title* |
string | Название, до 255 символов |
language* |
string | python, javascript или cpp |
code* |
string | Код |
stdin* |
string | Ввод для запуска |
created_at* |
datetime | Когда создан |
updated_at* |
datetime | Когда изменён |
Гостевая сессия¶
Открывает гостевую сессию: ставит cookie wonk_compiler_guest, с которой гость запускает код.
Запрос: POST {COMPILER_URL}/v1/auth/guest-session, без тела.
Cookie HttpOnly, Secure, SameSite=Lax: гостевой режим работает по HTTPS, когда клиент и компилятор на одном сайте, например app.korifei.kz и api.korifei.kz, и с запросами credentials: "include".
У гостя свои, более строгие лимиты и нет проектов.
Ответ 200:
{"principal_id": "guest:5f0c...", "expires_in_seconds": 3600}
Языки¶
Возвращает доступные языки.
Запрос: GET {COMPILER_URL}/v1/languages, авторизация не нужна.
Ответ 200:
| Параметр | Тип | Описание |
|---|---|---|
languages[].key* |
string | python, javascript, cpp |
languages[].label* |
string | Название для интерфейса |
languages[].enabled* |
boolean | Доступен ли язык |
languages[].default_version* |
string | Версия |
languages[].starter_code |
string | Код для пустого редактора |
languages[].debug |
boolean | Доступна отладка |
languages[].trace |
boolean | Доступна трассировка |
{"languages": [{"key": "python", "label": "Python", "enabled": true, "default_version": "3.12.0", "starter_code": "print(\"Hello, Wonk!\")\n", "debug": true, "trace": true}]}
Запуск кода¶
Выполняет программу с заданным вводом и возвращает результат после её завершения.
Запрос: POST {COMPILER_URL}/v1/run, авторизация - токен или гостевая cookie.
| Параметр | Тип | Описание |
|---|---|---|
language* |
string | Язык |
code* |
string | Код, до 64 КБ |
stdin |
string | Ввод, до 16 КБ |
{"language": "python", "code": "print(sum(range(10)))", "stdin": ""}
Ответ 200:
| Параметр | Тип | Описание |
|---|---|---|
status* |
string | Статус запуска (раздел «Статусы и коды») |
language* |
string | Язык |
stdout |
string | Вывод программы |
stderr |
string | Ошибки программы и компилятора |
exit_code |
integer | Код завершения |
execution_time_ms |
integer | Время выполнения, мс |
memory_kb |
integer | Память, КБ |
message |
string | Причина validation_error для пользователя |
{"status": "success", "language": "python", "stdout": "45\n", "stderr": "", "exit_code": 0, "execution_time_ms": 41, "memory_kb": 8120, "message": null}
| Код ошибки | Когда |
|---|---|
401 |
Нет ни токена, ни гостевой cookie |
429 |
Песочница занята; заголовок Retry-After |
503 |
Песочница выключена или недоступна |
Последний код¶
Возвращает последний сохранённый код пользователя по языку.
Запрос: GET {COMPILER_URL}/v1/last-code?language=python, авторизация - токен.
Ответ 200:
{"language": "python", "code": "print(1)", "updated_at": "2026-11-10T10:00:00Z"}
code и updated_at - null, если код ещё не сохраняли.
Сохранение последнего кода¶
Сохраняет последний код пользователя по языку.
Запрос: PUT {COMPILER_URL}/v1/last-code, авторизация - токен.
| Параметр | Тип | Описание |
|---|---|---|
language* |
string | Язык |
code* |
string | Код |
Ответ 200:
{"success": true}
| Код ошибки | Когда |
|---|---|
400 |
Язык недоступен или код слишком большой |
Профиль¶
Возвращает профиль пользователя в компиляторе; создаётся при первом обращении, имя берётся из токена.
Запрос: GET {COMPILER_URL}/v1/me, авторизация - токен.
Ответ 200:
| Параметр | Тип | Описание |
|---|---|---|
id* |
string | id пользователя |
first_name*, last_name* |
string | Имя и фамилия |
role |
string | Роль из токена |
profile_id |
string | profile_id из токена |
is_demo |
boolean | Всегда false |
created_at*, updated_at* |
datetime | Когда создан и изменён |
Профиль пользователя¶
Возвращает профиль другого пользователя, если он уже открывал компилятор.
Запрос: GET {COMPILER_URL}/v1/users/{user_id}, авторизация - токен teacher или school_admin.
Ответ 200: как у метода «Профиль».
| Код ошибки | Когда |
|---|---|
403 |
Роль не учитель и не директор |
404 |
Пользователь ещё не открывал компилятор |
Список проектов¶
Возвращает проекты пользователя без кода.
Запрос: GET {COMPILER_URL}/v1/projects, авторизация - токен.
Ответ 200:
{"projects": [{"id": "3d9f...", "title": "Задача 1", "language": "python", "created_at": "2026-11-10T10:00:00Z", "updated_at": "2026-11-10T10:05:00Z"}]}
Создание проекта¶
Создаёт проект пользователя.
Запрос: POST {COMPILER_URL}/v1/projects, авторизация - токен.
| Параметр | Тип | Описание |
|---|---|---|
title |
string | Название, до 255 символов; без него - «Untitled project» |
language* |
string | Язык |
code |
string | Код |
stdin |
string | Ввод |
{"title": "Задача 1", "language": "python", "code": "print(1)"}
Ответ 201: объект «Проект».
| Код ошибки | Когда |
|---|---|
400 |
Язык недоступен или код слишком большой |
Проект¶
Возвращает проект с кодом.
Запрос: GET {COMPILER_URL}/v1/projects/{project_id}, авторизация - токен.
Ответ 200: объект «Проект».
| Код ошибки | Когда |
|---|---|
404 |
Проекта нет или он чужой |
Изменение проекта¶
Меняет переданные поля проекта.
Запрос: PUT {COMPILER_URL}/v1/projects/{project_id}, авторизация - токен.
| Параметр | Тип | Описание |
|---|---|---|
title |
string | Название |
language |
string | Язык |
code |
string | Код |
stdin |
string | Ввод |
Ответ 200: объект «Проект».
| Код ошибки | Когда |
|---|---|
400 |
Язык недоступен или код слишком большой |
404 |
Проекта нет или он чужой |
Удаление проекта¶
Удаляет проект.
Запрос: DELETE {COMPILER_URL}/v1/projects/{project_id}, авторизация - токен.
Ответ 204 без тела.
| Код ошибки | Когда |
|---|---|
404 |
Проекта нет или он чужой |
Интерактивная сессия¶
WebSocket для запуска с вводом по ходу программы (input(), cin, scanf): вывод приходит по мере работы.
Один сокет - один запуск.
Сессия ограничена по времени: по умолчанию 120 секунд на запуск и 60 секунд без ввода и вывода, под отладчиком - 900 и 300; по истечении придёт status: timeout.
Одновременно у пользователя до 3 сессий, у гостя - одна.
Подключение: WS {COMPILER_URL}/v1/interactive/session?token={токен}; гость - без token, с гостевой cookie.
Сообщения клиента:
type |
Поля | Описание |
|---|---|---|
start* |
language*, code*, debug, breakpoints, trace |
Первое сообщение: запуск программы |
stdin |
data* |
Ввод в программу |
stop |
Остановить программу | |
dap |
payload* |
Команда отладчика, только при debug: true |
Сообщения сервера:
type |
Поля | Описание |
|---|---|---|
status |
status |
starting, running, finished, timeout, stopped или error |
stdout |
data |
Вывод программы; stdout и stderr программы приходят одним потоком |
stderr |
data |
Служебные сообщения |
exit |
exit_code |
Программа завершилась |
error |
message |
Ошибка: нет авторизации, язык недоступен, пустой или слишком большой код, сторонняя библиотека, нет свободных мест; после неё сервер закрывает сокет |
dap |
payload |
Ответ или событие отладчика |
trace |
truncated, steps |
Все шаги программы, при trace: true |
Нет авторизации (неверный токен, нет гостевой cookie) - кадр error после подключения, а не ответ 401.
{"type": "start", "language": "python", "code": "name = input()\nprint('hi', name)"}
{"type": "stdin", "data": "Ару\n"}
{"type": "stdout", "data": "hi Ару\r\n"}
Отладка¶
Запуск под отладчиком: точки останова, шаги, стек и переменные; только Python, доступность - флаг debug в «Языках».
Это та же «Интерактивная сессия»: ввод и вывод программы идут сообщениями stdin и stdout, команды отладчика - сообщениями dap по протоколу Debug Adapter Protocol (DAP).
Сообщение start:
| Параметр | Тип | Описание |
|---|---|---|
debug* |
boolean | true |
breakpoints |
array | Строки точек останова с 1: до 100 точек, строки 1-10000; без поля или [] программа остановится только на необработанном исключении |
{"type": "start", "language": "python", "code": "x = 41\nx += 1\nname = input(\"who: \")\nprint(\"hello\", name, x)", "debug": true, "breakpoints": [2]}
Сообщение dap: {"type": "dap", "payload": {...}} в обе стороны; payload - объект, а не строка.
Запрос клиента:
| Параметр | Тип | Описание |
|---|---|---|
seq* |
integer | Номер запроса, свой счёт с 1; номера от 1000000000 заняты сервером, запрос с таким номером сервер отбрасывает |
type* |
string | request |
command* |
string | Команда из таблицы ниже |
arguments |
object | Аргументы команды |
Ответ и событие сервера:
| Параметр | Тип | Описание |
|---|---|---|
type* |
string | response или event |
request_seq |
integer | У ответа: seq запроса |
success |
boolean | У ответа: выполнен ли запрос |
message |
string | У неуспешного ответа: причина |
command |
string | У ответа: команда запроса |
event |
string | У события: его вид |
body |
object | Данные ответа или события |
Порядок работы:
- Клиент шлёт
startсdebug: true, приходятstatus: startingиstatus: running. - Сервер сам подключает отладчик и ставит точки останова из
start; программа ждёт этого до первой строки, поэтому точки срабатывают всегда. Ответы и события подключения сервер пересылает клиенту: ответы сrequest_seqот 1000000000 и событияoutput,initialized,process,thread,debugpyWaitingForServerпропускайте. - Событие
stopped- программа на паузе: клиент запрашиваетstackTrace, затемscopes, затемvariables, по очереди, потому что каждому запросу нужен id из предыдущего ответа. continue,next,stepInилиstepOutпродолжают программу до следующей паузы.- Программа закончилась - приходят событие
terminated, затемstatusиexit; если программа ни разу не остановилась, это первые сообщения после подключения.exit- конец сессии: убирайте интерфейс отладки, даже еслиterminatedне пришёл.
Команды клиента:
command |
arguments |
Ответ |
|---|---|---|
stackTrace |
{threadId, startFrame, levels}, например {"threadId": 1, "startFrame": 0, "levels": 20} |
body.stackFrames[]: {id, name, line, source}, верхний кадр первый |
scopes |
{frameId} - id кадра |
body.scopes[]: {name, variablesReference}, первая область - локальные переменные |
variables |
{variablesReference} |
body.variables[]: {name, value, type, variablesReference}; у списка, словаря и объекта variablesReference больше 0, их содержимое отдаёт ещё один variables |
continue |
{threadId} |
Продолжить до следующей точки останова |
next |
{threadId} |
Шаг через строку |
stepIn |
{threadId} |
Шаг внутрь функции |
stepOut |
{threadId} |
Шаг из функции |
setBreakpoints |
{"source": {"path": "/session/main.py"}, "breakpoints": [{"line": 2}]} |
body.breakpoints[]: {verified, line}; запрос заменяет все точки, присылайте полный список |
evaluate |
{expression, frameId, "context": "hover"} |
body.result: значение выражения на паузе |
threadId берётся из события stopped.
initialize, attach, launch и configurationDone сервер отладчику не передаёт и отвечает на них success: false: подключение он делает сам.
События сервера:
event |
body |
Описание |
|---|---|---|
stopped |
{reason, threadId} |
Пауза; reason - breakpoint, step, exception или pause |
terminated |
Программа закончилась | |
output |
Служебный вывод отладчика; вывод программы приходит в stdout |
Ограничения:
- Сессия под отладчиком живёт до 900 секунд, без активности - до 300; активность - любое сообщение в любую сторону, в том числе запросы на паузе.
- Сообщение
dap- до 1 МБ, всего от отладчика за сессию - до 16 МБ. - Отладка занимает место интерактивной сессии: у пользователя их одновременно до 3.
Ошибки приходят сообщением error, после него сессия завершается:
message |
Когда |
|---|---|
Debugging is disabled. |
Отладка выключена |
Debugging is not available for this language yet. |
У языка нет отладки |
Invalid breakpoints. |
breakpoints - не список целых чисел, строка вне 1-10000 или точек больше 100 |
The debugger failed to start. |
Отладчик не подключился |
The debugger connection was lost. |
Связь с отладчиком оборвалась, а программа ещё работает |
The debug session produced too much data. |
Отладчик прислал больше 16 МБ |
Debug message rejected. |
Сообщение dap не удалось передать отладчику, например больше 1 МБ |
Пример, точка останова на строке 2:
→ {"type": "start", "language": "python", "code": "...", "debug": true, "breakpoints": [2]}
← {"type": "status", "status": "starting"}
← {"type": "status", "status": "running"}
← сообщения dap подключения - пропустить
← {"type": "dap", "payload": {"type": "event", "event": "stopped", "body": {"reason": "breakpoint", "threadId": 1}, ...}}
→ {"type": "dap", "payload": {"seq": 1, "type": "request", "command": "stackTrace", "arguments": {"threadId": 1, "startFrame": 0, "levels": 20}}}
← {"type": "dap", "payload": {"type": "response", "request_seq": 1, "success": true, "command": "stackTrace", "body": {"stackFrames": [{"id": ..., "name": "<module>", "line": 2, ...}]}, ...}}
→ scopes (seq 2) с id кадра, затем variables (seq 3) с variablesReference локальных переменных
← {"type": "dap", "payload": {"type": "response", "request_seq": 3, "success": true, "command": "variables", "body": {"variables": [{"name": "x", "value": "41", "type": "int", "variablesReference": 0}]}, ...}}
→ {"type": "dap", "payload": {"seq": 4, "type": "request", "command": "continue", "arguments": {"threadId": 1}}}
← {"type": "stdout", "data": "who: "}
→ {"type": "stdin", "data": "Ару\n"}
← {"type": "stdout", "data": "Ару\r\nhello Ару 42\r\n"}
← {"type": "dap", "payload": {"type": "event", "event": "terminated", ...}}
← {"type": "status", "status": "finished"}
← {"type": "exit", "exit_code": 0}
- После
terminatedне шлитеstop: итог сессии станетstoppedс кодом-1вместо настоящего. - Запрос, отправленный в момент завершения программы, может получить ответ
success: false; послеterminatedиexitтакие ответы пропускайте. - Редактор на время сессии лучше сделать только для чтения: точки останова привязаны к номерам строк.
- Какие точки останова сработают (
verified), покажет повторныйsetBreakpointsс тем же списком на паузе.
Трассировка¶
Сервер сам проходит программу по шагам и присылает все шаги одним сообщением; только Python, доступность - флаг trace в «Языках».
Пока идёт запись, вывод программы приходит сообщениями stdout, а input() ждёт ввода stdin, как в обычной сессии; сообщения dap от клиента игнорируются.
Сообщение start: {"type": "start", "language": "python", "code": "...", "trace": true}.
Сообщение сервера trace:
| Параметр | Тип | Описание |
|---|---|---|
truncated* |
boolean | Запись остановлена по лимиту, 300 шагов или 2 МБ, или оборвалась на сбое; программа при этом доходит до конца |
steps[].line* |
integer | Строка |
steps[].function* |
string | Функция |
steps[].event* |
string | line или exception (необработанное исключение, последний шаг) |
steps[].exception.description |
string | У шага exception: текст исключения |
steps[].frames[]* |
array | Стек сверху вниз, до 8 кадров: {name, line, locals} |
steps[].frames[].locals |
object | До 50 переменных: {"имя": {"value", "type"}}, значения обрезаны |
{"type": "trace", "truncated": false, "steps": [{"line": 2, "function": "double", "event": "line", "frames": [{"name": "double", "line": 2, "locals": {"n": {"value": "3", "type": "int"}}}]}]}
debug и trace в одной сессии не совмещаются.