Repository navigation
Providers and Agents es
English | 中文 | 日本語 | 한국어 | Español | Português | Русский
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 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).
-
max_tokenspor defecto 32768; los servidores que RECHAZAN un presupuesto sobre el límite con un 400 obtienen un reintentorenegotiateOutputCapcon 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 llevaoutputTruncated, 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».
| 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).
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 abrowsa:+ 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 (elPOST /threads/{id}/titledel daemon → app-serverthread/name/set, verificado en vivo sobre codex 0.149.1 — el nombre persiste en la base de estado de codex ycodex resumeresuelve 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 pickerhas_user_event = 1 AND title <> ''— los turnos reales lo cumplen; base de estado global, sin acotado por cwd; nombrado vía elPOST /threads/{id}/titledel daemon → app-serverthread/name/set). claude ✓ desde que eltranscriptFix: 'claude'del bridge reescribe en disco elentrypoint: sdk-*auto-sellado aclitras 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 nativoset_session_namede pi escribe una entrada de nombresession_info— pi-acp solo lo expone como el comando/namedel turno, aún sin cablear al bridge). gemini ✓ (la lista excluye solokind:"subagent"; las sesiones del bridge sonkind:"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.getAgentSessionInfoposee en exclusiva las formas de clave de sesión por tipo (bridge con clave por endpoint víaactiveModel || 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.
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).
- 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;
resolveChatModelhonra 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).
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.
English
- Home
- Architecture
- Rendering Pipeline
- Storage Model
- Providers and Agents
- ASR and Video Analysis
- Security Model
- Design Decisions
- Contributing
中文
相关 / Related
日本語
한국어
Español
- Inicio
- Arquitectura
- Pipeline de renderizado
- Modelo de almacenamiento
- Proveedores y agentes
- ASR y análisis de vídeo
- Modelo de seguridad
- Decisiones de diseño
- Contribuir
Português
- Início
- Arquitetura
- Pipeline de renderização
- Modelo de armazenamento
- Provedores e agentes
- ASR e análise de vídeo
- Modelo de segurança
- Decisões de design
- Contribuindo
Русский