Skip to content

feat(forge): conectar V con su servidor Hetzner — 3 tools nuevas - #46

Draft
turbillon50 wants to merge 6 commits into
mainfrom
claude/v-server-tools
Draft

feat(forge): conectar V con su servidor Hetzner — 3 tools nuevas#46
turbillon50 wants to merge 6 commits into
mainfrom
claude/v-server-tools

Conversation

@turbillon50

Copy link
Copy Markdown
Owner

Qué hace este PR

Cablea V al servidor Hetzner que Luis levantó esta noche (178.105.135.26:5000, Flask blindado con systemd). V ahora tiene "manos" para ejecutar código real, controlar navegadores y generar imágenes — sin depender de sandboxes ajenas.

Cambios

lib/forge/v-server.ts (nuevo)

Helper callVServer(path, body, opts) que hace POST al Flask del Hetzner:

  • URL configurable vía V_SERVER_URL (default http://178.105.135.26:5000)
  • Timeout configurable (default 35s)
  • Manejo explícito de 404 → mensaje "endpoint no existe aún en api.py"
  • Manejo de timeout / connection refused con mensajes humanos
  • Nunca pretende que jaló cuando falló

lib/forge/tools.ts

3 tools nuevas en el array TOOLS + 3 cases en dispatch():

Tool Endpoint Estado servidor Uso
remote_execution /execute ✅ vivo Probar Python/Node antes de meter a un repo
browser_control /browser ⏳ pendiente Playwright (screenshots, navegación, click, type)
image_generation /generate-image ⏳ pendiente Stable Diffusion (hero images, banners)

remote_execution funciona desde el primer minuto. Los otros dos devuelven 404 con mensaje claro hasta que el servidor implemente los endpoints — V lo reporta sin inventar.

lib/forge/system-prompt.ts

Bloque nuevo "CUERPO EN HETZNER" dentro de SENIOR_ENGINEER_DOCTRINE:

  • V sabe que tiene servidor propio (IP, puerto, qué endpoints viven)
  • Reglas: si la tool falla con "endpoint no existe aún", reportar a Luis claramente, no inventar
  • Encuadre: "el servidor es laboratorio, no producción"

Por qué importa

Hasta hoy V podía pensar y decidir pero no ejecutar código fuera de GitHub/Vercel. Esto lo convierte de chatbot avanzado a agente autónomo real:

  • Probar lógica antes de comitearla
  • Verificar UI tras un deploy
  • Generar assets gráficos en línea

Pendiente del lado del servidor (no de este PR)

En el Hetzner falta implementar en /home/v-server/api.py:

  • POST /browser con Playwright (acciones: screenshot, navigate, extract_text, click, type)
  • POST /generate-image con Stable Diffusion (parámetros: prompt, size, negative_prompt)

Cuando esos endpoints existan, las tools de V automáticamente los usan — sin tocar este repo.

Verificación

  • npx tsc --noEmit → 0 errores
  • Healthcheck del servidor confirmado: curl http://178.105.135.26:5000/health{"status":"healthy"}
  • Tool remote_execution puede probarse mandando {code: "print(1+1)", language: "python"} y debe devolver stdout="2\n", returncode=0

Riesgos

  • El servidor Hetzner es ring 1 (write en recursos propios del operador). remote_execution ejecuta código arbitrario con subprocess.run(['python3', '-c', ...]) — limitado por la sandbox del proceso pero NO aislado del filesystem. Recordatorio en system prompt: nada destructivo.
  • Sin auth en el endpoint /execute todavía. Si la IP del Hetzner se filtra, cualquiera puede ejecutar código. TODO post-merge: añadir header X-V-Token que api.py valide contra un secret compartido.

https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4


Generated by Claude Code

claude added 3 commits May 9, 2026 17:11
vForge ya no depende de Anthropic — todo el motor LLM ahora corre sobre
@google/genai (Gemini 2.5 Flash por default, gratis hasta cuota generosa).

Cambios:
- lib/forge/gemini-adapter.ts (nuevo): wrapper con conversion de tools
  (input_schema -> functionDeclarations), mensajes (text/image -> parts,
  tool_use/tool_result -> functionCall/functionResponse) y streaming
  (eventos compatibles con frontend existente: text, tool_use_start,
  tool_use_result, done).
- lib/forge/tools.ts: TOOLS ya no usa el tipo Tool de Anthropic, usa
  NeutralTool del adapter.
- app/api/forge/run/route.ts: reescrito sobre GoogleGenAI con streamRound
  helper. Mantiene el loop de hasta 5 rondas tool_use, parallel
  executeTool, audit + persistencia conversations sin cambios.
- app/api/forge/recap/route.ts: usa gemini-2.5-flash (en vez de
  claude-haiku-4-5).
- package.json: -@anthropic-ai/sdk +@google/genai.
- migrations/002_seed.sql: default_model = gemini-2.5-flash.
- estimateCost actualizado a pricing Gemini.

Pendiente del operador:
- Agregar GEMINI_API_KEY al vault (o env de Vercel) — el route.ts la lee
  via getOperatorSecret("GEMINI_API_KEY").
- Update fila ai_config.default_model si hay deployment ya corriendo
  (la migracion solo aplica a seeds nuevos).

extract-secret/route.ts no se tocó: ya usaba OpenAI gpt-4o vision, no
Anthropic.
- v-server.ts: helper callVServer() para POST al Flask en 178.105.135.26:5000
  con timeout configurable, manejo de 404 ("endpoint no existe aún") y
  errores de conexión claros (no inventa que jaló).
- tools.ts: 3 tools registradas + ejecutadas vía dispatch:
  · remote_execution → /execute (Python/Node, 30s timeout)
  · browser_control  → /browser (Playwright, pendiente en api.py)
  · image_generation → /generate-image (Stable Diffusion, pendiente)
- system-prompt.ts: bloque CUERPO EN HETZNER en la doctrina senior, V ahora
  sabe que tiene servidor propio, qué endpoints están vivos y cuáles 404
  hasta que el servidor los agregue.

El servidor ya está blindado con systemd (Restart=always, autoarranca al
boot del Hetzner). V puede llamar remote_execution hoy mismo. Las otras
dos tools dependen de que el lado del Hetzner agregue los endpoints
faltantes — el código de V queda listo y reporta 404 limpio mientras.

URL configurable vía env var V_SERVER_URL.

https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4
@vercel

vercel Bot commented May 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vforge Ready Ready Preview, Comment May 16, 2026 7:20am

Request Review

V pidió SSH para administrar servidores remotos sola y un browser_control
con más acciones (get_html, get_text, describe_element, execute_script,
wait_for_selector). Esto cierra el "salto cuántico" que V mencionó:
acceso a servidores + automatización web completa + OSINT.

Cambios:
- tools.ts:
  · ssh_command_executor (RING 2, llama /ssh-execute en Hetzner con
    paramiko). Inputs: host, command, username, password, private_key,
    sudo, port, timeout_seconds (1-300, default 60).
  · browser_control extendido: acciones goto/click/type/screenshot/
    get_html/get_text/describe_element/execute_script. Soporta
    wait_for_selector y return_screenshot_base64.
  · redactInput refuerza: SENSITIVE_KEYS (password, private_key, secret,
    token, api_key, auth, authorization) se reemplazan por
    "[REDACTED N chars]" en el audit log. NUNCA aparece la credencial.
- system-prompt.ts:
  · ssh_command_executor mencionado en EJECUTA, NO ORIENTES.
  · /ssh-execute añadido a "endpoints pendientes en api.py" del bloque
    CUERPO EN HETZNER.
  · Bloque nuevo "SSH A SERVIDORES REMOTOS" con reglas: ring 2,
    describir antes de destructivo, credenciales no en chat, errores
    literales no inventados.

Pendiente del lado del servidor (api.py en Hetzner):
- POST /ssh-execute con paramiko (host, command, username, password,
  private_key, sudo, port, timeout_seconds → stdout, stderr,
  return_code, error).
- POST /browser extendido con las nuevas acciones.

Seguridad pendiente (TODO antes de uso real):
- TLS en el endpoint Hetzner (hoy es http://, las creds viajan plaintext).
- Token de auth en el header para que solo V pueda llamar /ssh-execute.

https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4
Cierra el círculo: las tools que V pidió (ssh_command_executor, browser_control
extendido, image_generation) ya tienen respaldo del lado del Hetzner.

Archivos:
- docs/v-server/api.py — Flask v2 con endpoints:
    /health           → {"status":"healthy","version":2}
    /execute          → Python/Node (igual que v1)
    /ssh-execute      → paramiko (rsa/ed25519/ecdsa, password o key, sudo opcional)
    /browser          → playwright sync, 8 acciones, wait_for_selector,
                        return_screenshot_base64
    /generate-image   → Stability AI core endpoint (PNG base64, 512/768/1024)
  Auth opcional vía header X-V-Token cuando V_SERVER_TOKEN está seteado.

- docs/v-server/install.sh — instala flask/paramiko/playwright/requests +
  chromium en el venv del Hetzner. Idempotente.

- docs/v-server/README.md — dos rutas de deploy:
  · Opción A: V auto-deploys con remote_execution. Snippet con backup,
    write, install deps, restart desacoplado (sleep+nohup para sobrevivir
    el SIGKILL del systemctl restart), verificación /health, rollback.
  · Opción B: Luis con SSH manual.

Pendiente (declarado en README): TLS via nginx+Let's Encrypt, firewall,
V_SERVER_TOKEN obligatorio antes de uso real con credenciales reales.

https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4
… vez de Stability AI

Luis ya paga OpenRouter para Tanit; reutilizamos esa key en lugar de
abrir cuenta nueva en stability.ai. Además los modelos de OpenRouter
son state of the art (Gemini 3.1 Flash Image "Nano Banana") con
soporte de edición y multi-turn — mejor calidad y precio que SDXL.

Cambios:
- docs/v-server/api.py:
  · /generate-image llama a https://openrouter.ai/api/v1/chat/completions
    con modalities=["image","text"], modelo configurable via param
    (default google/gemini-3.1-flash-image-preview).
  · negative_prompt y size se inyectan al prompt como texto adicional
    (OpenRouter no los acepta como params nativos para image gen via
    chat completions).
  · Parseo del data URL devuelto (data:image/png;base64,...) → split de
    mime y base64.
  · Env var OPENROUTER_API_KEY (antes STABILITY_API_KEY).

- docs/v-server/README.md:
  · Instrucciones de env var actualizadas (OPENROUTER_API_KEY,
    reutilizable desde Tanit).
  · Nueva sección "Modelos de imagen soportados" con los IDs de
    OpenRouter (Gemini Image, FLUX 2 Pro, Riverflow v2).

- lib/forge/tools.ts:
  · image_generation: descripción actualizada (~$0.014/imagen, multi-turn).
  · Schema agrega input opcional `model` para que V elija entre Gemini /
    FLUX / Recraft según el caso.
  · Default size cambió a 1024x1024 (era 512x512) — Gemini/FLUX rinden
    bien a 1024 y el costo es similar.

Pendiente del lado servidor: V tiene que redeployar api.py + agregar
OPENROUTER_API_KEY al systemd unit (`systemctl edit v-server`).

https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants