AAYMA
RU
Войти

EKT AI-консультант

Чат-консультант для ekt.kz в виде расширения Chrome/Edge и виджета: подбирает товары по характеристикам и бюджету, отвечает по страницам магазина…

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

О проекте

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

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

Суть

Чат-консультант для ekt.kz в виде расширения Chrome/Edge и виджета: подбирает товары по характеристикам и бюджету, отвечает по страницам магазина, открывает карточки, добавляет в корзину и заполняет формы.

Как устроено

Скрапер собирает каталог (категория «Лампы», 89 товаров), 123 инфо-страницы и 9 филиалов в Supabase PostgreSQL с чанкингом, эмбеддингами и историей цен. Edge Function на Deno вызывает OpenAI с 12 инструментами (поиск товаров, фасеты, база знаний, филиалы, create_lead, navigate_to, highlight, click_element, fill_form, suggest_replies) и стримит ответ через SSE. Поиск гибридный: точный артикул, полнотекст, обработка опечаток и векторное сходство. После генерации сервер сверяет цены, ссылки и заявленные действия с результатами инструментов; действия на странице ограничены allow-list.

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

  • function calling (12 инструментов)
  • гибридный поиск (FTS + векторы + опечатки)
  • SSE-стриминг
  • hallucination guard
  • UI-действия на сайте через расширение MV3
  • скрапинг и история цен
  • rate limiting
  • eval-сценарии и E2E

Особенности

Агент действует прямо на живом ekt.kz через браузерное расширение (навигация, подсветка, «Купить», заполнение форм) с отменой действий и allow-list; ночное обновление цен в CI и проверка ответа модели на соответствие данным инструментов.

Стек

TypeScript · Supabase · PostgreSQL · Deno Edge Functions · Chrome Extension MV3 · Vercel · GitHub Actions

Модели

OpenAI API


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

README

README.md

EKT AI-консультант

ИИ-консультант для интернет-магазина электротехники ekt.kz. Проект команды Centras AI HUB для хакатона BAITC.

Консультант помогает подобрать товар, узнать характеристики и условия покупки, найти филиал и подготовить заявку. Он использует данные каталога и информационных страниц магазина, а при подключении к ekt.kz умеет выполнять ограниченный набор действий на странице.

Текущий формат демонстрации — расширение Chrome/Edge. У команды сейчас нет доступа к среде сайта для прямого внедрения, поэтому расширение подключает консультанта к ekt.kz в браузере проверяющего. Код сайта при этом менять не требуется. Для штатного подключения предусмотрен тот же виджет через <script>; необходимые доступы перечислены в разделе установки.

Для жюри: установить расширение · сценарий проверки · свой сервер и база · пример переменных окружения · потенциал развития.

1. Название проекта

EKT AI-консультант (ekt-ai-consultant в package.json).

2. Какую проблему решает проект

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

Как проект решает эту проблему. EKT AI-консультант сопровождает покупателя от вопроса до действия на сайте в одном диалоге. Он помогает уточнить запрос, ищет товары по характеристикам и бюджету, показывает цены и ссылки из загруженного каталога, отвечает по информационным страницам магазина. По просьбе покупателя агент выполняет доступные шаги сценария:

  • Подбор и покупка: открывает выбранный товар, подсвечивает цену и характеристики, нажимает «Купить» для добавления в корзину, помогает перейти к корзине или открывает форму «Купить в 1 клик» и заполняет контактные данные.
  • Обращение по возврату: открывает условия возврата, показывает нужный раздел, открывает общую форму «Оставить заявку» и заполняет контакты и текст обращения сведениями, которые сообщил покупатель: товар, номер заказа, дата покупки и причина возврата.
  • Помощь на странице: вводит запрос в поиск и запускает его, показывает способы оплаты, находит контакты филиала и подсвечивает телефон. Если требуется участие менеджера, может сохранить контакт и описание потребности в базе проекта.

Таким образом, агент помогает подготовить заказ или обращение по возврату непосредственно на сайте. Отправку форм и оплату выполняет покупатель; решение по возврату принимает магазин.

Ценность для покупателя:

  • Можно описать потребность своими словами и уточнять выбор в диалоге, сохраняя контекст предыдущих вопросов.
  • Товар, его характеристики, цена и условия покупки доступны в рамках одного сценария; ссылки позволяют сверить ответ с источником.
  • Помощь продолжается после выбора товара: агент выполняет переходы, добавляет товар в корзину и помогает заполнить форму заказа или обращения по возврату. Покупатель сохраняет контроль: переход и нажатие можно отменить, а заполненные данные — проверить перед отправкой.

Ценность для магазина. Консультант помогает покупателю пройти путь от подбора до подготовки заказа и разобраться с обращением после покупки. Типовые вопросы о товарах, условиях покупки и филиалах можно обслуживать через диалог, а в форму обращения передавать уже собранные сведения о потребности или причине возврата. Отдельный инструмент сохраняет заявку с контактами в базе проекта для дальнейшей работы сотрудника. Решение рассчитано на розничных и оптовых покупателей; текущая демонстрация использует категорию «Лампы» и подключается через расширение без изменения сайта.

Примеры результата:

  • «Нужна лампа E27 с тёплым светом до 1000 тенге» → подбор → открытие карточки → добавление в корзину → помощь с подготовкой заказа.
  • «Хочу вернуть лампу» → условия возврата → уточнение сведений о покупке → открытая и заполненная форма обращения, которую покупатель проверяет и отправляет.

Ценность прототипа — помощь в прохождении этих действий в контексте одного диалога. Влияние на конверсию, время оформления и нагрузку менеджеров предстоит измерить в пилоте.

3. Что реализовано

ВозможностьРеализация
Подбор товаровПоиск по запросу и артикулу; фильтры по бренду, категории, бюджету и характеристикам. Карточки с ценой, артикулом и ссылкой на источник.
Ответы о магазинеПоиск по информационным страницам: оплата, доставка, возврат, оформление заказа; отдельный инструмент для адресов и контактов филиалов.
ДиалогПотоковый ответ, контекст предыдущих сообщений, подсказки для продолжения, оценки ответов. Интерфейс и инструкции для русского, казахского и английского языков.
Действия на сайтеПереход к товару или служебной странице, подсветка элементов, заполнение и отправка поиска, нажатие «Купить», открытие и заполнение разрешённых форм. Перед переходом и нажатием есть возможность отмены. Формы заявки и покупки в один клик пользователь отправляет самостоятельно.
Заявка менеджеруИнструмент create_lead записывает контакт и запрос в таблицу ekt.leads. Промпт требует согласия покупателя; сервер проверяет телефон и ограничивает число заявок.
Подключение к сайтуВиджет через <script> и распаковываемое расширение Chrome/Edge Manifest V3. История диалога восстанавливается после переходов.
Подготовка данныхСкрапер HTML, загрузка в базу, разбиение страниц на фрагменты, эмбеддинги, журнал обновлений и история изменения цен.
ПроверкиМодульные тесты, проверка типов, smoke-тест API, набор eval-сценариев, браузерные E2E-сценарии и конфигурация CI.

Реализация функций не означает, что все сценарии проходят без ошибок: результаты сохранённых прогонов и ограничения приведены ниже.

В сервере реализовано 12 инструментов, доступных модели — см. tools.ts:

ИнструментКонкретная функция
search_productsНайти товары по запросу с фильтрами по цене, бренду, категории и характеристикам
get_productПолучить подробную карточку конкретного товара
category_facetsУзнать, какие характеристики и значения есть у товаров выбранной категории
list_categoriesПолучить корневые разделы и подкатегории каталога
search_knowledgeНайти фрагменты информационных страниц с заголовками и ссылками
get_branchesНайти адрес, телефон, email и часы работы филиала по городу
create_leadСохранить заявку с контактами и потребностью в базе проекта
navigate_toОткрыть разрешённую страницу ekt.kz, например карточку товара или условия возврата
highlightПодсветить цену, характеристики, телефон, кнопку или другой разрешённый элемент
click_elementНажать «Купить», выполнить поиск либо открыть форму заявки или покупки в один клик
fill_formЗаполнить разрешённые поля поиска, заявки или покупки в один клик; формы обращения не отправляются автоматически
suggest_repliesПоказать варианты следующего сообщения покупателя

Что агент может сделать непосредственно на странице:

  • Открыть найденный товар, главную страницу, категорию «Лампы», корзину, условия возврата, оплату, оформление заказа, контакты или FAQ. Переходы ограничены разрешёнными адресами ekt.kz.
  • Подсветить цену, кнопку «Купить», характеристики, описание, условия возврата, способы оплаты, телефон, список товаров, поле поиска или корзину.
  • Ввести запрос в поиск сайта и выполнить поиск; на карточке товара нажать «Купить» для добавления в корзину.
  • Открыть «Оставить заявку» и заполнить имя, email, телефон и текст обращения; открыть «Купить в 1 клик» и заполнить имя, телефон и email. Возврат оформляется как текст обращения в общей форме заявки: отдельной формы возврата агент не создаёт.
  • Предложить до четырёх вариантов следующей реплики, сохранить контекст диалога при переходе и выполнить отложенную подсветку или заполнение на открытой странице.

Нажатие «Купить» добавляет товар в корзину, но не оплачивает и не завершает заказ. Формы обращения пользователь отправляет сам. Агент не получает произвольного доступа к браузеру: доступны только перечисленные адреса, элементы и поля. Сбор каталога и обновление цен выполняются отдельными скриптами, а не во время каждого сообщения покупателя.

4. Как работает решение

Пример запроса: «Нужна светодиодная лампа E27, тёплый свет, до 1000 тенге».

  1. Покупатель открывает виджет и отправляет сообщение. Виджет передаёт текст, идентификатор диалога и контекст страницы в API чата.
  2. Сервер добавляет историю диалога и инструкции консультанта. Модель выбирает инструменты: например, поиск товаров или получение карточки по артикулу.
  3. Инструменты получают сведения из PostgreSQL. Поиск объединяет точное совпадение артикула, полнотекстовый поиск, обработку опечаток и векторное сходство.
  4. Модель формирует ответ на основе найденных данных. Виджет получает текст через SSE и отображает карточки найденных товаров.
  5. По следующей просьбе — например, «Открой карточку» — сервер может передать разрешённое действие интерфейсу. На ekt.kz виджет выполняет его; на отдельной демостранице переход к ekt.kz предлагается ссылкой.
  6. Если вопрос требует участия менеджера, консультант может собрать данные для заявки. Запись заявки в БД и заполнение формы на сайте — разные механизмы; отправка формы остаётся за покупателем.

После генерации сервер сверяет цены, ссылки и заявления о действиях с результатами инструментов. Несоответствия сохраняются как диагностические флаги, но уже показанный текст автоматически не исправляется.

5. Технологии

КомпонентТехнологии
ЯзыкиTypeScript, JavaScript, SQL, HTML, CSS
Скрапер и служебные скриптыNode.js, tsx, Cheerio, dotenv
Сервер чатаSupabase Edge Functions, Deno 2, OpenAI Chat Completions API с вызовом инструментов
AI-модели по умолчаниюgpt-4.1-mini для диалога; text-embedding-3-small для эмбеддингов размерности 1536
Данные и поискSupabase PostgreSQL, схема ekt, pgvector, pg_trgm, полнотекстовый поиск russian, Reciprocal Rank Fusion. В локальной конфигурации указан PostgreSQL 17.
КлиентTypeScript без UI-фреймворка, Shadow DOM, SSE, localStorage; сборка esbuild
Расширение браузераChrome Extension Manifest V3, подключение того же виджета к ekt.kz
ПроверкиVitest, happy-dom, Deno test/check, Playwright Core и установленный браузер для E2E
Окружениеnpm, Supabase CLI, Docker для локального Supabase; GitHub Actions; конфигурация публикации статики в Vercel

Версии зависимостей зафиксированы в package-lock.json. Модели и серверные параметры задаются через окружение; смена модели эмбеддингов должна учитывать размерность в схеме БД.

6. Архитектура проекта

flowchart LR
    Site[Страницы ekt.kz] --> Scraper[Скрапер HTML]
    Scraper --> Files[JSONL в data/]
    Seed[Снимок seed/] --> Ingest[Загрузчик данных]
    Files --> Ingest
    Ingest --> DB[(PostgreSQL / схема ekt)]
    Ingest --> Embeddings[OpenAI Embeddings]
    Embeddings --> Ingest
    User[Покупатель] --> Widget[Виджет / расширение]
    Widget -->|HTTP-запрос| Chat[Edge Function chat]
    Chat <-->|Вызовы инструментов| Model[OpenAI Chat Completions]
    Chat <-->|Каталог, знания, история, заявки| DB
    Chat -->|SSE: текст, карточки, действия| Widget
ПутьНазначение
scraper/src/Сбор и разбор страниц, подготовка записей, загрузка данных и эмбеддингов
seed/Снимок данных для воспроизведения без повторного обхода ekt.kz
supabase/migrations/Таблицы, права доступа и SQL-функции поиска
supabase/functions/chat/API, промпт, 12 инструментов, клиент OpenAI, SSE, ограничения запросов и постпроверка
web/src/Чат-виджет, локализация, сохранение диалога и выполнение действий
web/public/Демо, страница проверки встраивания и результат сборки widget.js
extension/Расширение для подключения виджета к настоящему сайту
scripts/Локальная установка, smoke-тест, проверка поиска, обновление снимка
eval/, e2e/Проверки ответов и пользовательских сценариев
.github/workflows/CI и расписание обновления данных

Браузер обращается к функции чата, а не напрямую к таблицам. Ключ OpenAI и ключ Supabase service_role нужны серверу и загрузчику данных; в настройки виджета они не передаются.

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

Быстрая установка расширения для жюри

В системе нужны: Chrome или Microsoft Edge с возможностью загрузки распакованного расширения, доступ к интернету, ekt.kz и облачному API команды. Готовая сборка extension/widget.js уже находится в репозитории: для её установки Node.js, Docker, аккаунт Supabase и собственный ключ OpenAI не нужны.

  1. Скачайте репозиторий через Code → Download ZIP и распакуйте архив либо клонируйте его через Git.
  2. Откройте chrome://extensions в Chrome или edge://extensions в Edge.
  3. Включите «Режим разработчика».
  4. Нажмите «Загрузить распакованное» и выберите именно папку extension/, содержащую manifest.json, content.js, widget.js и icons/.
  5. Откройте или обновите категорию «Лампы» на ekt.kz. Справа внизу должна появиться кнопка «Задать вопрос».
  6. Отправьте: «Покажи цену и характеристики товара с артикулом 080300163_», затем «Открой карточку и покажи цену».

Расширение действует только на https://ekt.kz/* и https://www.ekt.kz/*. Оно использует API из extension/content.js. Если виджет появился, но ответа нет, проверьте health API; для независимого от стенда команды запуска используйте вариант B или C ниже. В управляемом корпоративном браузере загрузка расширений может требовать разрешения администратора.

Требования для сборки и собственного сервиса

  • Node.js 22.12+ в ветке 22 либо Node.js 24, npm, Git. Хотя package.json объявляет Node.js ≥20, текущие зависимости в lock-файле требуют более новую версию.
  • Для полноценного локального сервиса: запущенный Docker Desktop или совместимый Docker Engine, интернет для загрузки образов и запросов OpenAI, собственный OPENAI_API_KEY с доступом к указанным моделям.
  • Supabase CLI входит в зависимости проекта; команды вызываются через npx supabase.
  • Отдельный Deno 2 нужен для deno check и deno test, но не для запуска функции через Supabase CLI.
git clone https://github.com/BAITC-Hacks/hack-b0093e63-centras-ai-hub.git
cd hack-b0093e63-centras-ai-hub
npm ci

Выберите один из трёх вариантов ниже. Для воспроизведения всей цепочки с собственной базой используйте вариант B.

A. Демонстрация интерфейса без ключей и Docker

В первом терминале:

node web/dev/mock-server.mjs

Во втором терминале, из корня проекта:

npm run dev:web

Откройте демо с mock API или страницу проверки действий.

Mock API работает на порту 8787 и возвращает заранее заданные ответы. Этот режим позволяет проверить интерфейс и действия, но не качество AI, поиск по базе или создание настоящих заявок.

B. Полный локальный сервис: база → данные → API → виджет

Шаг 1. Создайте локальный файл настроек из .env.example.

PowerShell:

Copy-Item .env.example .env.local

Bash / zsh:

cp .env.example .env.local

Отредактируйте .env.local: заполните OPENAI_API_KEY, оставьте модели по умолчанию и ALLOWED_ORIGINS. Для этого варианта удалите строки SUPABASE_* с облачными заглушками: адреса и ключи локального Supabase определит CLI. Не используйте терминал с экспортированными переменными чужого облачного проекта.

ПеременнаяЧто указать
OPENAI_API_KEYСобственный секретный ключ OpenAI, обязателен для настоящего чата
OPENAI_MODELgpt-4.1-mini
OPENAI_EMBEDDING_MODELtext-embedding-3-small
ALLOWED_ORIGINSЗначение из примера уже включает http://localhost:5173, https://ekt.kz и https://www.ekt.kz
CHAT_URLМожно оставить пустым; для smoke/eval ниже адрес задаётся явно

Шаг 2. Запустите Docker и подготовьте базу.

npm run setup:local

Скрипт проверяет Docker, запускает Supabase, применяет миграции и загружает seed/, создавая эмбеддинги через OpenAI. Локальные реквизиты записываются в .env.local.generated; исходный .env.local сохраняется.

setup:local выполняет supabase db reset --local: повторный запуск удаляет данные локальной БД и загружает снимок заново. Для обычного возобновления контейнеров используйте npx supabase start.

Без ключа OpenAI скрипт может загрузить данные без эмбеддингов, но полноценный AI-чат от этого не заработает. Вариант npm run setup:local -- --no-embed пропускает создание эмбеддингов при первоначальной загрузке.

Шаг 3. В отдельном терминале запустите API и оставьте его работающим.

npm run serve:fn

Команда читает .env.local. Локальный адрес API: http://127.0.0.1:54321/functions/v1/chat.

Шаг 4. В ещё одном терминале запустите интерфейс.

npm run dev:web

Откройте локального консультанта. Параметр ?api= обязателен для этого варианта: без него демостраница использует сохранённый облачный API команды.

КомпонентЛокальный адрес
Демоlocalhost:5173
Проверка APIchat/health
Supabase Studio127.0.0.1:54323

В ответе /health проверьте ok: true, db: true, openai_key: true. Последнее поле подтверждает наличие ключа в настройках, а не успешный запрос к OpenAI; это проверяется сообщением в чат или smoke-тестом.

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

node --env-file=.env.local.generated --import tsx scraper/src/ingest.ts --dir seed

Здесь локальные реквизиты передаются загрузчику явно: ingest сам не читает .env.local.generated. Не экспортируйте облачные SUPABASE_* в этом терминале — переменные процесса имеют приоритет над файлом.

Для остановки завершите процессы API и интерфейса через Ctrl+C, затем выполните npx supabase stop.

C. Собственный облачный Supabase

  1. Создайте проект Supabase. Скопируйте .env.example в .env.local и заполните SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY. Project ref и пароль БД понадобятся при привязке CLI.

  2. Авторизуйте CLI и примените миграции:

    npx supabase login
    npx supabase link --project-ref <project-ref>
    npm run db:push
    

    Команда link может запросить пароль базы. Supabase CLI не получает все переменные автоматически из .env.local; для авторизации здесь используется login.

  3. В настройках Data API проекта добавьте ekt в Exposed schemas, затем загрузите снимок:

    npm run ingest:seed
    
  4. Создайте .env.function.local с OPENAI_API_KEY, OPENAI_MODEL, OPENAI_EMBEDDING_MODEL и ALLOWED_ORIGINS. Это отдельный файл только для секретов функции; не копируйте туда токен CLI, пароль БД или [скрыто]. Укажите в ALLOWED_ORIGINS фактические адреса страниц с виджетом.

    npx supabase secrets set --env-file .env.function.local
    npm run fn:deploy
    
  5. Задайте собственный URL https://<project-ref>.supabase.co/functions/v1/chat в <meta name="ekt-api"> файла web/public/index.html. Для расширения замените API в extension/content.js. Параметр ?api= демостраницы принимает только локальные HTTP-адреса и не переключает её на произвольный облачный проект.

  6. Выполните npm run smoke, затем npm run dev:web и откройте демо. Для smoke оставьте CHAT_URL пустым либо задайте свой адрес явно, чтобы он соответствовал выбранному проекту.

Подключение на настоящий сайт

Для демонстрации используйте готовое расширение. Если меняли исходники виджета, сначала пересоберите его:

npm run build:web

Сборка создаёт web/public/widget.js и обновляет extension/widget.js. Откройте chrome://extensions или edge://extensions, включите режим разработчика, выберите «Загрузить распакованное» и укажите папку extension/. После этого откройте категорию «Лампы».

Подробности — в инструкции расширения. По умолчанию оно подключается к облачному API команды. Для собственного API измените extension/content.js и перезагрузите расширение.

Что потребуется от владельца системы для прямого внедрения:

  • Доступ к шаблону сайта, чтобы подключить скрипт виджета, и возможность проверить его на тестовой странице.
  • HTTPS-хостинг для widget.js и работающий HTTPS API чата.
  • Настроенный Supabase со схемой ekt, миграциями и загруженными данными; серверный ключ OpenAI. Порядок — вариант C, переменные — .env.example.
  • Добавление домена сайта в ALLOWED_ORIGINS; если на сайте действует Content Security Policy, разрешение загрузки скрипта и подключения к API.
  • Проверка соответствия разметки сайта разрешённым целям в web/src/actions.ts. Для другого сайта потребуется адаптация селекторов и серверного списка разрешённых адресов и действий.

После получения доступа разместите widget.js на HTTPS-хостинге и добавьте в шаблон страницы:

<script src="https://<хостинг-виджета>/widget.js"
        data-api="https://<project-ref>.supabase.co/functions/v1/chat"
        data-lang="ru"
        defer></script>

Для публикации демо подготовлен vercel.json: команда сборки npm run build:web, каталог публикации web/public. Сам конфигурационный файл не подтверждает, что сайт опубликован.

8. Как проверить решение

Сценарий для жюри

Основной путь для жюри — установить расширение и пройти сценарий на ekt.kz. Оно использует API команды; альтернативно можно развернуть собственный API по варианту B или C. Mock-режим для проверки поиска не подходит.

ШагДействиеЧто проверить
1«Нужна светодиодная лампа E27, тёплый свет, до 1000 тенге»Ответ содержит найденные товары, цены в тенге и ссылки на ekt.kz. Сравните характеристики с карточками.
2«Покажи цену и характеристики товара с артикулом 080300163_»В снимке это PHILIPS Ecohome A60, E27, 11 Вт, 3000 K; price_site равна 800 ₸. Для обновлённой базы цена может отличаться.
3«Какие условия возврата?»Консультант использует информационные страницы магазина.
4«Где ваш филиал в Астане?»Ответ содержит адрес и контакты из данных филиалов.
5«Найди товар с артикулом TEST-NOT-EXIST-999»Проверка реакции на отсутствие данных: консультант не должен придумывать карточку и цену.

Чтобы проверить действия на ekt.kz с расширением, попросите открыть найденную карточку, затем показать цену. Для проверки формы попросите открыть заявку: проверьте её отображение и возможность заполнения. Нажатие «Купить» может изменить настоящую корзину, а отправка формы — создать обращение на сайте. Для демонстрации этих действий без обращения в магазин используйте локальный embed.html с mock API.

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

Тесты и проверка типов без обращения к живому AI:

npm test
npm run typecheck
npm run build:web

При установленном Deno 2:

deno check supabase/functions/chat/index.ts
deno test supabase/functions/chat/

Smoke-тест и eval обращаются к работающему API. Для локального сервиса задайте адрес явно.

PowerShell:

$env:CHAT_URL = "http://127.0.0.1:54321/functions/v1/chat"
npm run smoke
npm run eval

Bash / zsh:

export CHAT_URL=http://127.0.0.1:54321/functions/v1/chat
npm run smoke
npm run eval

smoke проверяет health, ответ с товаром и ссылкой, а также обработку некорректного запроса. eval выполняет сценарии из eval/questions.json, перезаписывает eval/report.json и завершается с ошибкой при результате ниже 80%. Eval автоматически читает .env, но не .env.local, поэтому выше используется явный CHAT_URL. Сценарий lead-flow-wholesale создаёт тестовую запись в ekt.leads.

Дополнительно доступны npm run e2e:api для контракта действий API и npm run e2e для браузерных сценариев на настоящем ekt.kz. Браузерный прогон требует установленного Chrome/Edge и сборки виджета; он может добавить товар в реальную корзину тестового браузера и обновляет файлы отчётов и скриншотов.

Сохранённые результаты, а не гарантия текущего состояния:

  • eval/RESULTS.md: 41 из 42 сценариев, 97,6%, прогон от 23.09.2026. Зафиксирована ошибка подбора лампы по сочетанию характеристик.
  • e2e/RESULTS.md: последний сохранённый браузерный прогон от 23.09.2026, 12:01 UTC — 14 из 14 проверок, PASS. Проверены ответ с карточкой/ссылкой, переход к тому же товару, подсветка, добавление в корзину, открытие и заполнение формы возврата, переход к оплате и поиск на сайте.
  • При обновлении README 23.09.2026 повторно выполнен npm run smoke против облачного API — 5 из 5 проверок, PASS: health, ответ с товарами и ссылкой, три некорректных запроса с ожидаемым HTTP 400.
  • docs/README-VERIFICATION.md: журнал проверки более раннего коммита; полный локальный Docker-стек в том прогоне не запускался.

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

9. Данные и интеграции

Данные для воспроизведения

В seed/ хранится снимок ekt.kz от 23.09.2026:

ФайлСодержимоеЧисло записей
products.jsonlТовары демонстрационной выборки категории «Лампы»89
categories.jsonlКатегории и пути каталога24
pages.jsonlИнформационные страницы123
branches.jsonФилиалы9

Это статический снимок, а не весь ассортимент магазина. Фрагменты страниц и эмбеддинги создаются при загрузке; готовые векторы в снимок не включены.

Какие именно данные доступны:

  • Товары: светодиодные, галогенные, газоразрядные, люминесцентные, бактерицидные лампы и лампы накаливания. В характеристиках встречаются цоколи E14, E27, E40, GX53, GU10, GU5.3, R7s, G13; бренды MEGALIGHT, OSRAM, KODAK, Philips, IEK, Gauss. У части записей бренд или отдельные характеристики не заполнены.
  • Поля товара: название, артикул и артикул поставщика, бренд, цена сайта и магазина в KZT, кратность покупки, описание, характеристики, категория, ссылка и URL изображения. Например, у лампы Philips 080300163_ в снимке указаны E27, 11 Вт, 3000 K и цена сайта 800 ₸.
  • Информационные страницы: FAQ, оформление заказа, оплата, возврат и контакты; «О компании», собственные торговые марки, производство, технические материалы, статьи и новости. Например, есть страницы «Производство электрощитового оборудования» и «Кабельно-проводниковая продукция». Упоминание кабеля в справочной статье не означает, что его товарная карточка загружена в каталог.
  • Филиалы: Алматы, Астана, Шымкент, Актау, Атырау, Тараз, Усть-Каменогорск, Караганда и Талдыкорган. Записи содержат адреса, телефоны, email и график работы.

Эти количества описывают файлы в репозитории. Состав работающей облачной БД может отличаться после обновлений и здесь отдельно не подтверждается.

Внешние системы

СистемаИспользование
ekt.kzSitemap, HTML карточек и информационных страниц, контакты филиалов, ссылки и изображения товаров. Сбор данных выполняется парсерами без LLM.
OpenAI APIГенерация ответов, выбор инструментов и создание эмбеддингов. Полный локальный запуск также обращается к этому внешнему сервису.
SupabaseХранение каталога, знаний, диалогов, оценок, заявок и истории цен; SQL-поиск и API чата. Можно использовать облачный проект либо локальные контейнеры.
GitHub ActionsCI и подготовленное расписание обновления категории «Лампы»; требует настройки секретов репозитория.
VercelПодготовлена конфигурация хостинга демо и виджета; подтверждённого адреса публикации в репозитории нет.

Обновление данных

Настройки категории, ограничения числа товаров и частоты запросов приведены в .env.example. Скопированный пример настраивает сбор категории «Лампы» с лимитом 100 товаров.

npm run scrape
npm run ingest

npm run refresh выполняет обе команды последовательно. Сбор сохраняет результат в data/, загрузчик читает реквизиты из .env.local / .env. Для локальной БД после setup:local вместо обычного npm run ingest используйте:

node --env-file=.env.local.generated --import tsx scraper/src/ingest.ts

Загрузчик сравнивает содержимое записей, обновляет эмбеддинги и сохраняет изменения цен в ekt.price_history. Команда npm run seed:update отдельно заменяет файлы снимка в репозитории результатом из data/.

Workflow refresh-data.yml задаёт ежедневный запуск в 22:15 UTC (03:15 по Алматы) для категории «Лампы». Нужны секреты SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY. Наличие workflow не подтверждает, что секреты настроены или обновления фактически выполняются.

Скрапер содержит исключения для служебных страниц, закрытых в robots.txt. Переменная SCRAPER_SKIP_SERVICE_PAGES=1 отключает их сбор.

10. Ограничения текущей версии

  • Ограниченный каталог. Снимок содержит 89 товаров; ответы о других категориях зависят от данных, загруженных в конкретную БД.
  • Нет оперативных складских остатков. Цена — значение из последней загрузки, а не гарантия текущей цены или наличия. Отдельной интеграции с учётной системой магазина нет.
  • Ошибки AI возможны. Качество подбора зависит от поиска и модели. Постпроверка сохраняет диагностические флаги после генерации, но не блокирует неверный ответ.
  • Действия зависят от сайта. Виджет использует селекторы текущей разметки ekt.kz; изменения сайта могут нарушить подсветку и заполнение. Выдача сервером команды не подтверждает её успешное выполнение браузером.
  • Заявки хранятся в БД. Отдельного кабинета менеджера, интеграции CRM и автоматической отправки заявок по email или в мессенджер в текущей реализации нет. Их можно просматривать в таблице ekt.leads через Supabase Studio.
  • Согласие контролируется не полностью. Запрос согласия предусмотрен промптом; отдельной серверной проверки факта согласия для create_lead нет.
  • История и контакты сохраняются. Диалоги записываются на сервере и в браузере; введённые в чат персональные данные могут попасть в историю сообщений, а не только в заявку.
  • Есть лимиты. До 2000 символов в сообщении, 12 предыдущих сообщений в контексте, 5 раундов инструментов, 20 сообщений в минуту на сессию, 60 на IP и 3 заявки на сессию — см. config.ts.
  • Требуются внешние сервисы. Для настоящего чата нужен работающий OpenAI API; локальная база не делает решение полностью автономным. Mock-режим не заменяет AI-проверку.
  • Не все способы запуска подтверждены сквозным прогоном. Инструкция локального Docker-стека составлена по скриптам и конфигурации. Сохранённый журнал верификации не подтверждает полный запуск этого варианта; успешные браузерные проверки относятся к сценарию с облачным API.

11. Развёрнутая версия

В исходниках демостраницы и расширения указан следующий адрес; в репозитории есть отчёты обращений к нему от 23.09.2026:

КомпонентСсылка / способ доступа
Облачный API чатаSupabase Edge Function chat — POST, ответ SSE; это не веб-страница чата
Проверка состоянияHealth-check
Интерфейс для этого APInpm ci → npm run dev:web → localhost:5173 без параметра ?api=
Консультант поверх ekt.kzИнструкция установки расширения

Работа с облачным API проверена на живом ekt.kz. Последний сохранённый E2E-прогон от 23.09.2026 завершился результатом 14/14 PASS: консультант показал товар, перешёл к его карточке, подсветил цену, добавил товар в корзину, открыл и заполнил форму возврата, перешёл к условиям оплаты и выполнил поиск. Результаты и пути к скриншотам — в e2e/RESULTS.md. Отдельный повторный smoke-тест облачного API при обновлении README завершился 5/5 PASS.

Для проверки жюри консультант поставляется как расширение Chrome/Edge, устанавливаемое в режиме разработчика. Оно подключает виджет поверх настоящего сайта без изменения его серверной части. Автоматический E2E-тест внедряет ту же сборку виджета в страницу через Playwright; он проверяет взаимодействие с живым сайтом и API, но не автоматизирует установку расширения в интерфейсе браузера. Доступа к среде сайта для штатного подключения у команды сейчас нет, поэтому основной способ демонстрации — расширение. После предоставления доступа тот же виджет можно подключить непосредственно в шаблон сайта по инструкции выше.

12. Потенциал развития и масштабирования

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

Общая основа уже разделена на сбор данных, поиск, диалог с инструментами и выполнение действий в браузере. Сейчас парсеры, промпт, адреса и элементы интерфейса настроены под ekt.kz. Для подключения другой компании потребуется адаптация этих частей. Следующий этап — вынести такие настройки в отдельные профили сайтов и подтвердить переносимость на втором проекте.

Общая логика для разных компаний

Слой решенияЧто можно использовать повторноЧто настраивается под компанию
Сбор данныхОбход страниц, извлечение содержимого, подготовка записей и повторная загрузкаРазрешённые источники, структура сайта, HTML-парсеры, поля товаров или услуг, расписание обновления
База знаний и поискРазбиение текстов на фрагменты, эмбеддинги, сочетание текстового и векторного поискаКаталог, характеристики, справочные документы, условия обслуживания; при другой предметной области — схема данных и фильтры
КонсультацияИстория диалога, уточнение запроса, вызов инструментов, ответы по найденным сведениям и ссылки на источникиТерминология, язык общения, правила компании, границы консультации и условия передачи вопроса сотруднику
Действия на сайтеПереход, подсветка, нажатие, заполнение разрешённых полей и подсказки следующего шагаДомены, страницы, селекторы элементов, формы, допустимые действия и необходимые подтверждения
Работа с обращениямиСбор контактов и описание потребности в контексте диалогаПоля заявки, ответственный отдел, способ обработки; при дальнейшем развитии — передача в CRM или сервисную систему через API
Проверка качестваТесты контрактов, сценарии диалога, проверки ссылок и браузерные прогоныКонтрольные вопросы, ожидаемые товары или услуги, правила компании и действия на её сайте

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

Где может применяться этот подход

Ниже — возможные сценарии после адаптации; это направления развития, а не уже подключённые компании или готовые интеграции.

НаправлениеПример задачи пользователяКак помогает агент
Интернет-магазины техники, мебели, стройматериаловПодобрать товар под параметры и бюджет, подготовить заказ или обращение по возвратуНаходит варианты, объясняет характеристики и условия, открывает карточку, помогает с корзиной и формой обращения
B2B-поставщики и производителиНайти продукцию по характеристикам и запросить коммерческое предложениеИщет по каталогу и техническим материалам, уточняет количество и требования, готовит заявку отделу продаж
Сервисные компанииВыбрать услугу, узнать условия и оставить запросОбъясняет состав услуги по данным компании, помогает выбрать подходящее направление и заполнить форму; подтверждение записи требует связи с системой расписания
Образовательные организацииПодобрать программу и узнать условия поступления или обученияСопоставляет запрос с описаниями программ, показывает требования и сроки из опубликованных материалов, помогает подготовить обращение
Корпоративные порталыНайти инструкцию или оформить внутреннюю заявкуНаходит регламент, открывает нужный раздел и помогает заполнить форму; такой сценарий требует авторизации и учёта прав сотрудника

Как подключать новый сайт

  1. Выбрать конкретный пользовательский сценарий. Например, подбор товара и заявка на расчёт. Определить, какой результат должен получить пользователь и какие действия остаются за ним или сотрудником компании.
  2. Подготовить источники. Согласовать сбор доступных страниц, настроить парсеры и загрузить каталог, услуги, контакты и правила обслуживания. Если компания предоставляет API или выгрузку, разработать соответствующий загрузчик вместо разбора HTML для этих данных.
  3. Настроить инструменты. Сопоставить поиск с полями компании, а действия — с её страницами, кнопками и формами. Задать разрешённые домены, поля и условия подтверждения. Подключение нового сайта не должно открывать агенту произвольный доступ ко всем действиям браузера.
  4. Провести пилот. Для проверки в контролируемом браузере адаптировать расширение, включая список доменов. Для штатной работы с посетителями подключить виджет в шаблон сайта с согласия владельца и настроить доступ к API.
  5. Проверить результат на реальных сценариях. Подтвердить точность ответов, корректность заполнения, обработку ошибок и передачу обращения. После этого согласовать регулярное обновление данных и ответственность за обработку заявок.

Этапы развития после хакатона

Этап 1 — переносимость на второй сайт. Вынести привязки к EKT в профиль компании: источники, правила консультации, домены, маршруты, селекторы и формы. Адаптировать структуру данных там, где каталог отличается. Проверить обновление отдельных категорий без отключения остальных товаров. Критерий результата — тот же основной код обслуживает два разных сайта с отдельными настройками и проверенными сценариями.

Этап 2 — связь с рабочими системами бизнеса. Добавить согласованные интеграции с CRM, каталогом или учётной системой, чтобы получать актуальные сведения и передавать обращения ответственным сотрудникам. Расширение действий — создание заказа, подтверждение записи или регистрация возврата — возможно только при наличии соответствующего API, прав доступа и подтверждения пользователя. В текущей версии агент помогает с корзиной и формами; эти будущие операции пока не реализованы.

Этап 3 — обслуживание нескольких компаний. Добавить изоляцию данных, истории, ключей и настроек каждой организации; роли сотрудников; управление источниками и версиями сценариев; отдельные лимиты и учёт использования. Сейчас готового режима обслуживания нескольких организаций и кабинета для самостоятельного подключения компаний нет. На первом этапе возможны отдельные развёртывания с адаптацией под каждого заказчика.

Этап 4 — измеримое качество и управляемые расходы. Собирать показатели успешного поиска и завершения сценариев, долю обращений к сотруднику, время до результата, частоту ошибок действий и стоимость обслуживания диалога. Сравнивать их с исходным процессом компании. Такие измерения позволят выбирать дальнейшие улучшения по результатам пилота и обосновывать экономическую ценность внедрения.

Ценность масштабирования

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

Для развития продукта ценность заключается в повторном использовании общей технической основы: опыт подключения одного сайта, проверенные инструменты и сценарии становятся базой для следующих внедрений. Практическую универсальность нужно подтвердить пилотами на разных сайтах; текущий проект уже даёт исходную реализацию консультаций, сбора данных и действий, на которой можно строить такие пилоты.

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

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

Тамерлан 37yensepbaymeirambek 6vkhan-dot 5

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

  • 2026-09-23 17:27docs: describe cross-site growth and integration roadmapТамерлан
  • 2026-09-23 17:22docs: clarify value and purchase and return workflowsТамерлан
  • 2026-09-23 17:12docs: document agent capabilities and technical evaluationТамерлан
  • 2026-09-23 17:07docs: README updates; ailem evidence factsvkhan-dot
  • 2026-09-23 17:07docs: README updates; ailem evaluation report and evidence snapshotsyensepbaymeirambek
  • 2026-09-23 17:01test(e2e): wait for stream end (aria-busy); final live ekt.kz run 14/14Тамерлан
  • 2026-09-23 17:01fix(widget): persist deferred actions before navigation, keep product cards across pagesТамерлан
  • 2026-09-23 16:49test(e2e): final run on live ekt.kzТамерлан
Все коммиты (48)
  • 2026-09-23 16:40docs: README rewriteТамерлан
  • 2026-09-23 16:40fix(chat): navigate supersedes on-site search in the same turnТамерлан
  • 2026-09-23 16:39perf(widget): act immediately — no plate for fill/highlight/search, 1 s navigateТамерлан
  • 2026-09-23 16:37test(e2e): wait for filled values, accept product cardТамерлан
  • 2026-09-23 16:34fix(widget): buy actions only on product page, cancel pending actions on new inputТамерлан
  • 2026-09-23 16:33fix(chat): default highlight on navigate, show card of the navigated productТамерлан
  • 2026-09-23 16:27test(e2e): real ekt.kz browser scenarios and API action contract checksТамерлан
  • 2026-09-23 16:27fix(chat): always submit site search after filling itТамерлан
  • 2026-09-23 16:27docs: README verified against a clean clone — fix commands and numbersyensepbaymeirambek
  • 2026-09-23 16:27fix(deps): sync package-lock with package.json so npm ci works on a clean clonevkhan-dot
  • 2026-09-23 16:23fix(chat): accept relative navigate paths, trigger scenario actions on first turnТамерлан
  • 2026-09-23 16:17feat(widget): UI actions on the real ekt.kz (navigate/highlight/click/fill/suggest) + Chrome extensionТамерлан
  • 2026-09-23 16:03fix(chat): no claimed actions without tools, canonical navigate URLs, less narrationТамерлан
  • 2026-09-23 15:57fix(search): boost all-terms full-text matchesТамерлан
  • 2026-09-23 15:56docs(plan): pivot — consultant acts on the real ekt.kz via browser extension; real-site selectorsТамерлан
  • 2026-09-23 15:55fix(search): unit-aware attribute filters and OR full-text recallТамерлан
  • 2026-09-23 15:46test(eval): focus eval suite on category «Лампы» and record live resultsТамерлан
  • 2026-09-23 15:44feat(chat): navigate/highlight UI action tools with URL allow-listyensepbaymeirambek
  • 2026-09-23 15:44docs: README restructured by jury criteria (implemented, architecture, data, run, verify, limitations)vkhan-dot
  • 2026-09-23 15:32docs(plan): extend UI actions contract — click, fill, filter, suggest; scenario playbookТамерлан
  • 2026-09-23 15:31docs: plan for consultant UI actions (navigate/highlight) and demo storefrontТамерлан
  • 2026-09-23 15:25feat: one-command local setup from seed data, smoke test, daily price-check workflowТамерлан
  • 2026-09-23 15:19data: seed snapshot — 89 products of category «Лампы», 123 info pages, 9 branches (2026-09-23)Тамерлан
  • 2026-09-23 15:16feat(ingest): detect price changes, price history, --dir for seed dataТамерлан
  • 2026-09-23 15:15feat(chat): expose recent price changes in tools and promptТамерлан
  • 2026-09-23 15:11feat(scraper): single-category mode with product cap and tracked-first ordering; price history migration; planТамерлан
  • 2026-09-23 15:08feat: store order_note ("Под заказ") for products without price; expose in search and chat toolsyensepbaymeirambek
  • 2026-09-23 15:08feat(scraper): robust page extraction, 60s timeout, ekt schema in ingest; remove debug scriptvkhan-dot
  • 2026-09-23 15:00docs: README — ekt schema, Edge Function env vars, deploy checks, eval lead cleanupТамерлан
  • 2026-09-23 14:59fix(chat): reject non-UTF-8 messages; ask to rephrase instead of guessing on unclear inputТамерлан
  • 2026-09-23 14:49fix(db): rename reserved column in category_facets; migration applied to SupabaseТамерлан
  • 2026-09-23 14:46fix(db): isolate consultant in dedicated ekt schema; scope grants to service_roleТамерлан
  • 2026-09-23 14:45FFXТамерлан
  • 2026-09-23 14:44feat(widget): embeddable chat widget (Shadow DOM, SSE, safe markdown, product cards, feedback) + demo page, mock server, Vercel configyensepbaymeirambek
  • 2026-09-23 14:35feat(chat): Edge Function consultant with OpenAI tool calling, SSE streaming, hallucination guard, rate limits; eval suiteТамерлан
  • 2026-09-23 14:31chore: document where to get each env variableТамерлан
  • 2026-09-23 14:29docs: full README — architecture, DB, scraping, API, widget, deploy, opsvkhan-dot
  • 2026-09-23 14:29ci: nightly data refresh and CI workflowsyensepbaymeirambek
  • 2026-09-23 14:18chore: project scaffold, Supabase schema with hybrid search RPC, parser fixturesТамерлан
  • 2026-09-23 14:15docs: design spec for EKT AI consultantТамерлан
Структура репозитория (143 файлов)
.env.example
.gitattributes
.github/workflows/ci.yml
.github/workflows/refresh-data.yml
.gitignore
README.md
docs/README-VERIFICATION.md
docs/ailem-run-ekt-2026-09-23/evidence/E2E.snapshot.md
docs/ailem-run-ekt-2026-09-23/evidence/README.snapshot.md
docs/ailem-run-ekt-2026-09-23/evidence/facts.md
docs/ailem-run-ekt-2026-09-23/evidence/ingest-dry-run.txt
docs/ailem-run-ekt-2026-09-23/report/frame.md
docs/ailem-run-ekt-2026-09-23/report/report.md
docs/ailem-run-ekt-2026-09-23/report/tech.json
docs/ailem-run-ekt-2026-09-23/report/tech.md
docs/ailem-run-ekt-2026-09-23/verdicts/tech-case_fit.json
docs/ailem-run-ekt-2026-09-23/verdicts/tech-implementation.json
docs/ailem-run-ekt-2026-09-23/verdicts/tech-readme.json
docs/ailem-run-ekt-2026-09-23/verdicts/tech-reliability.json
docs/ailem-run-ekt-2026-09-23/verdicts/tech-reproducibility.json
docs/ailem-run-ekt-2026-09-23/verdicts/tech.json
docs/screenshots/e2e-s1-product.png
docs/screenshots/e2e-s2-cart.png
docs/screenshots/e2e-s3-return-form.png
docs/screenshots/e2e-s3a-return-page.png
docs/screenshots/e2e-s4-payments.png
docs/screenshots/e2e-s5-search.png
docs/screenshots/ekt-01-catalog-with-widget.png
docs/screenshots/ekt-02-search-filled.png
docs/screenshots/ekt-03-search-results.png
docs/screenshots/ekt-04-navigate-plate.png
docs/screenshots/ekt-05-price-highlight.png
docs/screenshots/ekt-06-buy-plate.png
docs/screenshots/ekt-07-lead-form-filled.png
docs/screenshots/ekt-08-return-request-filled.png
docs/screenshots/ekt-09-return-conditions.png
docs/screenshots/ekt-10-contacts-phone.png
docs/screenshots/ekt-11-mobile-characteristics.png
docs/screenshots/ekt-lead-form-filled-real.png
docs/superpowers/plans/2026-09-23-agent-hands.md
docs/superpowers/plans/2026-09-23-prices-seed-readme.md
docs/superpowers/specs/2026-09-23-ekt-ai-consultant-design.md
e2e/RESULTS.md
e2e/api-contract.mjs
e2e/lib/inject.mjs
e2e/lib/sse.mjs
e2e/real-site.mjs
eval/RESULTS.md
eval/questions.json
eval/report.json
eval/run.ts
extension/README.md
extension/content.js
extension/icons/icon128.png
extension/icons/icon16.png
extension/icons/icon48.png
extension/manifest.json
extension/widget.js
package-lock.json
package.json
scraper/src/check-city-prices.ts
scraper/src/chunk.ts
scraper/src/http.ts
scraper/src/ingest.ts
scraper/src/parse/branches.ts
scraper/src/parse/category.ts
scraper/src/parse/common.ts
scraper/src/parse/index.ts
scraper/src/parse/page.ts
scraper/src/parse/product.ts
scraper/src/robots.ts
scraper/src/rows.ts
scraper/src/scrape.ts
scraper/test/chunk.test.ts
scraper/test/fixtures/article.html
scraper/test/fixtures/category.html
scraper/test/fixtures/contacts.html
scraper/test/fixtures/faq.html
scraper/test/fixtures/howto.html
scraper/test/fixtures/payments.html
scraper/test/fixtures/product.html
scraper/test/fixtures/product2.html
scraper/test/fixtures/return.html
scraper/test/parse.test.ts
scraper/test/prices.test.ts
scripts/check-search.mjs
scripts/seed-update.mjs
scripts/setup-local.mjs
scripts/smoke.mjs
seed/README.md
seed/branches.json
seed/categories.jsonl
seed/pages.jsonl
seed/products.jsonl
seed/scrape-report.json
supabase/.gitignore
supabase/config.toml
supabase/functions/chat/chat.ts
supabase/functions/chat/config.ts
supabase/functions/chat/db.ts
supabase/functions/chat/deno.json
supabase/functions/chat/http.ts
supabase/functions/chat/http_test.ts
supabase/functions/chat/index.ts
supabase/functions/chat/openai.ts
supabase/functions/chat/openai_test.ts
supabase/functions/chat/prompt.ts
supabase/functions/chat/prompt_test.ts
supabase/functions/chat/ratelimit.ts
supabase/functions/chat/sse.ts
supabase/functions/chat/sse_test.ts
supabase/functions/chat/tools.ts
supabase/functions/chat/tools_test.ts
supabase/functions/chat/ui_actions.ts
supabase/functions/chat/ui_actions_test.ts
supabase/functions/chat/validate.ts
supabase/functions/chat/validate_test.ts
supabase/migrations/20260923120000_init.sql
supabase/migrations/20260923140000_order_note.sql
supabase/migrations/20260923150000_price_history.sql
supabase/migrations/20260923160000_search_recall.sql
supabase/migrations/20260923170000_search_rank.sql
tsconfig.json
vercel.json
web/build.mjs
web/dev/ekt-live.mjs
web/dev/mock-server.mjs
web/public/bookmarklet.html
web/public/embed.html
web/public/index.html
web/src/actions.ts
web/src/i18n.ts
web/src/icons.ts
web/src/markdown.ts
web/src/sse.ts
web/src/storage.ts
web/src/styles.ts
web/src/widget.ts
web/test/actions.test.ts
web/test/markdown.test.ts
web/test/security.test.ts
web/test/sse.test.ts
web/test/widget-actions.test.ts
Ветки (2)

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

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

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