Files
Bro_js_Agent/README.md
T
RomanKurlygin c02268a180 Initial commit: KFU Course Agent
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 00:16:45 +03:00

4.1 KiB
Raw Blame History

KFU Course Agent

Автоматизация домашних заданий курса KFU-26-1 на platform.brojs.ru: агент сам находит открытые задачи, пишет решение, публикует репозиторий и сдаёт работу.

Как это устроено

flowchart LR
  A[Журнал BroJS] --> B[Агент]
  B --> C[Gitea git.brojs.ru]
  B --> D[Ответ в журнал]
  D --> E[Проверка]
Этап Действие
1 Список незакрытых заданий через Journal MCP
2 Генерация Python-решения
3 Репозиторий git.brojs.ru/glevelll/task-<id>
4 Коммит через Gitea API
5 Ссылка в ответ + task_submit
6 При отклонении — клон, правки, повторная отправка

Требования

  • Python 3.11+
  • Ключи в .env (см. ниже)

Зависимости: deepagents, LangGraph, LangChain, OpenRouter (gpt-oss-20b:free), Gitea API, BroJS Journal MCP.

Быстрый старт

git clone https://github.com/Glevelll/brojs-agent.git
cd brojs-agent
pip install -r requirements.txt
cp .env.example .env
# заполните .env реальными ключами

Переменные окружения

Переменная Назначение Где взять
OPENAI_API_KEY LLM через OpenRouter openrouter.ai/settings/keys
JOURNAL_TOKEN API журнала platform.brojs.ru → профиль → токены
GITEA_TOKEN git.brojs.ru Settings → Applications → Access Tokens
TAVILY_API_KEY Поиск в сети (необязательно) tavily.com

Файл .env не коммитится — он в .gitignore.

Запуск

Пайплайн (все открытые coding-задания)

python -c "
import asyncio
from src.agent.graph.pipeline import pipeline

async def main():
    state = {'tasks': [], 'current_index': 0, 'results': [], 'errors': []}
    cfg = {'configurable': {'thread_id': 'run-1'}}
    out = await pipeline.ainvoke(state, cfg)
    print('Готово:', len(out['results']))
    if out['errors']:
        print('Сбои:', out['errors'])

asyncio.run(main())
"

LangGraph Studio

pip install "langgraph-cli[inmem]"
langgraph dev --allow-blocking --port 2024

UI: LangSmith Studio

Чат с оркестратором

python -c "
import asyncio
from src.agent.agent import agent
from langchain_core.messages import HumanMessage

async def main():
    cfg = {'configurable': {'thread_id': 'chat-1'}}
    while True:
        q = input('> ').strip()
        if q in ('exit', 'quit', 'q'):
            break
        r = await agent.ainvoke({'messages': [HumanMessage(content=q)]}, cfg)
        print(r['messages'][-1].content)

asyncio.run(main())
"

Карта репозитория

.
├── agent.py              # экспорт для langgraph dev
├── langgraph.json
├── requirements.txt
├── .env.example
└── src/agent/
    ├── agent.py          # оркестратор, homework, rework
    ├── graph/pipeline.py # пакетная обработка заданий
    ├── prompts.py
    ├── gitea_tools.py
    ├── mcp_client.py
    ├── middlewares/
    └── agent_workspace/  # клоны репозиториев

Секреты в коде

Плейсхолдеры подхватываются из .env:

Модуль Переменная
llm.py OPENAI_API_KEY
mcp_client.py JOURNAL_TOKEN
gitea_tools.py GITEA_TOKEN