feat(forge): conectar V con su servidor Hetzner — 3 tools nuevas - #46
Draft
turbillon50 wants to merge 6 commits into
Draft
feat(forge): conectar V con su servidor Hetzner — 3 tools nuevas#46turbillon50 wants to merge 6 commits into
turbillon50 wants to merge 6 commits into
Conversation
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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:V_SERVER_URL(defaulthttp://178.105.135.26:5000)lib/forge/tools.ts3 tools nuevas en el array
TOOLS+ 3 cases endispatch():remote_execution/executebrowser_control/browserimage_generation/generate-imageremote_executionfunciona desde el primer minuto. Los otros dos devuelven404con mensaje claro hasta que el servidor implemente los endpoints — V lo reporta sin inventar.lib/forge/system-prompt.tsBloque nuevo "CUERPO EN HETZNER" dentro de
SENIOR_ENGINEER_DOCTRINE: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:
Pendiente del lado del servidor (no de este PR)
En el Hetzner falta implementar en
/home/v-server/api.py:POST /browsercon Playwright (acciones: screenshot, navigate, extract_text, click, type)POST /generate-imagecon 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 errorescurl http://178.105.135.26:5000/health→{"status":"healthy"}remote_executionpuede probarse mandando{code: "print(1+1)", language: "python"}y debe devolverstdout="2\n",returncode=0Riesgos
remote_executionejecuta código arbitrario consubprocess.run(['python3', '-c', ...])— limitado por la sandbox del proceso pero NO aislado del filesystem. Recordatorio en system prompt: nada destructivo.X-V-Tokenqueapi.pyvalide contra un secret compartido.https://claude.ai/code/session_01YD9ckFDdBjDhYB6aaH1HR4
Generated by Claude Code