Перейти к содержанию

Компилятор

Запуск кода учеников: 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 Данные ответа или события

Порядок работы:

  1. Клиент шлёт start с debug: true, приходят status: starting и status: running.
  2. Сервер сам подключает отладчик и ставит точки останова из start; программа ждёт этого до первой строки, поэтому точки срабатывают всегда. Ответы и события подключения сервер пересылает клиенту: ответы с request_seq от 1000000000 и события output, initialized, process, thread, debugpyWaitingForServer пропускайте.
  3. Событие stopped - программа на паузе: клиент запрашивает stackTrace, затем scopes, затем variables, по очереди, потому что каждому запросу нужен id из предыдущего ответа.
  4. continue, next, stepIn или stepOut продолжают программу до следующей паузы.
  5. Программа закончилась - приходят событие 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 в одной сессии не совмещаются.