# 1C Agent (подпроект)

Этот подпроект — отдельный сервис-агент для 1С с:

- хранением состояния `project -> chat -> messages`;
- маршрутизацией модели через `registry/index.json` + `runtime_profiles`;
- вызовом LLM через настраиваемые провайдеры;
- встроенной RAG-подготовкой контекста по `plugins/1c/datasets/prepared/rag_index.json`;
- вызовами 1C-адаптера (`/onec-tool` / `adapter_calls`).

## API (коротко)

- `GET /v1/health` — здоровье сервиса.
- `GET /v1/projects` — список проектов.
- `POST /v1/projects` — создать проект.
- `GET /v1/projects/{project_id}` — получить проект.
- `GET /v1/projects/{project_id}/chats` — список чатов проекта.
- `POST /v1/projects/{project_id}/chats` — создать чат.
- `GET /v1/projects/{project_id}/chats/{chat_id}` — получить чат.
- `GET /v1/projects/{project_id}/chats/{chat_id}/messages` — история сообщений.
- `POST /v1/projects/{project_id}/chats/{chat_id}/messages` — добавить message (user/assistant/system/tool).
- `GET /v1/projects/{project_id}/chats/{chat_id}/runtime` — показать, как в этом чате разрешается запуск модели (provider/model/model_id/base_url/adapter и настройки).
- `POST /v1/projects/{project_id}/chats/{chat_id}/turn` — сделать turn LLM:
  - принимает `message`
  - может включать `adapter_calls` (список `{method, params}`)
  - может включать `use_rag` и RAG-профиль.
- `POST /v1/projects/{project_id}/chats/{chat_id}/onec-tool` — прямой вызов адаптера.
- `PATCH /v1/projects/{project_id}` — обновить проект (название/описание/metadata).
- `PATCH /v1/projects/{project_id}/chats/{chat_id}` — обновить настройки чата.
- `DELETE /v1/projects/{project_id}` — удалить проект вместе со всеми чатами/сообщениями.
- `DELETE /v1/projects/{project_id}/chats/{chat_id}` — удалить чат и его сообщения.
- `GET /v1/state` — диагностика состояния сервиса (запущен, uptime, счётчики, провайдеры).

## Веб-интерфейс

- Открой `http://<host>:<port>/` (на тесте: `http://docker-test.cin.su:8090/`), чтобы войти в UI.
- UI не требует отдельной авторизации в самом сервисе; доступ регулируется только сетевыми правилами/портом.
- API по-прежнему доступен на `/v1/*` для интеграций и для работы без UI.

## Контракт

Нормализованный контракт API: [openapi.yaml](openapi.yaml).

## Разделение ответственностей

### Агент (этот сервис)
- Определяет сценарий: project/chat/role/memory/tool-call/guardrails.
- Собирает prompt:
  1) системный prompt проекта/чата,
  2) историю чата,
  3) RAG-подготовленный контекст (если включён),
  4) результаты инструментов.
- Вызывает LLM через выбранный провайдер.
- Сохраняет сообщение и служебные метаданные.

### Модель
- Принимает стандартный диалоговый список сообщений.
- Возвращает только сгенерированный текст.
- Никакой бизнес-логики 1С в сервисе модели — только reasoning по prompt.

### Логика работы с адаптером в prompt

Правила выбора маршрута поиска живут в `plugins/1c/prompts/system.md`, а не в REST/MCP-адаптере. Адаптер должен возвращать структурированные факты и статусы, а агент обязан правильно их интерпретировать.

Ключевые правила для агента:
- всегда явно передавать `base_id` для live-запросов;
- читать известный `module_ref`/read selector напрямую перед глобальным поиском;
- не считать `not_found` доказательством отсутствия кода в расширениях или `ConfigCAS`;
- считать `partial`, `truncated=true` и timeout неполным результатом;
- отделять доказанный факт от гипотезы и показывать конкретный участок кода, если пользователь просит "место".

### Адаптер (1С)
- Отвечает за живые данные 1С (`query`, `metadata`, `modules`, и т.д.).
- Возвращает строго структурированный JSON.
- Не должен быть «зашит» в модель: модель может запрашивать только через инструментовое API.

### RAG
- Не является моделью.
- Превращает вопрос в релевантный контекст + мета-информацию источников.
- Передаётся в модель как системное сообщение с уже собранным `rag_prompt`.

## Что проходит между слоями

- `agent -> model`:  
  `{"role":"system"/"user"/"assistant", "content": ...}` + опционально `provider/system` настройки.
- `agent -> adapter`:  
  `{"method": "...", "payload": {...}}`.
- `adapter -> agent`:  
  structured JSON-ответ (метаданные/результаты запроса/ошибки).
- `agent -> клиент`:  
  user message + assistant message + RAG-сводка + tool outputs + guardrail info.

## Быстрый smoke на развернутом сервисе

Для проверки продового/тестового инстанса:

- `python scripts/smoke_onec_agent_api.py --base-url http://docker-test.cin.su:8090`
- По умолчанию скрипт проверяет быстрые роуты (`/health`, `/state`, CRUD, `messages`).
- Для live-проверки `/turn` добавь `--with-turn-check` и учти, что первый запуск может идти дольше из‑за холодного инференса.

- Быстрый авто-проход "deploy + smoke":
- `powershell -File scripts/deploy_onec_agent_test.ps1 -NoBuild`
- `powershell -File scripts/deploy_onec_agent_test.ps1`
- `powershell -File scripts/deploy_onec_agent_test.ps1 -WithTurnCheck`

## Обновление на `docker-test` без влияния на остальные проекты

Деплой скрипт работает только с сервисом `onec-agent`, поэтому на `docker-test` не затрагиваются другие проекты.

- Быстрое обновление (с пересборкой):  
  `powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_onec_agent_test.ps1`
- Обновление только с перезапуском (без сборки):  
  `powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_onec_agent_test.ps1 -NoBuild`
- Если добавляешь скрипт в задачу по расписанию, используй именно этот файл — он делает деплой + health-check + smoke в одном проходе.

## Автообновление при изменении кода

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

- `powershell -NoProfile -ExecutionPolicy Bypass -File scripts/watch_onec_agent_for_test.ps1`

Скрипт мониторит каталоги/файлы:
- `plugins/1c/agent`
- `core/deploy/docker/1c-agent/compose.yaml`
- `scripts/deploy_onec_agent_test.ps1`
- `scripts/smoke_onec_agent_api.py`

При любых изменениях автоматически перезапускает только сервис `onec-agent` на `docker-test`, затем делает health-check и smoke.

Для непрерывного режима в фоне:

- `Start-Process -FilePath powershell -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','scripts/watch_onec_agent_for_test.ps1' -WindowStyle Hidden`

## Что хранит агент (сущности)

- `Project`: `id`, `name`, `description`, `metadata`, `created_at`, `updated_at`.
- `Chat`: `id`, `project_id`, `title`, `provider_id`, `base_url`, `served_model_name`, `model_id`, `temperature`, `max_tokens`, `rag_profile`, `rag_limit`, `system_prompt`, `metadata`, `created_at`, `updated_at`.
- `Message`: `id`, `project_id`, `chat_id`, `role`, `content`, `payload` (операционные поля), `created_at`.

## Как подключать другого ИИ в будущем

Сервис уже рассчитан на расширение:

- в `ONEC_AGENT_PROVIDERS` задаются провайдеры;
- у каждого провайдера есть `type`.
- сейчас поддержан `openai-compatible`.

Когда нужна другая платформа, добавляется новый `type` в диспетчер провайдеров (и, при необходимости, нормализация ответа в единый формат `{"text": "...", "raw": {...}}`).
