MCPcopy Create free account
hub / github.com/IBM/mcp-cli / _run_enhanced_chat_loop

Function _run_enhanced_chat_loop

src/mcp_cli/chat/chat_handler.py:416–608  ·  view source on GitHub ↗

Run the main chat loop with enhanced streaming support. Args: ui: UI manager with streaming coordination ctx: Chat context convo: Conversation processor with streaming support max_turns: Maximum conversation turns before forcing exit (default: 100)

(
    ui: ChatUIManager,
    ctx: ChatContext,
    convo: ConversationProcessor,
    max_turns: int = 100,
)

Source from the content-addressed store, hash-verified

414
415
416async def _run_enhanced_chat_loop(
417 ui: ChatUIManager,
418 ctx: ChatContext,
419 convo: ConversationProcessor,
420 max_turns: int = 100,
421) -> None:
422 """
423 Run the main chat loop with enhanced streaming support.
424
425 Args:
426 ui: UI manager with streaming coordination
427 ctx: Chat context
428 convo: Conversation processor with streaming support
429 max_turns: Maximum conversation turns before forcing exit (default: 100)
430 """
431 # Shared queue: terminal reader task and browser WebSocket both put messages here.
432 # This lets browser input arrive during the terminal prompt wait.
433 # Type is Any because we also put _INTERRUPT sentinel objects on the queue.
434 input_queue: asyncio.Queue = asyncio.Queue()
435
436 # Wire dashboard bridge so browser USER_MESSAGE/USER_COMMAND go into the queue.
437 if bridge := getattr(ctx, "dashboard_bridge", None):
438 bridge.set_input_queue(input_queue)
439
440 # Gate the prompt display: the reader waits for this event before showing
441 # the "💬 You:" prompt, preventing streaming / tool output from overwriting it.
442 prompt_ready = asyncio.Event()
443 prompt_ready.set() # Ready immediately for the first prompt
444
445 # Background task: reads terminal input and forwards to the queue.
446 reader_task = asyncio.create_task(
447 _terminal_reader(ui, input_queue, ready=prompt_ready)
448 )
449
450 try:
451 while True:
452 try:
453 user_msg = await input_queue.get()
454
455 # Handle interrupt sentinel forwarded from _terminal_reader
456 if user_msg is _INTERRUPT:
457 logger.info(
458 "Interrupt forwarded from reader — streaming=%s, tools_running=%s",
459 ui.is_streaming_response,
460 ui.tools_running,
461 )
462 if ui.is_streaming_response:
463 output.warning("\nStreaming interrupted - type 'exit' to quit.")
464 ui.interrupt_streaming()
465 elif ui.tools_running:
466 output.warning(
467 "\nTool execution interrupted - type 'exit' to quit."
468 )
469 ui._interrupt_now()
470 else:
471 output.warning("\nInterrupted - type 'exit' to quit.")
472 prompt_ready.set()
473 continue

Calls 15

parse_inline_refsFunction · 0.90
process_local_fileFunction · 0.90
detect_image_urlsFunction · 0.90
build_multimodal_contentFunction · 0.90
attachment_descriptorFunction · 0.90
_terminal_readerFunction · 0.85
set_input_queueMethod · 0.80
setMethod · 0.80
_interrupt_nowMethod · 0.80
print_user_messageMethod · 0.80
drainMethod · 0.80
on_messageMethod · 0.80