report-builder-progress

Report Builder: Form Constructor + AI Chat

Статус: MVP готов, нужно тестирование и доработка

Дата начала: 2026-03-28 Проект: c10r.io (c10r.io) Ветка: текущая (изменения не закоммичены)


Что сделано

Новые файлы

ФайлСтатусОписание
app/ws/[wsid]/reports/components/ReportBuilder.tsxDONEКонтейнер: FormConstructor (слева) + ReportChat (справа, ResizablePanel collapsible) + ResultTable (внизу)
app/ws/[wsid]/reports/components/FormConstructor.tsxDONEForm-конструктор с collapsible секциями: Source, Mode toggle (Fields/Measures), Fields picker, Measures, Group By, Filters, Sort, Limit
app/ws/[wsid]/reports/components/ReportChat.tsxDONEAI чат: streaming SSE, starter suggestions, парсинг DataConfig из ```json блоков, кнопка очистки, badge "Applied"
app/ws/[wsid]/reports/components/ResultTable.tsxDONEИзвлечённая таблица результатов (из старого ReportConstructor)
app/ws/[wsid]/reports/components/report-config-utils.tsDONEОбщие типы (DataConfig, EntityInfo, ChatMessage), configToUI/uiToConfig, parseDataConfigFromMarkdown, константы
app/api/ws/[wsid]/reports/[id]/chat/route.tsDONEAPI endpoint: streaming через LangChain, system prompt с entity registry, сохранение сообщений в отчёт
config/prompts/report-builder.mdDONESystem prompt для AI: роль, схема DataConfig, правила, плейсхолдеры {ENTITY_REGISTRY} и {CURRENT_CONFIG}

Изменённые файлы

ФайлЧто изменено
app/ws/[wsid]/reports/[id]/page.tsxImport ReportConstructor → ReportBuilder, добавлен chatMessages в тип ReportDetail
modules/workspace/report/model.tsДобавлен IReportChatMessage, ChatMessageSchema, chatMessages[] в IReport + ReportSchema
modules/workspace/report/controller.tsaddChatMessages(), clearChatMessages(), chatMessages в getReport()
modules/workspace/report/index.tsЭкспорт addChatMessages, clearChatMessages
app/api/ws/[wsid]/reports/[id]/route.tsPATCH поддерживает chatMessages: [] для очистки чата
messages/en/reports.jsonКлючи: constructor.section*, constructor.mode*, chat.*
messages/ru/reports.jsonКлючи: constructor.section*, constructor.mode*, chat.*

Файлы к удалению (после проверки)

ФайлСтатус
app/ws/[wsid]/reports/components/ReportConstructor.tsxНигде не импортируется, можно удалить

Что сделано (тестирование 2026-03-28)

Исправленные баги

  • Safety limit 1000 rows — без лимита flat query возвращал все строки (71901), вешая браузер. Добавлен $count + $limit: 1000 в controller.ts, "Showing X of Y" в ResultTable
  • Устаревшая модель claude-3-5-haiku — API возвращал 404. Добавлен автофикс в chat route
  • Streaming crashing worker — ReadableStream при ошибке LLM крашил Turbopack worker (ERR_EMPTY_RESPONSE). Переделано на model.invoke() с error handling
  • groupBy теряется после AI apply — race condition: debounce save из FormConstructor перезаписывал AI config. Добавлен immediateSaveGuard
  • Timezone баг в date presetsresolveDatePreset использовал local timezone, из-за чего $this_year на EST начинался с 05:00 UTC. Переделано на UTC
  • Промпт: AI выдумывал пресеты$last_10_days не существует. Добавлено правило "ONLY listed presets"
  • Промпт: month() вместо day() — забыли day() и week() в списке date functions
  • Промпт: неправильная сортировка summary — sort по raw field вместо groupBy field
  • Промпт: семантические подсказки — "продажи" → payment/opportunity

Тесты пройдены

  • Flat report: Contacts (Name, Company, Email) — 1000 of 71901 rows
  • Summary report: Opportunities Sum Amount by month(createdAt) — 71 строка, $9.2M total
  • AI Chat: "покажи количество контактов по компаниям, топ 10" → config applied, Calculate OK
  • AI Chat: "продажи за 10 дней по дням суммы" → payment, day() grouping, $last_7_days
  • AI Chat: follow-up "покажи за этот год" → фильтр изменён на $this_year, данные показаны

Что НЕ сделано (TODO)

Желательно

  • Mobile responsive — на экранах < md скрыть ResizablePanel, показать табы (Form | AI) через компонент Tabs
  • Лимит сообщений — на клиенте нет ограничения на отображение чата, для длинных чатов может быть тормозно
  • Markdown rendering — ответы AI показываются как plain text, можно добавить рендер markdown
  • Auto-calculate — после применения AI конфига автоматически запускать Calculate
  • Streaming — вернуть streaming (model.stream) для лучшего UX, но с правильным error handling

Косметика

  • Удалить старый ReportConstructor.tsx после полной проверки
  • Scroll to results — после Calculate scroll вниз к таблице

Архитектура

┌──────────────────────────────────────────────────────────┐
│ page.tsx (header: name, description)                     │
├────────────────────────────┬─────────────────────────────┤
│ FormConstructor            │ ReportChat (ResizablePanel)  │
│                            │ collapsible, resizeFrom=left │
│ ▸ Source [dropdown]        │                              │
│ ▸ Mode [Fields|Measures]   │ 🤖 Опиши что хочешь узнать  │
│ ▸ Fields / Measures        │ 👤 message...                │
│ ▸ Group By                 │ 🤖 response + [Applied ✓]   │
│ ▸ Filters                  │                              │
│ ▸ Sort / Limit             │ [________________] [Send]    │
│ [▶ Calculate]              │                              │
├────────────────────────────┴─────────────────────────────┤
│ ResultTable (full width)                                  │
└──────────────────────────────────────────────────────────┘

Data flow

FormConstructor ──onChange──→ ReportBuilder (useState<DataConfig>) ←──onConfigChange── ReportChat
                                    │                                        │
                                    ├── debounced save → PATCH /api/reports/{id}
                                    ├── immediate save (AI) → PATCH /api/reports/{id}
                                    └── Calculate → POST /api/reports/{id}/calculate
                                                         │
ReportChat → POST /api/reports/{id}/chat ──stream──→ parse ```json → onConfigChange
                                         └── saves messages to report.chatMessages

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

  1. Единый DataConfig state в ReportBuilder — обе панели читают и пишут в него
  2. AI чат сохраняется в отчёте (report.chatMessages) — персистентный, с кнопкой очистки
  3. JSON из ответа AI парсится через regex json... → parseDataConfigFromMarkdown()
  4. System prompt включает полный entity registry (все 11 сущностей с полями) + текущий DataConfig
  5. Temperature 0.3 для AI чата (ниже чем основной chat 0.7) — для более предсказуемого JSON

Как запустить и проверить

cd /Users/m/a/kompot/c10r.io
npm run dev
  1. Открыть https://localhost:3000/ws/{wsid}/reports
  2. Создать или открыть существующий отчёт
  3. Проверить левую панель (FormConstructor): выбрать source, добавить fields, filters
  4. Проверить правую панель (ReportChat): написать "покажи количество контактов по компаниям"
  5. Проверить Calculate → таблица результатов
  6. Свернуть/развернуть чат-панель
  7. Очистить чат → сообщения удаляются

Контекст для продолжения

  • Старый конструктор: ReportConstructor.tsx — sentence builder с чипами ("Show me [X] from [Y]"). Нигде не используется, можно удалить
  • Pipeline builder: modules/workspace/report/pipeline-builder.ts — НЕ менялся, конвертирует DataConfig → MongoDB aggregation
  • Entity registry: modules/workspace/report/entity-registry.ts — НЕ менялся, 11 сущностей с полями/связями
  • Существующий AI chat: app/api/ws/[wsid]/chat/route.ts — основной чат с tools, report chat сделан проще (без tools)
  • ResizablePanel: app/components/ResizablePanel.tsx — компонент с drag-resize, collapsible, localStorage persistence