picogent/README.md
2026-02-21 02:41:39 +03:00

354 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# picogent
Минимальный AI-агент с in-process agentic loop на базе Pi Agent Core. Два режима работы: WebSocket-чат и интеграция с Team Board Tracker.
## Требования
- Node.js 22+
- npm
## Установка
```bash
npm install
npm run build
```
## Режимы работы
Picogent автоматически определяет режим по наличию конфигурации:
### 1. WebSocket-режим (чат)
Без конфига запускается как WebSocket-сервер для прямого общения через браузерный клиент.
```bash
npm run dev
# или
npm start
```
Откройте `client.html` в браузере, подключение к `ws://localhost:3100`.
Настройка через переменные окружения (или `.env` файл):
| Переменная | Описание | Default |
|---|---|---|
| `PICOGENT_PORT` | Порт WebSocket-сервера | `3100` |
| `PICOGENT_WORK_DIR` | Рабочая директория агента | `cwd` |
| `PICOGENT_MODEL` | Модель LLM | `sonnet` |
| `PICOGENT_PROVIDER` | Провайдер LLM | `anthropic` |
| `PICOGENT_API_KEY` | API ключ | — |
| `ANTHROPIC_API_KEY` | API ключ (альтернатива) | — |
### 2. Agent-режим (Team Board Tracker)
Агент регистрируется в трекере, получает задачи и выполняет их. Поддерживает два транспорта:
- **`http`** (по умолчанию) — агент поднимает HTTP-сервер, трекер шлёт события через POST. Требует открытый порт (`listen_port`).
- **`ws`** — агент сам подключается к трекеру по WebSocket. Не требует открытого порта и callback_url. Автоматический reconnect с exponential backoff.
Активируется при наличии `agent.json`, директории с конфигом, или переменной `TRACKER_URL`.
## Параметры запуска
```bash
# Режим директории — папка с agent.json, skills/, sessions/
npm run dev -- ./agents/coder/
# Режим файла — путь к JSON-конфигу
npm run dev -- ./my-agent.json
# Через переменную окружения
PICOGENT_CONFIG=./agent.json npm run dev
# Только через env (без файла конфига)
TRACKER_URL=http://localhost:8100 AGENT_TOKEN=tb-xxx npm run dev
# Production
npm start -- ./agents/coder/
```
### Приоритет конфигурации
1. CLI аргумент (директория или файл)
2. Переменная `PICOGENT_CONFIG`
3. `./agent.json` в текущей директории (если существует)
4. Env-переменные (`TRACKER_URL` + `AGENT_TOKEN`)
Env-переменные всегда имеют приоритет над значениями из JSON-файла.
## Конфигурация агента (`agent.json`)
Все поля опциональны (кроме `tracker_url` и `token` для agent-режима). Полный пример с описаниями — `agent.example.json`.
```json
{
"name": "Кодер",
"slug": "coder",
"prompt": "Ты опытный Go-разработчик...",
"tracker_url": "http://localhost:8100",
"token": "tb-agent-abc123",
"transport": "http",
"listen_port": 3200,
"work_dir": "/projects/my-app",
"model": "sonnet",
"provider": "anthropic",
"capabilities": ["coding", "review"],
"max_concurrent_tasks": 2,
"heartbeat_interval_sec": 30,
"allowed_paths": []
}
```
| Поле | Env | Default | Описание |
|---|---|---|---|
| `name` | `AGENT_NAME` | `Agent` | Имя агента в трекере |
| `slug` | `AGENT_SLUG` | `agent` | Уникальный ID (латиница) |
| `prompt` | `AGENT_PROMPT` | — | Системный промпт — роль агента |
| `tracker_url` | `TRACKER_URL` | — | URL Team Board Tracker (**обязательно**) |
| `token` | `AGENT_TOKEN` | — | Bearer-токен для Tracker API (**обязательно**) |
| `transport` | `AGENT_TRANSPORT` | `http` | Транспорт: `http` или `ws` |
| `listen_port` | `AGENT_PORT` | `3200` | Порт HTTP (только transport=http) |
| `work_dir` | `PICOGENT_WORK_DIR` | `agentHome` / `cwd` | Рабочая директория |
| `model` | `PICOGENT_MODEL` | `sonnet` | Модель LLM |
| `provider` | `PICOGENT_PROVIDER` | `anthropic` | Провайдер LLM |
| `api_key` | `PICOGENT_API_KEY` / `ANTHROPIC_API_KEY` | — | API ключ провайдера |
| `capabilities` | — | `["coding"]` | Возможности для трекера |
| `max_concurrent_tasks` | — | `2` | Макс. параллельных задач |
| `heartbeat_interval_sec` | — | `30` | Интервал heartbeat (сек.) |
| `allowed_paths` | — | `[]` (без ограничений) | Ограничение доступа к FS |
### Алиасы моделей
| Алиас | Полный ID |
|---|---|
| `sonnet` | `claude-sonnet-4-6` |
| `opus` | `claude-opus-4-6` |
| `haiku` | `claude-haiku-4-5` |
| `sonnet-4` | `claude-sonnet-4-6` |
| `opus-4` | `claude-opus-4-6` |
| `sonnet-3.5` | `claude-3-5-sonnet-20241022` |
## Режим директории (рекомендуется)
Самый удобный способ — создать папку со всем необходимым:
```
agents/coder/
agent.json # конфиг
skills/ # скилы агента
review/
SKILL.md
sessions/ # сессии (создаётся автоматически)
```
Запуск:
```bash
npm run dev -- ./agents/coder/
```
В этом режиме:
- `agentHome` = путь к директории
- `workDir` = то же (если не переопределён через `work_dir` или env)
- Скилы загружаются из `agentHome/skills/`
- Сессии сохраняются в `agentHome/sessions/`
## Скилы (Skills)
Агент поддерживает скилы — специализированные инструкции в формате `SKILL.md`.
### Структура скила
```
skills/
review/
SKILL.md
refactor/
SKILL.md
```
### Формат `SKILL.md`
```markdown
---
name: review
description: "Code review — анализ кода на ошибки, стиль, производительность"
---
# Code Review
Инструкции для агента...
```
### Как работает
Используется **progressive loading** (как в Claude Code):
1. В системный промпт попадают только XML-сводки скилов (имя + описание + путь)
2. Агент читает полный `SKILL.md` через инструмент `Read` только когда скил нужен
3. Контекст не засоряется лишним текстом
Скилы загружаются из двух мест:
- `agentHome/skills/` (или `workDir/skills/`) — скилы конкретного агента
- `~/.picogent/skills/` — глобальные скилы
## Ограничение доступа к файлам (`allowed_paths`)
По умолчанию агент может читать и писать файлы без ограничений. Для ограничения укажите список разрешённых директорий:
```json
{
"allowed_paths": [
"/projects/my-app/src",
"/projects/my-app/tests"
]
}
```
Что защищено:
- **Read** — проверка пути перед чтением
- **Write** — проверка перед записью и созданием директорий
- **Edit** — проверка перед чтением и записью
- **Bash** — проверка, что рабочая директория команды внутри allowed_paths
Что **не** защищено:
- **Grep/Find/Ls** — read-only инструменты, не ограничиваются
- **Bash-команды** — содержимое команд не парсится (агент может выполнить `cat /etc/passwd`). Для полной изоляции bash используйте контейнеры
## `.env` файл
API ключи и секреты удобно хранить в `.env` файле в корне проекта:
```env
ANTHROPIC_API_KEY=sk-ant-...
TRACKER_URL=http://localhost:8100
AGENT_TOKEN=tb-agent-abc123
```
Node 22 загружает `.env` автоматически через флаг `--env-file=.env` (прописан в `package.json`).
## Архитектура
```
src/
index.ts # Точка входа, dual-mode wiring
config.ts # Загрузка конфигурации (JSON + env)
agent.ts # Pi Agent Core — agentic loop, skills, sessions
sandbox.ts # Sandboxed tools с проверкой путей
router.ts # Роутер событий трекера -> agent
logger.ts # Pino logger
transport/
websocket.ts # WebSocket-сервер (чат-режим)
http.ts # HTTP-сервер (agent-режим, transport=http)
ws-client.ts # WebSocket-клиент к трекеру (agent-режим, transport=ws)
types.ts # Общие типы транспорта
tracker/
client.ts # HTTP-клиент к Tracker API
registration.ts # Регистрация + heartbeat
types.ts # Типы Tracker API
```
### Поток данных
**WebSocket-режим:**
```
Browser (client.html) -> WebSocket -> index.ts -> runAgent() -> Pi Agent Core -> WebSocket -> Browser
```
**Agent-режим (transport=http):**
```
Tracker -> HTTP POST /events -> HttpTransport -> EventRouter -> runAgent() -> Pi Agent Core -> TrackerClient -> Tracker
```
**Agent-режим (transport=ws):**
```
Agent -> WebSocket -> Tracker (auth + heartbeat + events) -> WsClientTransport -> EventRouter -> runAgent() -> TrackerClient -> Tracker
```
### Ядро (`agent.ts`)
Использует Pi Agent Core (`@mariozechner/pi-coding-agent`) для in-process agentic loop:
- Модели через `ModelRegistry` с `models.json` в `~/.picogent/`
- API ключи через `AuthStorage` с runtime injection (`initAgent()`)
- Инструменты: Read, Write, Edit, Bash, Grep, Find, Ls (через `createSandboxedTools`)
- Сессии: JSONL-файлы через `SessionManager`
- Скилы: `loadSkills()` + `formatSkillsForPrompt()` для progressive loading
### Tracker интеграция
- **HTTP-транспорт** (по умолчанию): POST `/api/v1/agents/register` с callback_url, POST `/api/v1/agents/heartbeat`, события через HTTP POST
- **WS-транспорт**: агент подключается к `/ws?client_type=agent`, регистрация и heartbeat через WebSocket, события приходят через тот же канал
- **Задачи**: трекер отправляет `task.assigned` event -> агент выполняет -> результат как комментарий + статус `review`
- **Чат**: трекер отправляет `chat.message` -> агент отвечает -> комментарий к задаче
- **Устойчивость**: HTTP — retry регистрации каждые 5с. WS — reconnect с exponential backoff (1с → 30с)
## WebSocket-протокол
### Клиент -> Сервер
```json
{
"id": "msg-1",
"content": "Какие файлы есть в текущей директории?",
"sessionId": "my-session",
"workDir": "/projects/my-app",
"systemPrompt": "Ты помощник-разработчик"
}
```
| Поле | Обязательно | Описание |
|---|---|---|
| `id` | да | Уникальный ID сообщения |
| `content` | да | Текст промпта |
| `sessionId` | нет | Имя сессии (для сохранения контекста между сообщениями) |
| `workDir` | нет | Рабочая директория для этого запроса |
| `systemPrompt` | нет | Дополнительный системный промпт |
### Сервер -> Клиент (стрим)
```json
{
"id": "msg-1",
"type": "text",
"content": "В директории находятся...",
"sessionId": "abc-123"
}
```
Типы сообщений:
- **`text`** — фрагмент текстового ответа (стримится по мере генерации)
- **`tool_use`** — агент вызвал инструмент (формат: `ToolName: описание`)
- **`tool_result`** — результат инструмента с ошибкой
- **`error`** — ошибка агента или API
- **`done`** — запрос завершён
## Команды
```bash
npm install # Установка зависимостей
npm run build # Компиляция TypeScript
npm run dev # Dev-режим (tsx, .env)
npm start # Запуск из dist/ (.env)
npm test # Тесты (vitest)
```
## Файлы данных
| Путь | Описание |
|---|---|
| `~/.picogent/` | Домашняя директория picogent |
| `~/.picogent/models.json` | Конфигурация моделей (создаётся автоматически) |
| `~/.picogent/auth.json` | Хранилище API ключей |
| `~/.picogent/sessions/` | Сессии по умолчанию |
| `~/.picogent/skills/` | Глобальные скилы |
## Происхождение
Проект извлечён из двух соседних проектов:
- **OpenClaw** (`openclaw/`) — паттерн in-process agent loop через Pi Agent Core (`createAgentSession`, `AuthStorage`, `ModelRegistry`, `codingTools`, event subscription)
- **NanoClaw** (`nanoclaw/`) — паттерн pino-логгера, структура "получи сообщение -> запусти агента -> отправь результат"
Сознательно выброшено: каналы, контейнеры, плагины, auth profiles, MCP, subagents и прочая сложность. Picogent — это голый agent loop + транспорт.