SSE en formato Claude Code CLI via ?format=claude
Nuevo ClaudeFormatEmitter traduce eventos nativos al formato exacto
que produce Claude Code CLI: content_block_start/delta/stop, tool_result,
assistant snapshots, result con usage/cost, done.
- streaming/claude_format.py: ClaudeFormatEmitter + DualEmitter
- base.py: enriquecer eventos con tool_call_id, raw_output, tool_arguments
- engine.py: usage/cost en EXECUTION_COMPLETED
- routes.py: ?format=claude en /sessions/{id}/stream
- main.py: DualEmitter wiring (emite a ambos formatos)
El frontend puede consumir el stream sin cambios — mismos event types
que Claude Code CLI. El formato nativo sigue disponible para el dashboard.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,13 +68,15 @@ def set_dependencies(
|
||||
context_engine: Any,
|
||||
memory_store: Any,
|
||||
sse_emitter: Any,
|
||||
mcp_registry: Any,
|
||||
claude_emitter: Any = None,
|
||||
mcp_registry: Any = None,
|
||||
) -> None:
|
||||
_deps["storage"] = storage
|
||||
_deps["model_adapter"] = model_adapter
|
||||
_deps["context_engine"] = context_engine
|
||||
_deps["memory_store"] = memory_store
|
||||
_deps["sse"] = sse_emitter
|
||||
_deps["claude_sse"] = claude_emitter
|
||||
_deps["mcp_registry"] = mcp_registry
|
||||
|
||||
|
||||
@@ -207,22 +209,33 @@ async def _execute_and_persist(orchestrator, storage, session, message) -> dict[
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@router.get("/sessions/{session_id}/stream")
|
||||
async def stream_session(session_id: str) -> StreamingResponse:
|
||||
async def stream_session(session_id: str, format: str = "native") -> StreamingResponse:
|
||||
storage = _get_storage()
|
||||
session = await storage.get_session(session_id)
|
||||
if not session:
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
|
||||
sse = _get_sse()
|
||||
headers = {
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"X-Accel-Buffering": "no",
|
||||
}
|
||||
|
||||
if format == "claude":
|
||||
claude_sse = _deps.get("claude_sse")
|
||||
if not claude_sse:
|
||||
raise HTTPException(status_code=501, detail="Claude format emitter not available")
|
||||
return StreamingResponse(
|
||||
claude_sse.subscribe(session_id),
|
||||
media_type="text/event-stream",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
sse = _get_sse()
|
||||
return StreamingResponse(
|
||||
sse.subscribe(session_id),
|
||||
media_type="text/event-stream",
|
||||
headers={
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"X-Accel-Buffering": "no",
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user