Commit Graph

4 Commits

Author SHA1 Message Date
bboxwtf
153399f41e feat(phase-A): agent-worker container — autonomous agent HTTP server
PHASE A COMPLETE: каждый агент теперь может жить в отдельном Docker Swarm контейнере как автономная единица.

- HTTP-сервер агента: GET /health, GET /info, POST /chat, POST /task, GET /tasks, GET /tasks/{id}, GET /memory
- Загружает конфиг из shared DB по AGENT_ID env var (model, systemPrompt, allowedTools)
- 4 горутины-воркера для параллельной обработки задач
- In-memory task queue (buffered channel, depth=100) + ring buffer последних 50 задач
- Callback URL: POST результата при завершении async задачи
- Sliding window памяти: загружает последние 20 сообщений из DB при каждом запросе
- Изолированные инструменты: агент получает только allowedTools из своей конфигурации
- Агент сам вызывает LLM напрямую через LLM_BASE_URL (не через Gateway)
- Graceful shutdown с таймаутом 15s

- 20 unit-тестов: все PASS
- Покрытие: инициализация, task queue, /health, /info, /task, /tasks, /memory, инструменты, lifecycle

- Multi-stage Go build: golang:1.23-alpine → alpine:3.21
- EXPOSE 8001, HEALTHCHECK на /health каждые 15s
- Агенты деплоятся динамически Swarm (не статический сервис в stack)

- Новые поля в таблице agents: serviceName, servicePort, containerImage, containerStatus
- SQL migration: drizzle/migrations/0006_agent_container_fields.sql

- AgentConfig + AgentRow: новые поля serviceName, servicePort, containerImage, containerStatus
- UpdateContainerStatus() — обновление статуса при деплое/остановке
- GetAgentHistory() — sliding window памяти агента из DB
- SaveHistory() — сохранение диалога агента в DB

- delegate_to_agent: реальный HTTP POST к контейнеру агента через overlay DNS
  - sync: POST /chat (ждёт ответ)
  - async: POST /task (возвращает task_id)
  - fallback: если агент не запущен — информативное сообщение
- SetDatabase() — инжекция DB для резолва адресов живых агентов

- Orchestrator инжектирует DB в Executor через SetDatabase() при инициализации
2026-03-31 23:11:02 +00:00
bboxwtf
3be643992d fix(nodes): SSH join-node fix + Test Connection button
Root cause:
  gateway binary was built before SwarmJoinNodeViaSSH was added → 404 on
  /api/swarm/join-node → tRPC threw 'Gateway unavailable' error.

Gateway fixes:
  - Rebuilt gateway image (golang:1.23-alpine + go mod tidy → clean go.sum)
  - SwarmJoinNodeViaSSH now live in binary (was already coded, not compiled)
  - NEW: POST /api/swarm/ssh-test handler (SwarmSSHTest)
      • Dials SSH with 10s timeout
      • Runs 'docker version' on remote to check Docker availability
      • Returns {ok, sshOk, dockerOk, dockerVersion, error, step}
  - Route registered: r.Post("/swarm/ssh-test", h.SwarmSSHTest)

Server fixes:
  - gateway-proxy.ts: added testSSHConnection() → POST /api/swarm/ssh-test
  - routers.ts: added nodes.sshTest mutation (input: host/port/user/password)

UI (client/src/pages/Nodes.tsx) — AddNodeDialog rewritten:
  - Separate state for testResult and joinResult (two independent panels)
  - NEW: yellow 'Test Connection' button → calls nodes.sshTest
      shows SSH OK + Docker version, or human-readable error
  - 'Join Swarm' button remains independent
  - Human-readable error messages per step:
      ssh_connect → 'Cannot connect — check IP, port, SSH running'
      docker_join → 'docker swarm join failed: ...'
      trpc        → 'Gateway unavailable — check gateway container'
  - Input changes clear stale test/join results
  - ✕ close button in dialog header
  - Disabled state unified (busy || joinDone)
2026-03-21 22:37:59 +00:00
bboxwtf
37e0a21ec3 feat(nodes): Add Node via SSH — join any host to Swarm cluster
- client/src/pages/Nodes.tsx:
  • Added showAddNode state (useState(false))
  • Added 'Add Node' button (green, UserPlus icon) in page header toolbar
  • Added 'Add Node via SSH' button in Nodes tab toolbar (always visible)
  • Added 'Add Node via SSH' button in empty-state of Nodes tab
  • Rendered <AddNodeDialog> overlay when showAddNode=true;
    onSuccess refreshes nodesQ + swarmInfoQ then closes dialog
  • AddNodeDialog component was already implemented: SSH host/port/user/
    password/role inputs, live result display (green/red), command echo

- server/gateway-proxy.ts:
  • joinSwarmNodeViaSSH() — POST /api/swarm/join-node with SSH credentials

- server/routers.ts:
  • nodes.joinNode mutation — validates input, calls joinSwarmNodeViaSSH,
    throws if gateway unavailable

- gateway/internal/api/handlers.go:
  • POST /api/swarm/join-node handler (SwarmJoinNodeViaSSH):
    retrieves join token, SSHes to remote host via golang.org/x/crypto/ssh,
    runs 'docker swarm join --token <token> <managerAddr>',
    handles already-member case as success

- gateway/cmd/gateway/main.go:
  • Route registered: r.Post("/swarm/join-node", h.SwarmJoinNodeViaSSH)

- gateway/go.mod + go.sum:
  • Added golang.org/x/crypto v0.37.0 dependency for SSH client support
2026-03-21 21:57:43 +00:00
Manus
02742f836c Checkpoint: Phase 9: Go Gateway — полный перенос оркестратора и tool executor на Go. Добавлены gateway/ (Go), docker/ (docker-compose + stack + Dockerfiles), server/gateway-proxy.ts 2026-03-20 18:43:49 -04:00