Перейти к основному содержимому

HTTP API

Оба приложения — FastAPI на localhost, каждое говорит только со своей SPA. Общего сервера и межприложенческого API нет: генератор и раннер связаны форматом пака.

Раннер студента​

Порт 8766.

Практика и задания​

МетодПутьОтдаёт
GET/api/packописание базы, DDL, таблицы, число заданий, сколько решено
GET/api/tasksзадания с формулировками, темами, сложностью, открытыми примерами, статусом и текущим решением

GET /api/tasks отдаёт и public_checks — открытые проверки задания. Скрытые в ответ не попадают.

Вместе с формулировками едет контракт результата: result (columns, ordered, cardinality, numeric_precision), state_tables, require_constructs, forbid_constructs. Это часть условия, а не закрытые данные: без состава колонок и признака порядка задание нерешаемо.

Работа с базой​

МетодПутьДелает
POST/api/queryвыполняет SQL в живой базе, возвращает колонки, строки и время
POST/api/load_exampleналивает в живую базу открытый вариант данных
POST/api/resetвозвращает живую базу к пустой схеме

Проверка​

МетодПутьДелает
POST/api/tasks/{id}/checkпрогоняет решение по всем вариантам в проверочной базе, сохраняет solutions/<id>.sql
GET/api/tasks/{id}/variant/{variant}данные варианта и ожидаемый результат
POST/api/tasks/{id}/variant/{variant}то же плюс результат решения студента на этих данных — для построчного сравнения

Каждая запись в failures ответа check несёт машинный диагноз: code (row_order, columns_mismatch, cardinality, rows_differ, exec_error, constructs, …) и details с числами — сколько строк ожидалось и получено, с какой позиции разошёлся порядок, каких колонок не хватает. Английский diagnostic остаётся для отчёта автора и CI; текст для студента интерфейс собирает из code и details, а не разбирает прозу.

Правило закрытых данных

Эти два эндпоинта отдают ожидаемый результат только для открытых примеров и для вариантов, на которых решение студента уже упало. Всё остальное остаётся в закрытой части пака и наружу не уходит.

Черновики​

МетодПутьДелает
GET POST/api/history/{id}история запросов по заданию; кольцо из ста записей
GET PUT/api/bookmarksзакладки

Хранятся в solutions/.history/, который раннер дописывает в solutions/.gitignore: черновики не попадают в сдачу.

Оформление​

МетодПутьОтдаёт
GET/api/themeразобранную тему: brand, scheme, fonts, tokens, hasCss
GET/theme/theme.cssсодержимое theme.css как есть
GET/theme/assets/{path}файлы темы; расширения по белому списку

Значения токенов подставляются в <head> при отдаче index.html, поэтому приложение стартует уже в цветах курса. Параметр ?theme=off отключает тему.

Заголовки​

Content-Security-Policy: default-src 'self'; img-src 'self' data:; font-src 'self';
style-src 'self' 'unsafe-inline'; script-src 'self'
X-Content-Type-Options: nosniff

unsafe-inline для стилей необходим: редактор кода вставляет свои <style> в рантайме, и токены темы приходят инлайн-блоком. Внешние запросы при этом запрещены — образ автономен.

Студия автора​

Порт 8765. Доступна только с локального адреса.

МетодПутьДелает
GET/api/practiceсостояние всех шагов и хэши
GET/api/catalogкаталог предметных областей и тем SQL для форм
GET POST/api/brief, /api/brief/generate, /api/brief/applyшаг 0: разбор лекции и перенос в форму шага 1
GET POST/api/domain, /api/domain/generate, /api/domain/approveшаг 1
GET POST/api/tasks, /api/tasks/generate, /api/tasks/approveшаг 2
POST/api/materialize?task_id=…шаг 3 для одного задания; итог сливается в report/outcomes.json, итоги остальных заданий сохраняются. Без task_id — все задания разом, отчёт пишется заново
GET/api/outcomesрезультаты прогона: статусы, материализации, матрица негативов
GET/api/tasks/{id}/variant/{variant}данные любого варианта, включая скрытые

Ручной режим — параллельная пара эндпоинтов у каждого шага: /prompt отдаёт готовый промт, /manual принимает ответ модели и валидирует его так же, как ответ API. У шага 0 /api/brief/prompt — POST, а не GET: текст лекции в query-строку не помещается. Лекция длиннее 60 000 знаков отклоняется с 400 — усечения нет.

Ответ нейросети не той формы​

Если JSON от модели не прошёл проверку формы — на генерации после одного повтора, в ручном режиме сразу, — эндпоинт отвечает 422 с телом:

{
"detail": "ответ нейросети не прошёл проверку формы: …",
"errors": [
"`dataspec.class_columns[0]`: нужен объект {table, column, values}, получено: строка `\"shops.city\"`"
],
"fix_request": "Твой JSON не прошёл проверку формы:\n- …\n\nПришли исправленный JSON целиком…"
}

detail — сводная строка для любого клиента. errors — по одной ошибке на поле, в обратных кавычках пути и значения. fix_request — готовое сообщение для нейросети; тот же текст студия отправляет модели при повторе. Прочие 422 (пустая лекция, не выбраны темы) приходят с одним detail.

Прогон одного задания на шаге 3 не отвечает 422 на ошибку формы: такое задание получает статус bad_response в outcomes.json, а очередь в UI идёт дальше.

Студии автора закрытых данных не существует: она показывает всё содержимое пака, включая скрытые проверки и ожидаемые результаты всех вариантов.