Fix stream ai bug
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
__version__ = "6.0.0b4"
|
__version__ = "6.0.0b5"
|
||||||
|
|||||||
+15
-6
@@ -271,7 +271,7 @@ class ai:
|
|||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
chunk_callback(delta.content)
|
chunk_callback(delta.content)
|
||||||
|
|
||||||
if not debug and not chunk_callback:
|
if not chunk_callback:
|
||||||
if not is_streaming_text:
|
if not is_streaming_text:
|
||||||
# Stop spinner definitively
|
# Stop spinner definitively
|
||||||
if status:
|
if status:
|
||||||
@@ -279,9 +279,15 @@ class ai:
|
|||||||
status.stop()
|
status.stop()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Create a stable, direct Console to bypass _ConsoleProxy recreation bugs
|
||||||
|
from rich.console import Console as RichConsole
|
||||||
|
from .printer import connpy_theme, get_original_stdout
|
||||||
|
stable_console = RichConsole(theme=connpy_theme, file=get_original_stdout())
|
||||||
|
|
||||||
live_display = Live(
|
live_display = Live(
|
||||||
Panel(Markdown(full_content), title=title, border_style=border, expand=False),
|
Panel(Markdown(full_content), title=title, border_style=border, expand=False),
|
||||||
console=self.console,
|
console=stable_console,
|
||||||
refresh_per_second=8,
|
refresh_per_second=8,
|
||||||
transient=False
|
transient=False
|
||||||
)
|
)
|
||||||
@@ -303,7 +309,10 @@ class ai:
|
|||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
live_display.stop()
|
try:
|
||||||
|
live_display.stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Rebuild complete response from chunks
|
# Rebuild complete response from chunks
|
||||||
try:
|
try:
|
||||||
@@ -989,7 +998,7 @@ class ai:
|
|||||||
streamed_response = False
|
streamed_response = False
|
||||||
try:
|
try:
|
||||||
safe_messages = self._sanitize_messages(messages)
|
safe_messages = self._sanitize_messages(messages)
|
||||||
if stream and chunk_callback:
|
if stream:
|
||||||
response, streamed_response = self._stream_completion(
|
response, streamed_response = self._stream_completion(
|
||||||
model=model, messages=safe_messages, tools=tools, api_key=key,
|
model=model, messages=safe_messages, tools=tools, api_key=key,
|
||||||
status=status, label=label, debug=debug, num_retries=3,
|
status=status, label=label, debug=debug, num_retries=3,
|
||||||
@@ -1028,8 +1037,8 @@ class ai:
|
|||||||
if msg_dict.get("tool_calls") and msg_dict.get("content") == "": msg_dict["content"] = None
|
if msg_dict.get("tool_calls") and msg_dict.get("content") == "": msg_dict["content"] = None
|
||||||
messages.append(msg_dict)
|
messages.append(msg_dict)
|
||||||
|
|
||||||
if debug and resp_msg.content:
|
if debug and resp_msg.content and not streamed_response:
|
||||||
# In CLI debug mode, only print intermediate reasoning if there are tool calls.
|
# In CLI debug mode, only print intermediate reasoning if there are tool calls AND it wasn't already streamed.
|
||||||
# If there are no tool calls, this content is the final answer and will be printed by the caller.
|
# If there are no tool calls, this content is the final answer and will be printed by the caller.
|
||||||
if resp_msg.tool_calls:
|
if resp_msg.tool_calls:
|
||||||
if status:
|
if status:
|
||||||
|
|||||||
@@ -604,21 +604,33 @@ class AIStub:
|
|||||||
|
|
||||||
if response.debug_message:
|
if response.debug_message:
|
||||||
if debug:
|
if debug:
|
||||||
|
if live_display:
|
||||||
|
try: live_display.stop()
|
||||||
|
except: pass
|
||||||
if status:
|
if status:
|
||||||
try: status.stop()
|
try: status.stop()
|
||||||
except: pass
|
except: pass
|
||||||
printer.console.print(Text.from_ansi(response.debug_message))
|
printer.console.print(Text.from_ansi(response.debug_message))
|
||||||
if status:
|
if live_display:
|
||||||
|
try: live_display.start()
|
||||||
|
except: pass
|
||||||
|
elif status:
|
||||||
try: status.start()
|
try: status.start()
|
||||||
except: pass
|
except: pass
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if response.important_message:
|
if response.important_message:
|
||||||
|
if live_display:
|
||||||
|
try: live_display.stop()
|
||||||
|
except: pass
|
||||||
if status:
|
if status:
|
||||||
try: status.stop()
|
try: status.stop()
|
||||||
except: pass
|
except: pass
|
||||||
printer.console.print(Text.from_ansi(response.important_message))
|
printer.console.print(Text.from_ansi(response.important_message))
|
||||||
if status:
|
if live_display:
|
||||||
|
try: live_display.start()
|
||||||
|
except: pass
|
||||||
|
elif status:
|
||||||
try: status.start()
|
try: status.start()
|
||||||
except: pass
|
except: pass
|
||||||
continue
|
continue
|
||||||
@@ -627,14 +639,33 @@ class AIStub:
|
|||||||
if response.text_chunk:
|
if response.text_chunk:
|
||||||
full_content += response.text_chunk
|
full_content += response.text_chunk
|
||||||
|
|
||||||
if status and not debug:
|
if not live_display:
|
||||||
# Update the spinner line with a preview of the response
|
if status:
|
||||||
preview = full_content.replace("\n", " ").strip()
|
try: status.stop()
|
||||||
if len(preview) > 60: preview = preview[:57] + "..."
|
except: pass
|
||||||
status.update(f"[ai_status]{preview}")
|
|
||||||
|
from rich.console import Console as RichConsole
|
||||||
|
from ..printer import connpy_theme, get_original_stdout
|
||||||
|
stable_console = RichConsole(theme=connpy_theme, file=get_original_stdout())
|
||||||
|
|
||||||
|
# We default to Engineer title during stream, final result will correct it if needed
|
||||||
|
live_display = Live(
|
||||||
|
Panel(Markdown(full_content), title="[bold engineer]Network Engineer[/bold engineer]", border_style="engineer", expand=False),
|
||||||
|
console=stable_console,
|
||||||
|
refresh_per_second=8,
|
||||||
|
transient=False
|
||||||
|
)
|
||||||
|
live_display.start()
|
||||||
|
else:
|
||||||
|
live_display.update(
|
||||||
|
Panel(Markdown(full_content), title="[bold engineer]Network Engineer[/bold engineer]", border_style="engineer", expand=False)
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if response.is_final:
|
if response.is_final:
|
||||||
|
if live_display:
|
||||||
|
try: live_display.stop()
|
||||||
|
except: pass
|
||||||
# Final stop for status to ensure it disappears before the panel
|
# Final stop for status to ensure it disappears before the panel
|
||||||
if status:
|
if status:
|
||||||
try: status.stop()
|
try: status.stop()
|
||||||
@@ -646,10 +677,13 @@ class AIStub:
|
|||||||
role_label = "Network Architect" if responder == "architect" else "Network Engineer"
|
role_label = "Network Architect" if responder == "architect" else "Network Engineer"
|
||||||
title = f"[bold {alias}]{role_label}[/bold {alias}]"
|
title = f"[bold {alias}]{role_label}[/bold {alias}]"
|
||||||
|
|
||||||
# Always print the final Panel
|
|
||||||
content_to_print = full_content or final_result.get("response", "")
|
content_to_print = full_content or final_result.get("response", "")
|
||||||
if content_to_print:
|
if content_to_print:
|
||||||
printer.console.print(Panel(Markdown(content_to_print), title=title, border_style=alias, expand=False))
|
if live_display:
|
||||||
|
# Re-render the final frame with correct title/colors
|
||||||
|
live_display.update(Panel(Markdown(content_to_print), title=title, border_style=alias, expand=False))
|
||||||
|
else:
|
||||||
|
printer.console.print(Panel(Markdown(content_to_print), title=title, border_style=alias, expand=False))
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Check if it was a gRPC error that we should let handle_errors catch
|
# Check if it was a gRPC error that we should let handle_errors catch
|
||||||
|
|||||||
Reference in New Issue
Block a user