Metadata-Version: 2.4
Name: emberio-labs-ember-agent
Version: 0.3.0
Summary: Готовый к запуску агент на базе ember: настройка в TOML, запуск одной командой.
License-Expression: MIT
License-File: LICENSE
Keywords: agent,llm,ai,cli,ember,mcp
Author: Emberio Labs
Author-email: dev@emberio.labs
Requires-Python: >=3.12,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Dist: emberio-labs-ember[mcp,openai] (>=0.5.0,<1.0)
Requires-Dist: rich (>=13.0.0,<16.0.0)
Description-Content-Type: text/markdown

# ember-agent

Готовый к запуску агент на базе [`ember`](https://github.com/emberio-labs/ember):
настройка в TOML — запуск одной командой.

- **CLI-команда:** `ember-agent` (короткая, удобная в терминале)
- **На PyPI пакет публикуется как:** `emberio-labs-ember-agent`

```text
$ ember-agent --version
ember-agent 0.3.0
```

## Возможности

- Конфигурация в одном TOML-файле: системный промпт, провайдер LLM (ключ, модель, base_url), MCP-инструменты, память.
- Интерактивный диалог в терминале или разовый запрос (`--message`) для скриптов.
- Красивый вывод в интерактиве: баннер приветствия в рамке (версия, провайдер,
  модель, инструменты, память), диалог в виде чата (подпись `🤖 ember-agent`,
  приглашение «Ваш ответ: »), markdown-рендер ответов, потоковая печать (где
  доступна), команды сессии `/help` и `/reset`, показ процесса вызова
  инструментов (`🔧`/`✔`/`✖`), Ctrl+C отменяет ответ.
- Межсессионная память: каждый запуск — новый диалог, а прошлые агент вспоминает
  сам (recall по всем сессиям). Чтобы продолжить конкретный диалог, задайте его
  `session_id`. Хранилище — `FileMemory` из `ember` (JSONL, по файлу на сессию).
- Команды `ember-agent memory`: список сохранённых сессий, просмотр диалога,
  удаление одной сессии или всех сразу.
- Провайдеры: `mock` (без сети и ключей, для экспериментов и тестов) и `openai`
  (OpenAI и любые OpenAI-совместимые API: OpenRouter, Groq, vLLM, LM Studio и т.п.).
- Модель задаётся провайдеру (`[provider] model`) — как часть «подключения к LLM».
- Инструменты по [MCP](https://modelcontextprotocol.io): `stdio`-процессы и streamable HTTP-серверы.
- Работает на Python 3.12+.

## Установка

Из PyPI:

```bash
pip install emberio-labs-ember-agent
```

Из исходников (Poetry):

```bash
git clone https://github.com/emberio-labs/ember-agent.git
cd ember-agent
poetry install
```

## Настройка

Скопируйте пример конфигурации и отредактируйте под себя:

```bash
cp config.example.toml config.toml
```

Все секции конфигурации опциональны: пустой файл создаст агента на `MockProvider`,
который работает без сети и API-ключей.

```toml
[agent]
system_prompt = "Ты полезный и краткий помощник."   # как агент себя ведёт

[provider]
type = "mock"                  # "mock" | "openai"
model = "gpt-4o-mini"          # модель подключения LLM (для type = "openai")
api_key_env = "OPENAI_API_KEY" # откуда брать ключ (для type = "openai")

[memory]                       # межсессионная память (опционально)
enabled = true
type = "file"                  # пока единственное хранилище
directory = ".ember/memory"    # где лежат файлы сессий
# session_id = "my-project"    # не задан → каждый запуск начинает новый диалог

[[mcp.servers]]                       # внешние инструменты (опционально)
transport = "stdio"                   # "stdio" | "http"
command = "python"
args = ["path/to/server.py"]
```

Полный пример с комментариями — в [`config.example.toml`](config.example.toml).
Для реального провайдера задайте переменную окружения с ключом, например `OPENAI_API_KEY`.
Если модель не указана, провайдер берёт свою по умолчанию (`gpt-4o-mini` у OpenAI).

## Память

Память **выключена по умолчанию**: без секции `[memory]` (или при `enabled = false`)
агент ничего не пишет на диск. Включается двумя способами:

- в конфигурации — `[memory] enabled = true`;
- флагом CLI — `--session ID` (включает память и переключает на сессию `ID`),
  при этом `--no-memory` выключает память, даже если она включена в TOML.

```bash
ember-agent run                             # [memory] enabled = true → новый диалог
ember-agent run --session my-project        # продолжить диалог my-project
ember-agent run -m "напомни, что мы решили" --session my-project
ember-agent run --no-memory                 # разовый запуск без памяти
```

Как это работает:

- **по умолчанию каждый запуск — новый диалог**: если `session_id` не задан, он
  генерируется (`20260910-221503-4f1a2b`) — id виден в баннере или в подсказке
  после запуска;
- из прошлых сессий агент подтягивает релевантные фрагменты (кросс-сессионный
  recall) — текущая сессия исключается, её история и так в контексте;
- `session_id` в TOML или `--session ID` продолжают один и тот же диалог:
  запуски с тем же `session_id` дописывают его историю;
- хранилище — `FileMemory` из `ember`: файл `<session_id>.json` в
  `directory` (по умолчанию `.ember/memory`); запись атомарная;
- `/reset` в интерактивном режиме очищает историю и удаляет текущую сессию из
  хранилища.

При разовом запуске (`-m`) с включённой памятью id сессии печатается в stderr,
поэтому stdout остаётся чистым ответом, а диалог можно продолжить:

```text
$ ember-agent run -m "запомни: релиз в пятницу"
Запомнил.
🗂 сессия памяти: 20260910-221503-4f1a2b (.ember/memory) — продолжить: --session 20260910-221503-4f1a2b
```

### Просмотр и очистка

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

```bash
ember-agent memory list                # сессии: id, сообщений, время изменения, размер
ember-agent memory show my-project     # напечатать диалог сессии
ember-agent memory delete my-project   # удалить одну сессию
ember-agent memory clear --yes         # удалить все сессии (без --yes только предупредит)
```

Это нужно из-за поведения по умолчанию: каждый запуск без `session_id` создаёт
новую сессию, и без команды списка файлы пришлось бы искать вручную.

```text
$ ember-agent memory list
Хранилище: .ember/memory
ID                      Сообщений  Изменена             Размер
----------------------------------------------------------------
20260910-221804-dbe24d          2  2026-09-10 22:18:04   152 Б
Всего сессий: 1
```

Используйте в `session_id` только латиницу, цифры, `-`, `_` и `.`: `FileMemory`
санитизирует остальные символы для имени файла, и разные id (`ручная` и
`ручной`) могут схлопнуться в один файл — диалоги будут затирать друг друга.

Механику хранения и поиска реализует библиотека `ember` (публичный интерфейс
`Memory`) — своё хранилище (Redis, SQLite, ...) можно подставить, реализовав этот
интерфейс. В `ember-agent` тип хранилища выбирается в конфиге (`[memory] type`),
поэтому он не зависит от конкретного класса.

## Запуск

Интерактивный диалог:

```bash
ember-agent run
```

В начале сессии печатается баннер в рамке: версия, провайдер, модель,
подключённые инструменты и состояние памяти (`🗂 память: сессия '20260910-221503-4f1a2b' →
.ember/memory` и строка `↻ продолжить диалог: ember-agent run --session ...`).
Дальше идёт диалог в виде чата: ответы агента помечены подписью `🤖 ember-agent`,
свой ввод начинается по приглашению «Ваш ответ: ». Внутри диалога доступны команды:

- `/help` — справка по командам;
- `/reset` — начать новый диалог (сбросить историю, а с памятью — и текущую сессию);
- выход: `exit`, `quit`, `выход`, Ctrl+D, или Ctrl+C дважды.

Ответы рендерятся как markdown (заголовки, списки, код-блоки); там, где потоковая
печать доступна (агент без инструментов), текст появляется по мере генерации.
При вызове инструментов виден процесс: `🔧 имя(аргументы)` и результат `✔` / ошибка `✖`.
Ctrl+C прерывает текущий ответ, не завершая сессию.

Разовый запрос — без диалога, удобно для скриптов:

```bash
ember-agent run -m "Привет! Коротко: кто ты?"
```

Явно указать файл конфигурации:

```bash
ember-agent run -c path/to/config.toml
```

Альтернативный запуск через Python (без установки в окружение):

```bash
python -m ember_agent run -m "Привет"
```

## Разработка

```bash
poetry install                      # установка зависимостей (включая dev)
poetry run pytest                   # тесты
poetry run ruff check ember_agent tests   # линтер
poetry run mypy                     # статическая типизация
```

Код в `ember_agent/`, тесты — в `tests/`. Формат конфигурации описан в
[`config.example.toml`](config.example.toml).

## Релиз

Публикация новой версии на PyPI автоматизирована через GitHub Actions
(workflow `.github/workflows/publish.yml`):

1. Поднимите версию в `pyproject.toml` (`version = "0.3.0"`) и закоммитьте
   изменение, например: `chore: bump version to 0.3.0`.
2. Создайте и запушьте git-тег, совпадающий с версией:

   ```bash
   git tag v0.3.0
   git push origin v0.3.0
   ```

3. Workflow соберёт wheel и sdist (`poetry build`) и опубликует их на PyPI.
   Ветка `main` при этом не нужна — достаточно тега.

Публикация использует Trusted Publishing (OIDC): секреты в GitHub не хранятся.
Для этого владельцу нужно один раз настроить publisher на PyPI
(и, опционально, на TestPyPI для проверок):

- **PyPI:** https://pypi.org/manage/account/publishing/
- **TestPyPI:** https://test.pypi.org/manage/account/publishing/

Поля формы одинаковы для PyPI и TestPyPI:

| Поле | Значение |
|---|---|
| Project name | `emberio-labs-ember-agent` |
| GitHub owner | `emberio-labs` |
| GitHub repository | `ember-agent` |
| Workflow name | `publish.yml` |
| Environment | *(пусто)* |

После настройки публикацию можно проверить вручную на TestPyPI:
GitHub → Actions → Publish → Run workflow. На боевой PyPI пакет уходит
только по git-тегу `v*`.

## Лицензия

MIT — см. [LICENSE](LICENSE).

