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/
|
||||
build/
|
||||
.env
|
||||
|
||||
73
README.md
73
README.md
@@ -1,33 +1,58 @@
|
||||
# agent-news
|
||||
|
||||
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` как сабпроцесс.
|
||||
2. `claude` (Claude Code CLI) — делает ресёрч, в конце вызывает MCP-тул `send_to_telegram`.
|
||||
3. `agent-news-mcp` (Dart, stdio MCP-сервер) — спавнится самим `claude`, шлёт готовый
|
||||
текст в 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
|
||||
cd bot && 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` без темы |
|
||||
| `CLAUDE_TIMEOUT_SECONDS` | нет | таймаут на ресёрч (по умолчанию 360) |
|
||||
| `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,
|
||||
'--mcp-config',
|
||||
config.mcpConfigPath,
|
||||
'--strict-mcp-config',
|
||||
'--dangerously-skip-permissions',
|
||||
],
|
||||
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