Scope down to local Docker testing, drop Gitea/K3s plumbing for now
This is a pilot project — running it via docker compose locally is enough for now. Deploy/CI can come back once the project is greenlit for real use. Also fixes claude invocation: add --strict-mcp-config (verified against the actual installed claude-code CLI --help) so only agent-news' own MCP server is loaded, not whatever else might be discoverable in the environment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
TELEGRAM_BOT_TOKEN=
|
||||||
|
ALLOWED_CHAT_IDS=
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: Build & Deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: registry.service.bearsdev.tech
|
|
||||||
IMAGE: agent-news
|
|
||||||
REPO: platformteam-projects/agent-news
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: [ubuntu-latest]
|
|
||||||
steps:
|
|
||||||
- name: Build & Push
|
|
||||||
run: |
|
|
||||||
git clone https://gitea_admin:${{ secrets.CI_TOKEN }}@gitea.service.bearsdev.tech/${{ env.REPO }}.git app
|
|
||||||
cd app && git checkout ${{ gitea.sha }}
|
|
||||||
echo "${{ secrets.NEXUS_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.NEXUS_USERNAME }}" --password-stdin
|
|
||||||
docker buildx build \
|
|
||||||
--builder default \
|
|
||||||
-f runner/Dockerfile \
|
|
||||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ gitea.run_number }} \
|
|
||||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest \
|
|
||||||
--push .
|
|
||||||
|
|
||||||
- name: Update deploy repo
|
|
||||||
run: |
|
|
||||||
git clone https://gitea_admin:${{ secrets.CI_TOKEN }}@gitea.service.bearsdev.tech/deploy/${{ env.IMAGE }}.git deploy
|
|
||||||
cd deploy
|
|
||||||
sed -i "s|image: ${{ env.REGISTRY }}/${{ env.IMAGE }}:.*|image: ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ gitea.run_number }}|" deployment.yaml
|
|
||||||
git config user.email "ci@bearsdev.tech"
|
|
||||||
git config user.name "Gitea CI"
|
|
||||||
git add deployment.yaml
|
|
||||||
git commit -m "ci: update image to ${{ env.IMAGE }}:${{ gitea.run_number }}" || echo "no changes"
|
|
||||||
git push https://gitea_admin:${{ secrets.DEPLOY_TOKEN }}@gitea.service.bearsdev.tech/deploy/${{ env.IMAGE }}.git main
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
.dart_tool/
|
.dart_tool/
|
||||||
build/
|
build/
|
||||||
|
.env
|
||||||
|
|||||||
73
README.md
73
README.md
@@ -1,33 +1,58 @@
|
|||||||
# agent-news
|
# agent-news
|
||||||
|
|
||||||
Telegram-бот на Dart: по команде `/news` (или `/news <тема>`) запускает Claude Code
|
Telegram-бот на Dart: по команде `/news` (или `/news <тема>`) запускает Claude Code
|
||||||
для ресёрча и присылает выжимку в чат. Учебный проект для platformteam — архитектура
|
для ресёрча и присылает выжимку в чат. Тестовый/учебный проект — пока гоняем локально
|
||||||
и урок описаны в [aidoc](https://aidoc.platformteam.tech), страница `practices/agent-news-bot`.
|
в Docker, без деплоя в кластер.
|
||||||
|
|
||||||
## Как это работает
|
## Как это работает
|
||||||
|
|
||||||
Один под, один контейнер, три процесса:
|
Один контейнер, три процесса:
|
||||||
|
|
||||||
1. `agent-news-bot` (Dart, long polling) — слушает `/news`, спавнит `claude` как сабпроцесс.
|
1. `agent-news-bot` (Dart, long polling) — слушает `/news`, спавнит `claude` как сабпроцесс.
|
||||||
2. `claude` (Claude Code CLI) — делает ресёрч, в конце вызывает MCP-тул `send_to_telegram`.
|
2. `claude` (Claude Code CLI) — делает ресёрч, в конце вызывает MCP-тул `send_to_telegram`.
|
||||||
3. `agent-news-mcp` (Dart, stdio MCP-сервер) — спавнится самим `claude`, шлёт готовый
|
3. `agent-news-mcp` (Dart, stdio MCP-сервер) — спавнится самим `claude`, шлёт готовый
|
||||||
текст в Telegram Bot API.
|
текст в Telegram Bot API.
|
||||||
|
|
||||||
Подробности и диаграммы — в уроке aidoc.
|
## Запуск локально
|
||||||
|
|
||||||
## Локальная разработка
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# заполнить TELEGRAM_BOT_TOKEN и ALLOWED_CHAT_IDS (через запятую)
|
||||||
|
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
`~/.claude` (авторизация Claude Code) хранится в именованном volume `claude-home` —
|
||||||
|
переживает пересборку и рестарт контейнера.
|
||||||
|
|
||||||
|
### Первичная авторизация Claude Code
|
||||||
|
|
||||||
|
Claude Code CLI использует OAuth-логин через Claude.ai (подписка, не API-ключ). Один раз
|
||||||
|
после первого запуска нужно зайти в контейнер и залогиниться:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec agent-news claude
|
||||||
|
```
|
||||||
|
|
||||||
|
CLI напечатает ссылку — открой её в браузере, авторизуйся. Токен сохранится в
|
||||||
|
`~/.claude` на volume, так что после `docker compose restart` логин не слетит.
|
||||||
|
|
||||||
|
### Проверка
|
||||||
|
|
||||||
|
Напиши боту `/news` (или `/news <тема>`) из чата с id из `ALLOWED_CHAT_IDS` — бот
|
||||||
|
ответит "ищу…", а через 1-3 минуты Claude сам пришлёт выжимку через `send_to_telegram`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose logs -f agent-news
|
||||||
|
```
|
||||||
|
|
||||||
|
## Локальная разработка (без Docker)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd bot && dart pub get && dart analyze
|
cd bot && dart pub get && dart analyze
|
||||||
cd ../mcp_server && dart pub get && dart analyze
|
cd ../mcp_server && dart pub get && dart analyze
|
||||||
```
|
```
|
||||||
|
|
||||||
Сборка образа (контекст — корень репозитория):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -f runner/Dockerfile -t agent-news:dev .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Переменные окружения
|
## Переменные окружения
|
||||||
|
|
||||||
| Переменная | Обязательна | Назначение |
|
| Переменная | Обязательна | Назначение |
|
||||||
@@ -37,29 +62,3 @@ docker build -f runner/Dockerfile -t agent-news:dev .
|
|||||||
| `NEWS_PROMPT` | нет | промпт по умолчанию для `/news` без темы |
|
| `NEWS_PROMPT` | нет | промпт по умолчанию для `/news` без темы |
|
||||||
| `CLAUDE_TIMEOUT_SECONDS` | нет | таймаут на ресёрч (по умолчанию 360) |
|
| `CLAUDE_TIMEOUT_SECONDS` | нет | таймаут на ресёрч (по умолчанию 360) |
|
||||||
| `MCP_CONFIG_PATH` | нет | путь к `mcp.json` (по умолчанию `/home/agent/claude-config/mcp.json`) |
|
| `MCP_CONFIG_PATH` | нет | путь к `mcp.json` (по умолчанию `/home/agent/claude-config/mcp.json`) |
|
||||||
|
|
||||||
## Первичная авторизация Claude Code
|
|
||||||
|
|
||||||
Claude Code CLI использует OAuth-логин через Claude.ai (подписка, не API-ключ). После
|
|
||||||
первого деплоя нужно один раз пройти логин внутри пода — иначе `claude -p ...` будет
|
|
||||||
падать с ошибкой авторизации:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
kubectl exec -it -n platformteam deploy/agent-news -- claude
|
|
||||||
```
|
|
||||||
|
|
||||||
CLI напечатает ссылку — открой её в браузере, авторизуйся. Токен сохранится в
|
|
||||||
`~/.claude` (persist через PVC `agent-news-home`, см. `deploy/agent-news`), так что
|
|
||||||
после рестарта пода логин не слетит.
|
|
||||||
|
|
||||||
## Деплой
|
|
||||||
|
|
||||||
Стандартный BearsDev CI/CD (см. `bearsdev-systems/ai-agents/knowledge/cicd.md`):
|
|
||||||
`git push` → `.gitea/workflows/build.yaml` собирает и пушит образ → бампит тег в
|
|
||||||
`deploy/agent-news` → `.gitea/workflows/deploy.yaml` применяет манифест в K3s.
|
|
||||||
|
|
||||||
Перед первым деплоем вручную (см. план и `cicd.md`):
|
|
||||||
1. Создать `deploy/agent-news` репо с `deployment.yaml` + `.gitea/workflows/deploy.yaml`.
|
|
||||||
2. `kubectl apply -f pvc.yaml` — PVC `agent-news-home`, один раз, не через CI.
|
|
||||||
3. `kubectl create secret generic agent-news-secrets -n platformteam --from-literal=TELEGRAM_BOT_TOKEN=... --from-literal=ALLOWED_CHAT_IDS=...`
|
|
||||||
4. После первого деплоя — авторизация Claude Code (см. выше).
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class ClaudeRunner {
|
|||||||
prompt,
|
prompt,
|
||||||
'--mcp-config',
|
'--mcp-config',
|
||||||
config.mcpConfigPath,
|
config.mcpConfigPath,
|
||||||
|
'--strict-mcp-config',
|
||||||
'--dangerously-skip-permissions',
|
'--dangerously-skip-permissions',
|
||||||
],
|
],
|
||||||
environment: {'TELEGRAM_BOT_TOKEN': config.telegramToken},
|
environment: {'TELEGRAM_BOT_TOKEN': config.telegramToken},
|
||||||
|
|||||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
services:
|
||||||
|
agent-news:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: runner/Dockerfile
|
||||||
|
env_file: .env
|
||||||
|
volumes:
|
||||||
|
- claude-home:/home/agent/.claude
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
claude-home:
|
||||||
Reference in New Issue
Block a user