Skip to content

Providers and Agents es

Hermes Agent edited this page Oct 1, 2026 · 1 revision

Proveedores y agentes

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

Cuatro protocolos de red (apiStyle)

lib/llm-client.js es la capa de protocolo. Los cuatro streams comparten un único esqueleto openSseStream() (fetch / clasificación de errores / negociación de presupuesto / abort / enmarcado SSE / finalización); cada protocolo conserva solo buildRequest + parsers de eventos puros. La extracción del payload data: de SSE tiene una única fuente (sseDataPayload, unión de múltiples líneas data según la especificación):

apiStyle Endpoint Notas
chat /v1/chat/completions también parsea el reasoning_content estilo DeepSeek
responses /v1/responses ortografía multimodal input_* nativa
anthropic /v1/messages cache_control explícito en dos breakpoints (system + último mensaje) — Anthropic no tiene caché de prefijo implícita
runs Hermes /v1/runs protocolo de agente: eventos de approvals / clarifications / tools / thinking

thinking: 'inline' | 'omit' (por defecto omit) controla si el texto de razonamiento viaja en UN bloque <thinking> inline en el stream de deltas; solo el chat principal y el hilo de detalle usan inline. El campo reasoning.available de runs es una repetición de la respuesta, no razonamiento — la guarda de eco debe descartarlo (ADR-0004).

La escalera de turn-request

La forma de la petición por proveedor se reconstruye cuatro veces en el chat principal (inicial / reconstrucción por desbordamiento / continuación / reescritura de timestamps), unificada como createTurnRequest (prepare / rebuildFrom / continueWith / rewriteWith) — chat-handler conserva el CUÁNDO, la escalera posee el CÓMO. El hilo de detalle deliberadamente no la usa (semántica de sesión aislada, ADR-0007).

Presupuesto de salida y truncado

  • max_tokens por defecto 32768; los servidores que RECHAZAN un presupuesto sobre el límite con un 400 obtienen un reintento renegotiateOutputCap con el límite parseado del texto del error.
  • finish_reason === 'length' → UNA pasada de continuación silenciosa (instrucción anti-repetición, deltas descartados); si sigue truncado → DONE lleva outputTruncated, el panel muestra un toast + un botón de «continuar» de un clic. Deliberadamente NO hay campo manual de max_tokens — «un control que exige conocimiento por modelo es un bug de diseño».

Los cuatro agentes

Agente Canal Sesiones
Hermes /v1/runs del lado del servidor (sessionId en storage); las partes del turno actual usan text/image_url canónicos, conversation_history es solo de cadenas (422 en la capa estricta, verificado 2026-09-24)
OpenCode opencode serve HTTP del lado del servidor; puerto aleatorio por defecto → se recomienda un --port fijo
OpenSquilla gateway local ws://…/ws una sesión de gateway por conversación; los adjuntos de >60K caracteres se suben como documento page-context.md; allowlist de orígenes — ver Security Model
Agent Bridge daemon local @xiaohuzai/agent-bridge adapta codex/claude/pi/gemini tras un único protocolo HTTP; los logins de suscripción funcionan como fuentes de modelos

La capa compartida lib/agent-turn.js: un turno de agente envía SOLO el turno actual del usuario + el run final de page-context (la transcripción vive del lado del servidor; el historial nunca se reenvía). Las imágenes pasan por pickTurnImages (≤8 imágenes / presupuesto de URLs de ≤3MiB; las compuertas en el adjunto y en el envío se reflejan mutuamente). Cambiar a un proveedor de agente a mitad de conversación ofrece 「带上当前对话继续」(continuar con la conversación actual) = un backfill de un solo uso (transcripción en texto plano, tope de cola de 200K caracteres).

Traspaso entre entradas: nombrado e ID de sesión del lado del agente (2026-10-01)

Para los proveedores de agente la transcripción ya vive del lado del servidor (los turnos de agente envían solo el turno actual) — «dejar que la UI del propio agente tome el relevo» necesita descubribilidad, no movimiento de datos. Dos piezas:

  • Nombrado automático: tras un turno Hermes exitoso, un PATCH /api/sessions/{id} de un solo uso (API original del upstream; el servidor sanitiza los títulos y rechaza conflictos exactos) fija el título a browsa: + la primera línea del texto del usuario del turno actual (tope de 48 caracteres). Semántica de sello único (hermesSessionTitled_<provider>, mismo ciclo de vida que el id de sesión): el éxito Y los 4xx sellan (un conflicto de título no debe convertirse en un bucle de reintento por turno); solo los fallos de transporte (status 0) quedan sin sellar para el siguiente turno exitoso. El PATCH caduca a los 10s y su await compite con un tope de 2.5s para que DONE nunca se quede colgado. Canales hoy: Hermes (PATCH /api/sessions/{id}) y bridge/codex (el POST /threads/{id}/title del daemon → app-server thread/name/set, verificado en vivo sobre codex 0.149.1 — el nombre persiste en la base de estado de codex y codex resume resuelve por nombre o id; veredictos de visibilidad en el picker para los cuatro agentes del bridge (verificados en fuente 2026-10-01): codex ✓ (predicado del picker has_user_event = 1 AND title <> '' — los turnos reales lo cumplen; base de estado global, sin acotado por cwd; nombrado vía el POST /threads/{id}/title del daemon → app-server thread/name/set). claude ✓ desde que el transcriptFix: 'claude' del bridge reescribe en disco el entrypoint: sdk-* auto-sellado a cli tras cada turno asentado (agent-bridge #56, confirmado en Mac) — sin canal de renombrado por cliente (claude-agent-acp titula automáticamente), el resume funciona desde el picker o por ID. pi ✓ (las sesiones ACP aterrizan en el almacén propio de pi acotado por cwd que el picker lee; conmutador de scope + filtro por nombre; el RPC nativo set_session_name de pi escribe una entrada de nombre session_info — pi-acp solo lo expone como el comando /name del turno, aún sin cablear al bridge). gemini ✓ (la lista excluye solo kind:"subagent"; las sesiones del bridge son kind:"main"; almacén ~/.gemini/tmp/<cwd>/chats/, acotado por cwd; sin canal de nombrado — el título sale del primer mensaje del usuario). opencode/squilla sin verificar. Las sesiones dedicadas del hilo de detalle deliberadamente NO se titulan.)
  • Visualización del ID de sesión: storage.getAgentSessionInfo posee en exclusiva las formas de clave de sesión por tipo (bridge con clave por endpoint vía activeModel || baseUrl); el cajón de sesiones renderiza una línea «Sesión de agente» (id corto + copiar) sobre la lista, oculta para proveedores LLM / cuando no existe sesión.

Relevo de approval / clarify

Las aprobaciones de herramientas del agente y las preguntas de aclaración se relevan a través de lib/handlers/approval-relay.js (chat principal con clave tabId, hilo de detalle por subId). La forma de la entrada pendiente ES la interfaz de despacho. En el lado de la UI, turn-chrome.js es el chrome de turno compartido por ambas superficies (indicador de espera, progreso de herramientas, tarjetas de approval/clarify, chip de uso).

UI de selección de proveedor (reglas cerradas)

  • El desplegable lista solo los proveedores CONFIGURADOS, los alcanzables primero (orden estable); cero configurados → un placeholder deshabilitado.
  • Si el activeProvider almacenado no está configurado, el primero configurado se auto-selecciona Y se persiste (reparación de estado, no preferencia); el primer ping alcanzable también auto-cambia (una vez).
  • Proveedores multi-modelo: IDs de modelo separados por comas; una entrada de desplegable por modelo; resolveChatModel honra activeModel solo mientras siga perteneciendo a ese proveedor.
  • Ambos grupos (LLM / agente) se renderizan como tarjetas con pestañas (el grupo de agentes colapsado por defecto; el orden de pestañas [bridge, opencode, hermes] está fijado por test).

Economía de CAPABILITY_HINTS (ADR-0010 — no volver a proponer reducirlo)

El system prompt de cada turno CHAT = systemPrompt del usuario + línea de idioma de respuesta + CAPABILITY_HINTS + CHOICE_REQUEST_HINT; debe seguir siendo un prefijo estable byte a byte (el filtrado por palabras clave por turno rompe la caché KV del prompt desde la posición 0). Cada entrada restante se pagó sola con un bug real de renderizado — no «apretar» una cláusula de por qué sin leer su historia en AGENTS.md. La corrección para un formato que se escapa es un mejor hint, no detección en tiempo de ejecución.


Versiones autoritativas: Providers-and-Agents (inglés) / Providers-and-Agents-zh (chino) — instantánea de primera traducción por IA, sincronizada el 2026-10-01.

Clone this wiki locally