AAYMA
RU
Войти

ЭКТ — каталог и ИИ-ассистент

Витрина и чат-консультант по каталогу ekt.kz: поиск по артикулу, характеристики, цена, остаток, подбор аналогов при нулевом остатке, условия оплаты…

Доведённый продукт
Команда «Hahathon Devs» 19💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Hahathon Devs
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Доведённый продукт

Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина

Суть

Витрина и чат-консультант по каталогу ekt.kz: поиск по артикулу, характеристики, цена, остаток, подбор аналогов при нулевом остатке, условия оплаты и доставки, корзина с явным подтверждением. Поддерживаются вложения (XLSX/DOCX/PDF/изображения).

Как устроено

Next.js-proxy передаёт запросы в FastAPI (сессии, CSRF). Отдельный worker забирает задачи из SQLite-очереди. Оркестратор ассистента получает от LLM структурированный JSON-план с намерением и позициями, а факты о цене и остатке берутся и проверяются на сервере из каталога (PostgreSQL с pg_trgm или демо-SQLite). Аналоги подбираются серверным сравнением характеристик с исключением критических противоречий. Корзина меняется только после отдельного подтверждения с проверкой версии, цены и остатка и защитой ключом идемпотентности. Файлы проходят карантин, сканер ClamAV и изолированный парсер.

Ключевые решения

  • structured JSON plan (Responses API)
  • bounded assistant loop с верификацией ответа
  • PostgreSQL pg_trgm поиск
  • сравнение атрибутов для аналогов
  • idempotent cart confirmation
  • durable worker queue с lease
  • ClamAV scanning
  • OCR

Особенности

Зрелая архитектура на портах и адаптерах: PostgreSQL или SQLite, OpenAI или Claude, адаптер EKT API. Модель только планирует, а все факты и изменения корзины проверяет сервер. Безопасная загрузка документов через карантин, антивирус и изолированный парсер. Smoke-скрипт проверяет, что корзина не меняется до подтверждения и повторный запрос не дублирует добавление.

Стек

Python · FastAPI · Pydantic · Uvicorn · HTTPX · Next.js 15 · React 19 · TypeScript · PostgreSQL · SQLite · ClamAV · pypdf · python-docx · openpyxl

Модели

OpenAI (Responses API) · Anthropic Claude


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-4a724051-hahathon-devs.

README

README.md

ЭКТ — каталог и ИИ-ассистент

Команда Hahathon Devs, HACKALEM AI 2026. Кейс: ИИ-ассистент для чата на сайте ekt.kz.

Прототип помогает покупателю найти электротехнические товары, проверить характеристики, цену и остаток, подобрать доступные аналоги и подготовить корзину. Витрина, чат и проверка корзины используют один источник каталога. Модель определяет намерение и выбирает позиции; фактические сведения и разрешение на изменение корзины проверяет сервер.

Основной каталог команды — подготовленная PostgreSQL-база Нурсултана. Для её использования выполните установку зависимостей, затем раздел «Подключение уже заполненного PostgreSQL» и запустите API, worker и frontend. Не запускайте импорт, генерацию товаров или сброс рабочей БД. Описанный ниже автономный режим нужен только экспертам без доступа к PostgreSQL; он не заменяет основной каталог. Демонстрационная корзина не оформляет заказ на EKT.

Возможности и границы

ТребованиеРеализация
Информация по артикулуПоиск, цена, характеристики, остаток; сертификат показывается только при наличии ссылки в источнике
Аналоги при нулевом остаткеСерверное сравнение характеристик, исключение критических противоречий, объяснение; при недостатке данных — уточнение
Условия покупкиТемы оплаты/доставки из файла знаний с URL источников
Подтверждение покупкиПредложение не меняет корзину. Отдельное подтверждение проверяет версию, срок, цену, остаток и количество с учётом корзины
Ссылка на корзинуВозвращается после подтверждения. Повтор запроса не дублирует добавление
ВложенияTXT, CSV, XLSX, DOCX, PDF, JPG/PNG: проверка типа/размера/структуры, scanner, изолированный parser; фото/сканы требуют vision
ИнтерфейсКатегории, фильтры, поиск, сортировка, карточки, избранное, сравнение, подборка, чат и история в пределах сессии

Без OpenAI работают серверные сценарии по артикулам и известным намерениям. Свободный анализ запроса и изображений требует включённой модели. Реальные платные вызовы OpenAI и работа настоящего антивируса пока не подтверждены внешней приёмкой.

Реальное оформление заказа EKT, оплата, аккаунт/B2B, передача заявки менеджеру и гарантированно полный каталог не реализованы. API корзины партнёр не предоставил. Проект предназначен для локальной проверки MVP; APP_ENV=production блокируется до завершения эксплуатационной подготовки.

Архитектура

flowchart LR
  Browser[Витрина и чат] --> Next[Next.js: серверный proxy]
  Next --> API[FastAPI: сессии, CSRF, контракты]
  API --> State[(SQLite: сессии, очередь и демо-корзина)]
  State --> Worker[Отдельный worker]
  Worker --> Assistant[Оркестратор ассистента]
  Assistant --> Planner[OpenAI: структурированный план]
  API --> Catalog[Интерфейс каталога]
  Assistant --> Catalog
  Catalog --> PG[(PostgreSQL: EKT)]
  Catalog --> Demo[(SQLite: синтетические товары)]
  Assistant --> Actions[Предложение и подтверждение]
  Actions --> Catalog
  Actions --> State
  API --> Files[Приватные файлы: scanner и parser]
  Files --> Assistant

PostgreSQL и SQLite-каталог — альтернативные режимы. В catalog_db товары читаются из PostgreSQL; SQLite продолжает хранить сессии, очередь, предложения и демо-корзину. Удаление SQLite не обновляет PostgreSQL и не заменяет выбор правильного режима.

ПутьОтветственность
frontend/src/components/storefront/Витрина, карточки, фильтры и корзина
frontend/src/components/assistant-chat.tsxЧат, вложения, ответы и подтверждения
frontend/src/lib/api.tsТипы, HTTP-транспорт и сессия
frontend/src/app/api/v1/[...path]/route.tsСерверный proxy; внешние ключи не передаются браузеру
backend/app/api/, core/HTTP-контракты, конфигурация, безопасность и ошибки
backend/app/modules/catalog/, search/Нормализация, качество данных, поиск и аналоги
backend/app/modules/assistant/Оркестрация и ответ из проверенных данных
backend/app/modules/actions/Предложение, подтверждение и идемпотентность
backend/app/modules/chat/, worker.pyДиалоги, сохранённая очередь и обработка задач
backend/app/modules/documents/Карантин, изолированный разбор, доступ по сессии
backend/app/adapters/, bootstrap.pyАдаптеры PostgreSQL/SQLite/EKT/OpenAI и сборка зависимостей
data/, docs/, test-files/Данные демо, документация и тестовые вложения

Контракты отделяют доменную логику от хранилищ и провайдеров. API и worker запускаются отдельно; задачи сохраняются, используют lease и таймауты. Подтверждение защищено ключом операции и транзакцией. Ошибка источника не превращается в выдуманный остаток или успешный заказ.

SQLite-очередь рассчитана на один хост и общий файл. Для горизонтального масштабирования нужно совместно перенести сессии, очередь, предложения и корзину в общее транзакционное хранилище, а файлы — в приватное объектное хранилище. Независимые SQLite-копии на разных серверах не обеспечивают общую сессию. Подробнее: архитектура, интеграция, контракты.

Технологии и зависимости

КомпонентТребование
Python3.11+; проверено на 3.11, нужен venv
BackendFastAPI, Pydantic, Uvicorn, HTTPX; версии в backend/requirements.lock
FrontendNode.js 22.18+ (проверено на 24), npm; Next.js 15.5.26, React 19, TypeScript 5.9
КаталогSQLite для демо; PostgreSQL 14+ с pg_trgm для реальной БД
Документыpypdf, pypdfium2, python-docx, openpyxl, Pillow; устанавливаются с backend
ИИOpenAI Responses API, структурированный JSON-план
АнтивирусClamAV с актуальными сигнатурами, если включены загрузки

Нужны Git и доступ к пакетным реестрам при первой установке. Для автономного демо после установки внешние API не нужны. Docker, Redis и LibreOffice для запуска приложения не требуются. На Linux при отсутствии venv установите python3-venv средствами ОС.

Установка и запуск

1. Получить проект и подготовить окружение

git clone https://github.com/BAITC-Hacks/hack-4a724051-hahathon-devs.git
cd hack-4a724051-hahathon-devs

Используйте ветку/коммит, представленные командой на проверку. В нём должны быть этот README и scripts/smoke_test.py. Команды ниже выполняются из корня клона, если явно не указан другой каталог.

PowerShell:

if (!(Test-Path .env)) { Copy-Item .env.example .env }
if (!(Test-Path frontend/.env.local)) { Copy-Item frontend/.env.example frontend/.env.local }

Linux/macOS:

test -f .env || cp .env.example .env
test -f frontend/.env.local || cp frontend/.env.example frontend/.env.local

В корневом .env для автономной проверки:

APP_ENV=development
INTEGRATION_MODE=synthetic
LLM_ENABLED=false
LLM_DATA_POLICY_ACCEPTED=false
UPLOADS_ENABLED=false
EKT_LIVE_REFRESH=false

Остальные настройки оставьте из .env.example; ключи и DATABASE_URL не нужны. Если LOCAL_DB_PATH уже задан, используйте отдельный абсолютный путь для демо. По умолчанию файл backend/var/participant2.sqlite3 создаётся автоматически. API и worker должны использовать один файл.

В frontend/.env.local:

BACKEND_INTERNAL_URL=http://127.0.0.1:8000

Переменные терминала имеют приоритет над .env. Для чистой проверки используйте новые терминалы без старых значений INTEGRATION_MODE, LOCAL_DB_PATH, DATABASE_URL.

2. Установить зависимости

PowerShell, из корня:

python -m venv backend/.venv
backend/.venv/Scripts/python.exe -m pip install -r backend/requirements.lock -e './backend[dev]'
cd frontend
npm ci
cd ..

Linux/macOS, из корня:

python3 -m venv backend/.venv
backend/.venv/bin/python -m pip install -r backend/requirements.lock -e './backend[dev]'
cd frontend
npm ci
cd ..

Активация venv не нужна. На Windows при блокировке npm.ps1 используйте npm.cmd.

3. Запустить три процесса

Откройте три терминала в корне репозитория. На Linux/macOS замените .venv/Scripts/python.exe на .venv/bin/python.

Терминал 1 — API:

cd backend
.venv/Scripts/python.exe -m uvicorn app.main:create_app --factory --host 127.0.0.1 --port 8000 --no-proxy-headers

Терминал 2 — worker:

cd backend
.venv/Scripts/python.exe -m app.worker

Терминал 3 — frontend:

cd frontend
npm run build
npm run start -- --hostname 127.0.0.1 --port 3000

Для разработки вместо build и start используйте npm run dev. Не запускайте оба режима на одном порту. Сборка Next.js не означает включение APP_ENV=production в backend.

Ожидается 281 демонстрационный товар с пометкой демо. /health/ready не подтверждает работу worker/OpenAI — это проверяется сценарием ниже. Остановка: Ctrl+C в каждом терминале. После изменения .env перезапустите API и worker; после frontend-настроек — Next.js.

Проверка основного сценария

Автоматически через HTTP

При работающих трёх процессах из корня:

backend/.venv/Scripts/python.exe scripts/smoke_test.py

На Linux/macOS используйте backend/.venv/bin/python. Скрипт через frontend-прокси создаёт отдельную сессию, проверяет каталог, ответ worker, неизменность корзины до подтверждения, подтверждение, безопасный повтор и ссылку корзины. В конце удаляет свою тестовую сессию. Успех — строки PASS, ошибка — ненулевой код. Скрипт отказывается работать с адаптером реального оформления заказа.

В браузере

  1. Найдите 990100003_. В неизменённом демо: цена 1 350 ₸, продающий остаток 2 шт, характеристики и тестовый сертификат.
  2. В чате отправьте 990100003_, затем характеристики. Ответ и карточка должны использовать одинаковые факты.
  3. Отправьте 990100015_, затем отдельным сообщением есть аналог? без артикула. Ожидаются аналоги предыдущего товара с объяснением. Повтор а есть ещё аналоги? сохраняет исходный товар, а не переключается на предложенную замену. В новом пустом диалоге тот же вопрос должен запросить артикул. Неоднозначная выдача также требует уточнения.
  4. Отправьте условия доставки: ответ из файла знаний со ссылкой на источник.
  5. В новом диалоге отправьте Купить 990100003_ 2 шт. Предложение: 2 × 1 350 = 2 700 ₸. До подтверждения корзина пуста.
  6. Подтвердите предложение. Ссылка открывает корзину: 2 шт, 2 700 ₸. Повтор не увеличивает количество; запрос сверх остатка отклоняется.
  7. Перезагрузите страницу: история текущей сессии восстанавливается. Избранное и сравнение сохраняются в браузере.
  8. Для вложений сначала включите scanner по инструкции ниже. Десять тестовых файлов содержат ожидаемые результаты; отклонение файла больше лимита — успешная проверка защиты.

Подключение уже заполненного PostgreSQL

Для базы, подготовленной участником команды, не запускайте повторный импорт и не очищайте таблицы. В корневом .env:

INTEGRATION_MODE=catalog_db
DATABASE_URL=postgresql://USER:[скрыто]@HOST:5432/ekt
EKT_LIVE_REFRESH=false

Замените placeholders собственными значениями. Спецсимволы логина/пароля URI должны быть percent-encoded. Нужна доступная схема проекта с таблицами products, catalog_sync_runs и миграциями. Строка подключения — секрет; она не публикуется в Git или frontend. EKT Basic Auth не является доступом PostgreSQL.

Перезапустите API и worker. Каталог читается из products PostgreSQL; SQLite остаётся для чата/очереди/демо-корзины. Удаление этого файла уничтожит локальные сессии и историю. Новые записи PostgreSQL видны при следующих запросах без пересоздания SQLite. Перезапуск нужен при смене режима/подключения.

Проверка состояния без импорта, из backend:

.venv/Scripts/python.exe -m app.catalog_cli status

Сквозная проверка из корня с артикулом доступного товара вашей БД:

backend/.venv/Scripts/python.exe scripts/smoke_test.py --article 200300285_

Этот пример проверен в API партнёра; его наличие в вашей БД и остаток могут измениться. Для новой пустой БД подготовка описана в docs/data-and-db.md. Миграции и импорт изменяют целевую БД; не выполняйте их при проверке уже подготовленной базы без необходимости.

Почему встречались счётчики 0 и 54

В старом демо-файле было 65 товаров, из них 54 — низковольтная аппаратура. После объединения актуального main набор содержит 281 товар во всех 12 разделах. Старую локальную копию требуется обновить; перезапуск сам по себе не перезаписывает заполненный SQLite-каталог. Счётчики соответствуют выбранному источнику. Ноль в частичном наборе не означает отсутствие товара на EKT. Категория определяется по URL, поэтому промо-разделы/архив могут образовать дополнительные ветки. Проект не выдумывает товары для заполнения пустых категорий.

Используемые данные

  • data/synthetic/ekt_products.json: 281 демонстрационная карточка: 68 полностью синтетических и 213 на основе названий, изображений и характеристик из API EKT. У всех ID, артикулы, цены и остатки демонстрационные. Сертификаты в data/synthetic/certificates/ также тестовые.
  • data/curated/purchase_terms.json: редакционная подборка условий с публичных страниц EKT и URL источников; условия требуют периодической актуализации.
  • Реальный API: GET https://ekt.kz/api/products?page=N и GET https://ekt.kz/api/products/detail?id=ID, HTTP Basic Auth. Доступы передаются отдельно, реальные карточки/БД в Git не включены.
  • Список содержит до 20 позиций; count — число на странице, а не общее число товаров. При проверке далёкая страница вернула первую страницу: номер страницы не подтверждает полноту обхода.
  • Детальная карточка содержит description, properties, общую величину остатка и склады. Нормализатор сопоставляет характеристики, помечает противоречия, исключает непродающие склады. Неподтверждённые данные не подменяются точными.
  • В API нет подтверждённого интерфейса корзины/заказов. Корзина прототипа локальная даже при реальном каталоге.

Контракт EKT: docs/api.md. HTTP-контракт приложения: docs/openapi.json; актуальную схему запущенной версии проверяйте по /openapi.json.

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

API и worker читают корневой .env; Next.js — frontend/.env.local. Шаблоны: .env.example, frontend/.env.example. Секреты исключены .gitignore, не имеют префикса NEXT_PUBLIC_.

ПараметрНазначение / демо-значение
APP_ENVdevelopment; production в текущем MVP запрещён
INTEGRATION_MODEsynthetic, catalog_db или unavailable
LOCAL_DB_PATHОдин абсолютный SQLite-путь API/worker; по умолчанию backend/var/participant2.sqlite3
DATABASE_URLPostgreSQL URI, обязателен для catalog_db
CATALOG_DB_SEED_DEMOtrue; в catalog_db досевает демо-товары в пустую базу. Для подготовленной базы партнёра ставьте false
EKT_API_USER, EKT_API_PASSWORDBasic Auth EKT; пустые в шаблоне
EKT_LIVE_REFRESHfalse; true проверяет цену/остаток перед корзиной и обновляет карточку PostgreSQL
LLM_ENABLED, LLM_API_KEYfalse, пустой серверный ключ
LLM_PROVIDERopenai
LLM_MODEL, LLM_ALLOWED_MODELSgpt-6-sol, ["gpt-6-sol"]; нужен доступ проекта OpenAI к модели
LLM_REASONING_EFFORTmedium
LLM_DATA_POLICY_ACCEPTEDfalse; true после принятия оператором политики передачи данных
LLM_TIMEOUT_SECONDS, LLM_MAX_OUTPUT_TOKENS45, 8192
LLM_SESSION_DAILY_TOKENS, LLM_SITE_DAILY_TOKENS100000, 1000000; токенные, не денежные лимиты
AI_SERVICES_PROVIDERopenai или nvidia; провайдер OCR и эмбеддингов
NVIDIA_API_KEY, NVIDIA_DATA_POLICY_ACCEPTEDНужны только при AI_SERVICES_PROVIDER=nvidia
OCR_ENABLED, OCR_MODELfalse, пусто; распознавание сканов и фото. Пустая модель — значение провайдера по умолчанию
SEMANTIC_SEARCH_ENABLED, EMBED_MODELfalse, пусто; поиск по смыслу. Модель обязана совпадать с моделью индекса
SEMANTIC_INDEX_PATHdata/synthetic/embeddings.json; файл индекса эмбеддингов
AI_SITE_DAILY_CALLS, AI_SESSION_DAILY_CALLS3000, 200; лимиты вызовов AI-сервиса в сутки
WORKER_TIMEOUT_SECONDS, WORKER_LEASE_SECONDS75, 120; timeout worker > timeout модели с запасом, lease > timeout worker
UPLOADS_ENABLED, SCANNER_COMMANDfalse, []; включение требует настоящего антивируса
ASSETS_ROOTПриватные загрузки: по умолчанию backend/var/assets
ALLOWED_ORIGINS, ALLOWED_HOSTSJSON-массивы разрешённых origin/host; локальные значения по умолчанию в Settings
COOKIE_SECUREfalse для локального HTTP; HTTPS требует отдельной настройки
BACKEND_INTERNAL_URLТолько frontend server: http://127.0.0.1:8000
FRONTEND_ORIGINТолько frontend server: точный публичный origin за доверенным reverse proxy

CLAMD_SOCKET и DOCUMENTS_ALLOW_UNSCANNED относятся к неподключённому PostgreSQL-адаптеру документов. Они не включают HTTP-загрузки и не обходят scanner текущего DocumentsService.

Включение OpenAI

Заполните LLM_API_KEY, установите LLM_ENABLED=true, LLM_DATA_POLICY_ACCEPTED=true в корневом .env. Остальные настройки Sol есть в шаблоне. Перезапустите API и worker. Вызовы оплачиваются вашим проектом OpenAI; настройте его бюджет. Локальные mock-тесты не подтверждают качество/время ответа реальной модели.

Включение файлов

Установите ClamAV, обновите сигнатуры и проверьте команду из окружения backend. Затем:

UPLOADS_ENABLED=true
SCANNER_COMMAND=["clamscan","--no-summary"]

Если scanner не в PATH, укажите полный путь: например ["C:/Program Files/ClamAV/clamscan.exe","--no-summary"]. Перезапустите API/worker. Для отправки вложения внешней модели нужно также согласие пользователя в чате. Сбой scanner оставляет файл недоступным для анализа.

На Windows вместо ClamAV можно использовать работающий Microsoft Defender с актуальными сигнатурами:

UPLOADS_ENABLED=true
SCANNER_COMMAND=["windows-defender"]
LLM_ENABLED=true
LLM_DATA_POLICY_ACCEPTED=true

Ключ LLM_API_KEY заполните только в локальном .env. Backend сам находит установленную версию Defender и проверяет каждый файл; ошибка проверки блокирует анализ. После изменения настроек перезапустите API и worker, обновите страницу. В /api/v1/capabilities ожидаются upload: ready, documents: ready, llm: openai. Прикрепите файл скрепкой, отметьте разрешение на передачу выбранных файлов в OpenAI и отправьте «Найди товары по артикулам из вложенного файла». Sol получает изображения страниц скана и фотографии, а цены и наличие ответа берутся из каталога. Без разрешения доступен только локальный текстовый разбор, изображение не распознаётся.

Проверка всех десяти файлов через запущенный сайт (реальный антивирус и parser):

backend/.venv/Scripts/python.exe scripts/smoke_attachments.py
# Дополнительно три платных запроса OpenAI на синтетических DOCX, PDF-скане и фото:
backend/.venv/Scripts/python.exe scripts/smoke_attachments.py --analyze

Тест проверяет найденные артикулы и удаляет свои сессии. Суммарный текст вложений для одного вызова ограничен 24 000 UTF-8 байт; при превышении чат показывает предупреждение и предлагает разделить документ. Это предотвращает отказ модели из-за слишком большого контекста; полный разбор всех страниц больших файлов не гарантируется.

Лимиты: 3 вложения на сообщение, 10 МиБ на файл, 200 строк таблиц, 20 листов XLSX, 20 страниц PDF, 40 000 символов; до 4 страниц PDF без текста передаются как изображения. При обрезке показывается предупреждение. .doc/.xls не поддерживаются — используйте .docx/.xlsx. Полный анализ больших документов требует обработки по частям. Подробная инструкция.

Включение OCR и семантического поиска

Обе возможности обращаются к внешнему AI-сервису и по умолчанию выключены. Провайдер задаёт AI_SERVICES_PROVIDER: значение openai использует уже настроенные LLM_API_KEY и LLM_DATA_POLICY_ACCEPTED, значение nvidia — отдельные NVIDIA_API_KEY и NVIDIA_DATA_POLICY_ACCEPTED. Без ключа и согласия на передачу данных запуск останавливается с сообщением, в котором названы недостающие переменные.

OCR читает сканы и фотографии без текстового слоя — те файлы, для которых локального разбора не хватает:

AI_SERVICES_PROVIDER=openai
OCR_ENABLED=true

Семантический поиск отвечает на запрос по смыслу, а не только по артикулу и подстроке. Ему нужен заранее посчитанный индекс эмбеддингов. Из backend:

.venv/Scripts/python.exe -m app.catalog_cli embed --source synthetic

Для каталога PostgreSQL укажите --source db, путь файла меняется через --out. После этого в корневом .env:

SEMANTIC_SEARCH_ENABLED=true

Индекс читается из SEMANTIC_INDEX_PATH. EMBED_MODEL при запуске обязана совпадать с моделью, которой считался индекс: при расхождении выдача становится бессмысленной, а не пустой. Пустые OCR_MODEL и EMBED_MODEL означают модель провайдера по умолчанию.

Расход ограничен числом вызовов в сутки — AI_SITE_DAILY_CALLS и AI_SESSION_DAILY_CALLS. Это лимиты вызовов, а не денег: бюджет настраивается в кабинете провайдера. Перезапустите API и worker; в /api/v1/capabilities поля ocr и semantic_search перейдут из disabled в рабочее состояние.

Проверки качества

Из backend (Linux/macOS: заменить Scripts/python.exe на bin/python):

.venv/Scripts/python.exe -m pip check
.venv/Scripts/python.exe -m pytest

Из frontend:

npm run typecheck
npm run test:proxy
npm run build

Из корня — локальная проверка вложений без LLM/scanner:

backend/.venv/Scripts/python.exe scripts/verify_assistant_fixtures.py

PostgreSQL-тесты требуют отдельной одноразовой TEST_DATABASE_URL: они пересоздают схему public. Никогда не указывайте рабочую БД. Без неё 20 PostgreSQL-тестов пропускаются.

Проверка 23.09.2026: 254 backend-теста прошли, 20 PostgreSQL-тестов пропущены; 5 тестов proxy и TypeScript прошли. Подробности и ограничения: отчёт. Тесты не гарантируют отсутствия всех ошибок; внешние зависимости проверяются отдельно.

Диагностика запуска

СимптомДействие
Каталог недоступенДля демо: INTEGRATION_MODE=synthetic, перезапуск API/worker
Остались 65 товаров после обновления PostgreSQLПроверить catalog_db, DATABASE_URL, переменные терминала и BACKEND_INTERNAL_URL; перезапустить и обновить страницу
catalog_db requires DATABASE_URLУказать PostgreSQL URI; EKT Basic Auth не заменяет его
PostgreSQL timeout / нет таблицыПроверить хост/порт, пользователя и схему; использовать подготовленную базу
Сообщение в очередиЗапустить worker с тем же .env и SQLite-путём, что API
403 / CSRFИспользовать один адрес 127.0.0.1:3000, не смешивать localhost и IP; обновить сессию
503 при загрузкеПроверить включение, путь scanner, сигнатуры
Модель недоступнаПроверить ключ, доступ к модели, квоту, политику; каталог может работать в резервном режиме
OCR или семантический поиск не включаютсяПроверить AI_SERVICES_PROVIDER, ключ и согласие на передачу данных; для поиска — что индекс посчитан catalog_cli embed и EMBED_MODEL совпадает с моделью индекса
Порт занятОстановить старый экземпляр; при смене порта согласованно изменить proxy и allowed origins
SQLite занят / API и worker видят разноеПроверить общий абсолютный путь, права записи, лишние старые процессы

Перед сдачей выполните установку и основной сценарий на чистом клоне именно сдаваемого коммита. Незакоммиченные локальные файлы эксперту недоступны. Не публикуйте .env, приватные файлы и БД; доступы передавайте организатору отдельно.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
57
Авторы
2
Файлы
470
Ветки
2

Авторы коммитов

Goslinuly 38Tomiris 19

История коммитов

  • 2026-09-23 17:55README: OCR, семантический поиск и недостающие переменныеTomiris
  • 2026-09-23 17:48Resolve visible image articles before requesting clarificationTomiris
  • 2026-09-23 17:48Merge remote-tracking branch 'origin/main' into codex/participant-2-backendTomiris
  • 2026-09-23 17:47OCR and semantic search on OpenAI or NVIDIAGoslinuly
  • 2026-09-23 17:47Search: understand how customers write and table rows from filesGoslinuly
  • 2026-09-23 17:47Semantic index for the demo catalog and docsGoslinuly
  • 2026-09-23 17:44Fix attachment analysis, ground document lookup and bound model contextTomiris
  • 2026-09-23 17:40Поддержка Microsoft Defender как сканера вложенийTomiris
Все коммиты (57)
  • 2026-09-23 17:40Презентация проекта для защитыTomiris
  • 2026-09-23 17:32NVIDIA API client with a shared daily call budgetGoslinuly
  • 2026-09-23 17:32Read photos and scans with NVIDIA when the customer allows itGoslinuly
  • 2026-09-23 17:32Semantic catalog search on NVIDIA embeddingsGoslinuly
  • 2026-09-23 17:18Clearer DATABASE_URL errors: say when it is needed and the no-DB optionGoslinuly
  • 2026-09-23 17:11Add PostgreSQL catalog dump and make synthetic the default modeGoslinuly
  • 2026-09-23 17:10Merge remote-tracking branch 'origin/main' into codex/participant-2-backendTomiris
  • 2026-09-23 17:09catalog_db works on an empty PostgreSQL out of the boxGoslinuly
  • 2026-09-23 17:06fix: retain product context for assistant alternatives and document verificationTomiris
  • 2026-09-23 17:00Session logout, per-session rate limiting and upload test fixturesTomiris
  • 2026-09-23 16:54Merge remote-tracking branch 'origin/main' into codex/participant-2-backendTomiris
  • 2026-09-23 16:42README: stack and versions, one run guide for macOS, Linux, WindowsGoslinuly
  • 2026-09-23 16:32Fill every catalog section with real ekt.kz itemsGoslinuly
  • 2026-09-23 16:32Storefront: show Russian titles for all subsectionsGoslinuly
  • 2026-09-23 16:23Readable product names and illustrations for the demo catalogGoslinuly
  • 2026-09-23 16:23Serve product illustrations at /api/v1/product-imagesGoslinuly
  • 2026-09-23 16:13Demo data and profiles so every out-of-stock item has an analogGoslinuly
  • 2026-09-23 16:12fix: restore assistant chat after completed turns and verify storefront flowsTomiris
  • 2026-09-23 16:11Do not flag 400V AC vs 400V as a conflictGoslinuly
  • 2026-09-23 16:10Parser subprocess: do not crash on macOS memory limitGoslinuly
  • 2026-09-23 16:04Merge origin/main: PostgreSQL catalog, EKT API client and storefront UITomiris
  • 2026-09-23 15:43frontend: assistant chat component and catalog browse testTomiris
  • 2026-09-23 15:40frontend apiTomiris
  • 2026-09-23 15:34Backend and assistentTomiris
  • 2026-09-23 15:26docs: catalog DB, import CLI, documents and what is leftGoslinuly
  • 2026-09-23 15:26Fewer false attribute conflicts on real EKT cardsGoslinuly
  • 2026-09-23 15:24Parse client files: xlsx, docx, pdfGoslinuly
  • 2026-09-23 15:24Store client files in PostgreSQL and implement DocumentsPortGoslinuly
  • 2026-09-23 15:20EKT catalog API clientGoslinuly
  • 2026-09-23 15:20Catalog in PostgreSQL with import from file or EKT APIGoslinuly
  • 2026-09-23 15:20Wire PostgreSQL catalog into the API and workerGoslinuly
  • 2026-09-23 15:15Align ownership comments with the current splitGoslinuly
  • 2026-09-23 15:14Fix alternatives matching, add barcode lookupGoslinuly
  • 2026-09-23 15:05feat: integrate marketplace backend, assistant services and Next.js frontendTomiris
  • 2026-09-23 14:46feat: add session and chat API with durable worker and integration contractsTomiris
  • 2026-09-23 14:27README: data, assistant modules and how to run testsGoslinuly
  • 2026-09-23 14:27LLM port and Claude providerGoslinuly
  • 2026-09-23 14:27Assistant tools, prompt and reply contractsGoslinuly
  • 2026-09-23 14:27Bounded assistant loop with answer verificationGoslinuly
  • 2026-09-23 14:27Chat service: confirmation, model turn and no-LLM fallbackGoslinuly
  • 2026-09-23 14:27docs: service interfaces and chat reply format for the API sideGoslinuly
  • 2026-09-23 14:21Add synthetic catalog in ekt.kz API formatGoslinuly
  • 2026-09-23 14:21Catalog model and data quality rulesGoslinuly
  • 2026-09-23 14:21Product search and explainable alternativesGoslinuly
  • 2026-09-23 14:21Purchase terms knowledge base from ekt.kz pagesGoslinuly
  • 2026-09-23 14:21Cart proposals with explicit confirmationGoslinuly
  • 2026-09-23 14:00docs: add EKT API reference and environment templatesTomiris
  • 2026-09-23 13:53basesTomiris
  • 2026-09-23 13:44Add README with case description and data notesGoslinuly
Структура репозитория (470 файлов)
.env.example
.gitattributes
.gitignore
README.md
backend/app/__init__.py
backend/app/adapters/__init__.py
backend/app/adapters/ai_services/__init__.py
backend/app/adapters/ai_services/client.py
backend/app/adapters/ekt/__init__.py
backend/app/adapters/ekt/client.py
backend/app/adapters/llm/__init__.py
backend/app/adapters/llm/anthropic_provider.py
backend/app/adapters/llm/openai_provider.py
backend/app/adapters/memory.py
backend/app/adapters/postgres/__init__.py
backend/app/adapters/postgres/catalog.py
backend/app/adapters/postgres/documents.py
backend/app/adapters/storage/__init__.py
backend/app/adapters/storage/catalog.py
backend/app/adapters/storage/sqlite.py
backend/app/api/__init__.py
backend/app/api/v1/__init__.py
backend/app/api/v1/dependencies.py
backend/app/api/v1/responses.py
backend/app/api/v1/router.py
backend/app/bootstrap.py
backend/app/catalog_cli.py
backend/app/contracts.py
backend/app/core/__init__.py
backend/app/core/config.py
backend/app/core/errors.py
backend/app/core/http.py
backend/app/core/privacy.py
backend/app/core/security.py
backend/app/infrastructure/__init__.py
backend/app/infrastructure/db.py
backend/app/integrations/__init__.py
backend/app/integrations/domain.py
backend/app/integrations/ports.py
backend/app/integrations/unavailable.py
backend/app/main.py
backend/app/modules/__init__.py
backend/app/modules/actions/__init__.py
backend/app/modules/actions/models.py
backend/app/modules/actions/ports.py
backend/app/modules/actions/service.py
backend/app/modules/assistant/__init__.py
backend/app/modules/assistant/budget.py
backend/app/modules/assistant/catalog_only.py
backend/app/modules/assistant/config.py
backend/app/modules/assistant/contracts.py
backend/app/modules/assistant/policy.py
backend/app/modules/assistant/ports.py
backend/app/modules/assistant/processing.py
backend/app/modules/assistant/prompts/consultant.md
backend/app/modules/assistant/prompts/planner.md
backend/app/modules/assistant/references.py
backend/app/modules/assistant/rendering.py
backend/app/modules/assistant/runner.py
backend/app/modules/assistant/runtime.py
backend/app/modules/assistant/state.py
backend/app/modules/assistant/tools.py
backend/app/modules/catalog/__init__.py
backend/app/modules/catalog/browse.py
backend/app/modules/catalog/dto.py
backend/app/modules/catalog/models.py
backend/app/modules/catalog/ports.py
backend/app/modules/catalog/quality.py
backend/app/modules/catalog/routes.py
backend/app/modules/catalog/sync.py
backend/app/modules/chat/__init__.py
backend/app/modules/chat/application.py
backend/app/modules/chat/factory.py
backend/app/modules/chat/models.py
backend/app/modules/chat/ports.py
backend/app/modules/chat/routes.py
backend/app/modules/chat/service.py
backend/app/modules/documents/__init__.py
backend/app/modules/documents/extraction.py
backend/app/modules/documents/models.py
backend/app/modules/documents/ocr.py
backend/app/modules/documents/parser.py
backend/app/modules/documents/scanner.py
backend/app/modules/documents/service.py
backend/app/modules/documents/validation.py
backend/app/modules/knowledge/__init__.py
backend/app/modules/knowledge/service.py
backend/app/modules/knowledge/translations.py
backend/app/modules/search/__init__.py
backend/app/modules/search/alternatives.py
backend/app/modules/search/semantic.py
backend/app/modules/search/service.py
backend/app/worker.py
backend/migrations/001_catalog.sql
backend/migrations/002_documents.sql
backend/pyproject.toml
backend/requirements.lock
backend/scripts/export_openapi.py
backend/tests/conftest.py
backend/tests/test_actions.py
backend/tests/test_ai_services.py
backend/tests/test_analog_safety.py
backend/tests/test_anthropic_provider.py
backend/tests/test_api.py
backend/tests/test_assets_http.py
backend/tests/test_catalog_browse.py
backend/tests/test_catalog_quality.py
backend/tests/test_catalog_reader_contract.py
backend/tests/test_chat.py
backend/tests/test_documents.py
backend/tests/test_documents_extraction.py
backend/tests/test_ekt_client.py
backend/tests/test_grounded_runtime.py
backend/tests/test_integration_boundaries.py
backend/tests/test_openai_provider.py
backend/tests/test_postgres_catalog.py
backend/tests/test_postgres_documents.py
backend/tests/test_product_images.py
backend/tests/test_resource_lifecycle.py
backend/tests/test_search.py
backend/tests/test_security_boundaries.py
backend/tests/test_session_lifecycle.py
backend/tests/test_store_worker.py
backend/tests/test_synthetic_integration.py
backend/tests/test_terms_translations.py
data/curated/category_labels.json
data/curated/purchase_terms.json
data/db/README.md
data/db/ekt_catalog.sql
data/synthetic/certificates/SYN-900003.pdf
data/synthetic/certificates/SYN-900005.pdf
data/synthetic/certificates/SYN-900006.pdf
data/synthetic/certificates/SYN-900008.pdf
data/synthetic/certificates/SYN-900010.pdf
data/synthetic/certificates/SYN-900013.pdf
data/synthetic/certificates/SYN-900014.pdf
data/synthetic/certificates/SYN-900016.pdf
data/synthetic/certificates/SYN-900017.pdf
data/synthetic/certificates/SYN-900022.pdf
data/synthetic/certificates/SYN-900023.pdf
data/synthetic/certificates/SYN-900026.pdf
data/synthetic/certificates/SYN-900027.pdf
data/synthetic/certificates/SYN-900029.pdf
data/synthetic/certificates/SYN-900030.pdf
data/synthetic/certificates/SYN-900034.pdf
data/synthetic/certificates/SYN-900035.pdf
data/synthetic/certificates/SYN-900036.pdf
data/synthetic/certificates/SYN-900037.pdf
data/synthetic/certificates/SYN-900039.pdf
data/synthetic/certificates/SYN-900040.pdf
data/synthetic/certificates/SYN-900042.pdf
data/synthetic/certificates/SYN-900043.pdf
data/synthetic/certificates/SYN-900044.pdf
data/synthetic/certificates/SYN-900045.pdf
data/synthetic/certificates/SYN-900046.pdf
data/synthetic/certificates/SYN-900047.pdf
data/synthetic/certificates/SYN-900048.pdf
data/synthetic/certificates/SYN-900049.pdf
data/synthetic/certificates/SYN-900050.pdf
data/synthetic/certificates/SYN-900051.pdf
data/synthetic/certificates/SYN-900052.pdf
data/synthetic/certificates/SYN-900053.pdf
data/synthetic/certificates/SYN-900054.pdf
data/synthetic/certificates/SYN-900055.pdf
data/synthetic/certificates/SYN-900056.pdf
data/synthetic/certificates/SYN-900057.pdf
data/synthetic/certificates/SYN-900058.pdf
data/synthetic/certificates/SYN-900059.pdf
data/synthetic/certificates/SYN-900060.pdf
data/synthetic/certificates/SYN-900061.pdf
data/synthetic/certificates/SYN-900062.pdf
data/synthetic/certificates/SYN-900063.pdf
data/synthetic/certificates/SYN-900064.pdf
data/synthetic/certificates/SYN-900065.pdf
data/synthetic/certificates/SYN-900066.pdf
data/synthetic/certificates/SYN-900067.pdf
data/synthetic/certificates/SYN-900068.pdf
data/synthetic/certificates/SYN-900072.pdf
data/synthetic/certificates/SYN-900074.pdf
data/synthetic/certificates/SYN-900075.pdf
data/synthetic/certificates/SYN-900076.pdf
data/synthetic/certificates/SYN-900077.pdf
data/synthetic/certificates/SYN-900078.pdf
data/synthetic/certificates/SYN-900079.pdf
data/synthetic/certificates/SYN-900080.pdf
data/synthetic/certificates/SYN-900081.pdf
data/synthetic/certificates/SYN-900082.pdf
data/synthetic/certificates/SYN-900084.pdf
data/synthetic/certificates/SYN-900085.pdf
data/synthetic/certificates/SYN-900086.pdf
data/synthetic/certificates/SYN-900087.pdf
data/synthetic/certificates/SYN-900088.pdf
data/synthetic/certificates/SYN-900089.pdf
data/synthetic/certificates/SYN-900090.pdf
data/synthetic/certificates/SYN-900091.pdf
data/synthetic/certificates/SYN-900092.pdf
data/synthetic/certificates/SYN-900093.pdf
data/synthetic/certificates/SYN-900095.pdf
data/synthetic/certificates/SYN-900096.pdf
data/synthetic/certificates/SYN-900097.pdf
data/synthetic/certificates/SYN-900099.pdf
data/synthetic/certificates/SYN-900100.pdf
data/synthetic/certificates/SYN-900101.pdf
data/synthetic/certificates/SYN-900102.pdf
data/synthetic/certificates/SYN-900103.pdf
data/synthetic/certificates/SYN-900104.pdf
data/synthetic/certificates/SYN-900105.pdf
data/synthetic/certificates/SYN-900106.pdf
data/synthetic/certificates/SYN-900107.pdf
data/synthetic/certificates/SYN-900108.pdf
data/synthetic/certificates/SYN-900109.pdf
data/synthetic/certificates/SYN-900111.pdf
data/synthetic/certificates/SYN-900114.pdf
data/synthetic/certificates/SYN-900115.pdf
data/synthetic/certificates/SYN-900116.pdf
data/synthetic/certificates/SYN-900117.pdf
data/synthetic/certificates/SYN-900119.pdf
data/synthetic/certificates/SYN-900120.pdf
data/synthetic/certificates/SYN-900121.pdf
data/synthetic/certificates/SYN-900122.pdf
data/synthetic/certificates/SYN-900126.pdf
data/synthetic/certificates/SYN-900127.pdf
data/synthetic/certificates/SYN-900128.pdf
data/synthetic/certificates/SYN-900129.pdf
data/synthetic/certificates/SYN-900131.pdf
data/synthetic/certificates/SYN-900132.pdf
data/synthetic/certificates/SYN-900133.pdf
data/synthetic/certificates/SYN-900134.pdf
data/synthetic/certificates/SYN-900135.pdf
data/synthetic/certificates/SYN-900136.pdf
data/synthetic/certificates/SYN-900138.pdf
data/synthetic/certificates/SYN-900139.pdf
data/synthetic/certificates/SYN-900140.pdf
data/synthetic/certificates/SYN-900141.pdf
data/synthetic/certificates/SYN-900142.pdf
data/synthetic/certificates/SYN-900143.pdf
data/synthetic/certificates/SYN-900146.pdf
data/synthetic/certificates/SYN-900148.pdf
data/synthetic/certificates/SYN-900149.pdf
data/synthetic/certificates/SYN-900151.pdf
data/synthetic/certificates/SYN-900152.pdf
data/synthetic/certificates/SYN-900153.pdf
data/synthetic/certificates/SYN-900154.pdf
data/synthetic/certificates/SYN-900155.pdf
data/synthetic/certificates/SYN-900157.pdf
data/synthetic/certificates/SYN-900158.pdf
data/synthetic/certificates/SYN-900159.pdf
data/synthetic/certificates/SYN-900160.pdf
data/synthetic/certificates/SYN-900161.pdf
data/synthetic/certificates/SYN-900162.pdf
data/synthetic/certificates/SYN-900164.pdf
data/synthetic/certificates/SYN-900165.pdf
data/synthetic/certificates/SYN-900166.pdf
data/synthetic/certificates/SYN-900167.pdf
data/synthetic/certificates/SYN-900168.pdf
data/synthetic/certificates/SYN-900169.pdf
data/synthetic/certificates/SYN-900171.pdf
data/synthetic/certificates/SYN-900172.pdf
data/synthetic/certificates/SYN-900173.pdf
data/synthetic/certificates/SYN-900174.pdf
data/synthetic/certificates/SYN-900175.pdf
data/synthetic/certificates/SYN-900176.pdf
data/synthetic/certificates/SYN-900177.pdf
data/synthetic/certificates/SYN-900178.pdf
data/synthetic/certificates/SYN-900179.pdf
data/synthetic/certificates/SYN-900180.pdf
data/synthetic/certificates/SYN-900181.pdf
data/synthetic/certificates/SYN-900182.pdf
data/synthetic/certificates/SYN-900183.pdf
data/synthetic/certificates/SYN-900184.pdf
data/synthetic/certificates/SYN-900185.pdf
data/synthetic/certificates/SYN-900186.pdf
data/synthetic/certificates/SYN-900187.pdf
data/synthetic/certificates/SYN-900188.pdf
data/synthetic/certificates/SYN-900189.pdf
data/synthetic/certificates/SYN-900190.pdf
data/synthetic/certificates/SYN-900192.pdf
data/synthetic/certificates/SYN-900194.pdf
data/synthetic/certificates/SYN-900195.pdf
data/synthetic/certificates/SYN-900196.pdf
data/synthetic/certificates/SYN-900197.pdf
data/synthetic/certificates/SYN-900198.pdf
data/synthetic/certificates/SYN-900199.pdf
data/synthetic/certificates/SYN-900200.pdf
data/synthetic/certificates/SYN-900201.pdf
data/synthetic/certificates/SYN-900202.pdf
data/synthetic/certificates/SYN-900203.pdf
data/synthetic/certificates/SYN-900204.pdf
data/synthetic/certificates/SYN-900205.pdf
data/synthetic/certificates/SYN-900206.pdf
data/synthetic/certificates/SYN-900207.pdf
data/synthetic/certificates/SYN-900208.pdf
data/synthetic/certificates/SYN-900209.pdf
data/synthetic/certificates/SYN-900210.pdf
data/synthetic/certificates/SYN-900212.pdf
data/synthetic/certificates/SYN-900213.pdf
data/synthetic/certificates/SYN-900214.pdf
data/synthetic/certificates/SYN-900215.pdf
data/synthetic/certificates/SYN-900219.pdf
data/synthetic/certificates/SYN-900221.pdf
data/synthetic/certificates/SYN-900223.pdf
data/synthetic/certificates/SYN-900224.pdf
data/synthetic/certificates/SYN-900226.pdf
data/synthetic/certificates/SYN-900228.pdf
data/synthetic/certificates/SYN-900229.pdf
data/synthetic/certificates/SYN-900230.pdf
data/synthetic/certificates/SYN-900231.pdf
data/synthetic/certificates/SYN-900232.pdf
data/synthetic/certificates/SYN-900234.pdf
data/synthetic/certificates/SYN-900235.pdf
data/synthetic/certificates/SYN-900236.pdf
data/synthetic/certificates/SYN-900238.pdf
data/synthetic/certificates/SYN-900239.pdf
data/synthetic/certificates/SYN-900240.pdf
data/synthetic/certificates/SYN-900241.pdf
data/synthetic/certificates/SYN-900242.pdf
data/synthetic/certificates/SYN-900243.pdf
data/synthetic/certificates/SYN-900244.pdf
data/synthetic/certificates/SYN-900245.pdf
data/synthetic/certificates/SYN-900246.pdf
data/synthetic/certificates/SYN-900247.pdf
data/synthetic/certificates/SYN-900252.pdf
data/synthetic/certificates/SYN-900253.pdf
data/synthetic/certificates/SYN-900254.pdf
data/synthetic/certificates/SYN-900255.pdf
data/synthetic/certificates/SYN-900256.pdf
data/synthetic/certificates/SYN-900257.pdf
data/synthetic/certificates/SYN-900259.pdf
data/synthetic/certificates/SYN-900261.pdf
data/synthetic/certificates/SYN-900262.pdf
data/synthetic/certificates/SYN-900263.pdf
data/synthetic/certificates/SYN-900264.pdf
data/synthetic/certificates/SYN-900265.pdf
data/synthetic/certificates/SYN-900266.pdf
data/synthetic/certificates/SYN-900267.pdf
data/synthetic/certificates/SYN-900269.pdf
data/synthetic/certificates/SYN-900270.pdf
data/synthetic/certificates/SYN-900271.pdf
data/synthetic/certificates/SYN-900272.pdf
data/synthetic/certificates/SYN-900273.pdf
data/synthetic/certificates/SYN-900274.pdf
data/synthetic/certificates/SYN-900275.pdf
data/synthetic/certificates/SYN-900276.pdf
data/synthetic/certificates/SYN-900277.pdf
data/synthetic/certificates/SYN-900278.pdf
data/synthetic/certificates/SYN-900279.pdf
data/synthetic/ekt_products.json
data/synthetic/ekt_selection.json
data/synthetic/embeddings.json
data/synthetic/fetch_ekt_selection.py
data/synthetic/generate.py
data/synthetic/images/SYN-900001.svg
data/synthetic/images/SYN-900002.svg
data/synthetic/images/SYN-900003.svg
data/synthetic/images/SYN-900004.svg
data/synthetic/images/SYN-900005.svg
data/synthetic/images/SYN-900006.svg
data/synthetic/images/SYN-900007.svg
data/synthetic/images/SYN-900008.svg
data/synthetic/images/SYN-900009.svg
data/synthetic/images/SYN-900010.svg
data/synthetic/images/SYN-900011.svg
data/synthetic/images/SYN-900012.svg
data/synthetic/images/SYN-900013.svg
data/synthetic/images/SYN-900014.svg
data/synthetic/images/SYN-900015.svg
data/synthetic/images/SYN-900016.svg
data/synthetic/images/SYN-900017.svg
data/synthetic/images/SYN-900018.svg
data/synthetic/images/SYN-900019.svg
data/synthetic/images/SYN-900020.svg
data/synthetic/images/SYN-900021.svg
data/synthetic/images/SYN-900022.svg
data/synthetic/images/SYN-900023.svg
data/synthetic/images/SYN-900024.svg
data/synthetic/images/SYN-900025.svg
data/synthetic/images/SYN-900026.svg
data/synthetic/images/SYN-900027.svg
data/synthetic/images/SYN-900028.svg
data/synthetic/images/SYN-900029.svg
data/synthetic/images/SYN-900030.svg
data/synthetic/images/SYN-900031.svg
data/synthetic/images/SYN-900032.svg
data/synthetic/images/SYN-900033.svg
data/synthetic/images/SYN-900034.svg
data/synthetic/images/SYN-900035.svg
data/synthetic/images/SYN-900036.svg
data/synthetic/images/SYN-900037.svg
data/synthetic/images/SYN-900038.svg
data/synthetic/images/SYN-900039.svg
data/synthetic/images/SYN-900040.svg
data/synthetic/images/SYN-900041.svg
data/synthetic/images/SYN-900042.svg
data/synthetic/images/SYN-900043.svg
data/synthetic/images/SYN-900044.svg
data/synthetic/images/SYN-900045.svg
data/synthetic/images/SYN-900046.svg
data/synthetic/images/SYN-900047.svg
data/synthetic/images/SYN-900048.svg
data/synthetic/images/SYN-900049.svg
data/synthetic/images/SYN-900050.svg
data/synthetic/images/SYN-900051.svg
data/synthetic/images/SYN-900052.svg
data/synthetic/images/SYN-900053.svg
data/synthetic/images/SYN-900054.svg
data/synthetic/images/SYN-900055.svg
data/synthetic/images/SYN-900056.svg
data/synthetic/images/SYN-900057.svg
data/synthetic/images/SYN-900058.svg
data/synthetic/images/SYN-900059.svg
data/synthetic/images/SYN-900060.svg
data/synthetic/images/SYN-900061.svg
data/synthetic/images/SYN-900062.svg
data/synthetic/images/SYN-900063.svg
data/synthetic/images/SYN-900064.svg
data/synthetic/images/SYN-900065.svg
data/synthetic/images/SYN-900066.svg
data/synthetic/images/SYN-900067.svg
data/synthetic/images/SYN-900068.svg
data/synthetic/pictures.py
docs/api.md
docs/architecture.md
docs/assistant-testing.md
docs/backend-integration.md
docs/contracts.md
docs/data-and-db.md
docs/mvp-plan.md
docs/openapi.json
docs/research-ekt-you-aero.md
docs/verification-2026-09-23.md
frontend/.env.example
frontend/.gitignore
frontend/README.md
frontend/next-env.d.ts
frontend/next.config.ts
frontend/package-lock.json
frontend/package.json
frontend/src/app/api/v1/[...path]/route.ts
frontend/src/app/globals.css
frontend/src/app/layout.tsx
frontend/src/app/page.tsx
frontend/src/components/assistant-chat.css
frontend/src/components/assistant-chat.tsx
frontend/src/components/storefront/cart-drawer.tsx
frontend/src/components/storefront/compare-modal.tsx
frontend/src/components/storefront/header.tsx
frontend/src/components/storefront/icons.tsx
frontend/src/components/storefront/product-card.tsx
frontend/src/components/storefront/types.ts
frontend/src/components/storefront/use-dialog.ts
frontend/src/lib/api.ts
frontend/tests/proxy.test.mjs
frontend/tsconfig.json
scripts/build_assistant_fixtures.py
scripts/build_assistant_sheets.mjs
scripts/smoke_attachments.py
scripts/smoke_test.py
scripts/verify_assistant_fixtures.py
test-files/README.md
test-files/assistant/01_small_spec.txt
test-files/assistant/02_large_text.txt
test-files/assistant/03_spec_500_rows.csv
test-files/assistant/04_spec_1200_rows.xlsx
test-files/assistant/05_spec_22_sheets.xlsx
test-files/assistant/06_specification.docx
test-files/assistant/07_catalog_30_pages.pdf
test-files/assistant/08_scanned_spec.pdf
test-files/assistant/09_photo_spec.jpg
test-files/verification.json
презентации/ekt-assistant.pptx
Ветки (2)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.