729921e16e
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.8 KiB
7.8 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | file_path | params | output | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tee_anthropic_sse | function | py | cybersecurity | 1.0.0 | impure | class AnthropicSSETee — mitmproxy addon loaded via mitmdump -s | Addon de mitmproxy que intercepta el stream SSE de la API de Anthropic (/v1/messages) y emite cada evento significativo a stdout como NDJSON en tiempo real. Cada interaccion de la CLI claude dispara una o varias llamadas a /v1/messages; el addon las etiqueta con stream_id, model y has_tools para que el consumidor pueda distinguir la respuesta principal (claude-opus-X con tools) de las auxiliares (titulo/clasificador en haiku sin tools). Las funciones puras split_sse_events y event_to_ndjson son testeables sin mitmproxy. |
|
false | error_go_core |
|
true |
|
python/functions/cybersecurity/tests/test_tee_anthropic_sse.py | python/functions/cybersecurity/tee_anthropic_sse.py |
|
NDJSON a stdout, un objeto JSON por linea (flush inmediato). Tipos de linea: message_start{stream_id,model,has_tools} al inicio de cada stream; text_delta{stream_id,text} por cada fragmento de texto del modelo; tool_use_start{stream_id,tool_name,tool_id} cuando el modelo inicia una herramienta; tool_json_delta{stream_id,partial_json} por cada fragmento de argumentos JSON de la herramienta; message_stop{stream_id,stop_reason} al finalizar el stream. stderr recibe solo mensajes de diagnóstico del addon (errores, warnings), nunca NDJSON. |
Ejemplo
# Terminal 1: lanzar mitmproxy como proxy de interceptacion
# -q suprime el log de mitmdump; solo se ve el NDJSON en stdout
mitmdump -p 8901 \
-s python/functions/cybersecurity/tee_anthropic_sse.py \
-q
# Terminal 2: lanzar claude por el proxy
# NODE_EXTRA_CA_CERTS hace que el runtime Node de claude confie en la CA de mitmproxy
export HTTPS_PROXY=http://127.0.0.1:8901
export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
claude -p "di hola"
# Salida en stdout de mitmdump (Terminal 1):
# {"type": "message_start", "stream_id": 1, "model": "claude-haiku-4-5", "has_tools": false}
# {"type": "text_delta", "stream_id": 1, "text": "H"}
# {"type": "text_delta", "stream_id": 1, "text": "ola"}
# {"type": "message_stop", "stream_id": 1, "stop_reason": "end_turn"}
# ...
# {"type": "message_start", "stream_id": 2, "model": "claude-opus-4-8", "has_tools": true}
# {"type": "text_delta", "stream_id": 2, "text": "Hola"}
# ...
# Filtrar solo la respuesta principal (has_tools=true) con jq:
mitmdump -p 8901 -s python/functions/cybersecurity/tee_anthropic_sse.py -q \
| jq -c 'select(.has_tools == true or .stream_id != null and (.type == "text_delta"))'
# O usar la variable de entorno para que el addon ya filtre en origen:
FN_WIRE_ONLY_TOOLS=1 mitmdump -p 8901 \
-s python/functions/cybersecurity/tee_anthropic_sse.py -q
Cuando usarla
Cuando quieras el texto exacto que el modelo genera en tiempo real desde una sesion claude (TUI interactiva o claude -p), interceptando la red, sin parsear el render de la terminal ni depender de warmup/idle de la TUI. Util para: capturar la salida del modelo para procesado downstream (logging estructurado, metricas de tokens, replay), observar tool_use en construccion (argumentos parciales), o depurar la diferencia entre streams principales y auxiliares en una misma sesion TUI.
Gotchas
- Descompresion via strip de Accept-Encoding: el hook
requestelimina el headerAccept-Encodingde las llamadas a/v1/messagespara que la API responda con el SSE SIN comprimir. Esto es obligatorio: el modo streaming de mitmproxy (flow.response.stream) entrega al tee los bytes CRUDOS del cuerpo, que si vinieran conContent-Encoding: gzip/brnunca contendrian el delimitador\n\nde eventos SSE (se veria binario) y no se emitiria ningun delta. Verificado empiricamente el 2026-06-04: sin el strip, solo se emitiamessage_start; con el strip, lostext_deltasalen correctamente. La alternativa (un decompresor de streaming con estado por flujo) es mas fragil. El coste es unos bytes extra en el salto local, irrelevante. - NO usar
--set stream_large_bodies: el modo streaming se activa conflow.response.stream = funcenresponseheaders, sin necesidad de ese flag. Ademasstream_large_bodies=Nbajo rompe el acceso aflow.request.content(necesario parahas_tools), porque tambien streamea el cuerpo del request y deja de bufferearlo. - Requiere mitmproxy + CA confiada por claude: la CA de mitmproxy (
~/.mitmproxy/mitmproxy-ca-cert.pem) debe estar configurada enNODE_EXTRA_CA_CERTSpara que el runtime Node de la CLI claude acepte el certificado MITM. Sin esto, claude rechaza la conexion con error de TLS. Instalar mitmproxy:uv tool install mitmproxyopip install mitmproxy. claude tambien respetaHTTPS_PROXYpara enrutar su trafico por el proxy. - Una interaccion TUI dispara varias /v1/messages: la respuesta real del usuario usa el modelo principal (p.ej. claude-opus-4-8) y su request body incluye el array
toolscon las herramientas de Claude Code. Las llamadas auxiliares (generador de titulo, clasificador) usan claude-haiku y su request NO llevatools. Usahas_tools=trueoFN_WIRE_ONLY_TOOLS=1para aislar la respuesta principal y no mezclar streams. - Solo funciona mientras claude no haga TLS pinning: hoy (2026-06-04) la CLI claude no hace certificate pinning, por lo que el MITM funciona con
NODE_EXTRA_CA_CERTS. Si una version futura de claude añade pinning, el addon dejara de interceptar. - Es trafico de tu propia cuenta y maquina: el addon captura unicamente el trafico local que tu proxy intercepta. No hay acceso a otras cuentas ni sesiones remotas. El NDJSON se emite solo a stdout local.
- El endpoint puede cambiar: la CLI claude hoy usa
POST /v1/messages?beta=true. El addon filtra por prefix/v1/messagespara tolerar variantes de query string, pero si Anthropic cambia la ruta base en versiones futuras del protocolo, actualizar el check enresponseheaders. - Chunks parciales: el addon mantiene un buffer por stream para manejar eventos SSE partidos entre chunks TCP. Si mitmdump se mata con SIGKILL durante un stream activo, el ultimo bloque incompleto del buffer se descarta (no se emite un message_stop artificial).
- stdout debe ser exclusivamente NDJSON: no añadir prints de debug a stdout; redirigir diagnosticos a stderr. Si se canaliza la salida a
jqu otro parser, cualquier linea no-JSON rompe el pipeline.