Skip to content

Cli stream#791

Open
tallate wants to merge 20 commits intomainfrom
cli_activeskill
Open

Cli stream#791
tallate wants to merge 20 commits intomainfrom
cli_activeskill

Conversation

@tallate
Copy link
Collaborator

@tallate tallate commented Feb 28, 2026

  1. cli: Exit silently on Ctrl+C
  2. cli: stream output(gemini, claude)
    2.1 llm_agent output chunk, ignore empty chunk
    2.2 token statistics
    2.3 tool_calls array type parameter
  3. developer agent: generate code step by step, forbid super large code generation in one step
  4. when a .env file is set in the current directory, the global --config option will be ignored

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience of the CLI by introducing real-time streaming of agent responses with detailed token usage statistics, making interactions more dynamic and transparent. It also bolsters the CLI's stability through improved interrupt handling and refines agent behavior with updated prompting guidelines, leading to more predictable and controlled execution of tasks.

Highlights

  • Real-time Streaming Output with Token Statistics: Implemented real-time streaming of LLM responses and tool calls in the CLI, utilizing rich.Live for dynamic display. This includes a new StreamTokenStats utility to track and show input/output tokens and tool call counts during active streaming, providing immediate feedback on agent activity and resource usage.
  • Enhanced CLI Robustness and Interrupt Handling: Improved the CLI's resilience to KeyboardInterrupt (Ctrl+C) by suppressing tracebacks for cleaner exits and ensuring background processes (like terminal commands) are properly isolated to prevent them from being terminated with the main CLI process. Session exit logic was also simplified.
  • Agent Prompting and Behavior Guidance: Updated agent prompts across AWorld, Developer, and Explorer agents to include stricter guidelines. These include explicit path restrictions for terminal_tool usage (prohibiting cd commands and enforcing relative/absolute paths), directives against one-shot large file creation/modification, and instructions for handling consecutive user messages in chat sessions.
  • Stream Configuration and Environment Variable Integration: Added a new configuration option for enabling/disabling streaming display, which is resolved from the global config and applied to the STREAM environment variable. This allows users to control streaming behavior via configuration or environment settings.
  • Executor Resource Management: Introduced a cleanup_resources method in BaseAgentExecutor and its LocalExecutor subclass, ensuring that resources (such as MCP connections) are properly released when an executor session ends, even during unexpected exits like KeyboardInterrupt.
  • Refined Tool Call Display Logic: Centralized the formatting of tool calls into a new _format_tool_calls_display_lines method for consistent rendering across streaming and non-streaming outputs. This also includes logic to merge arguments from 'unknown' tool calls and truncate long argument displays for better readability.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • aworld-cli/src/aworld_cli/console.py
    • Imported os module.
    • Imported resolve_stream_value from core config.
    • Added stream configuration prompt to _edit_models_config to allow users to enable/disable streaming and set the STREAM environment variable.
    • Simplified the exit logic in run_chat_session.
    • Enhanced KeyboardInterrupt handling in run_chat_session to check for buffered input, allowing users to continue or exit based on input state.
  • aworld-cli/src/aworld_cli/core/config.py
    • Added resolve_stream_value function to determine the STREAM environment variable value based on configuration.
    • Added apply_stream_env function to set the STREAM environment variable.
    • Integrated apply_stream_env into load_config_with_env to ensure stream settings are applied during configuration loading.
  • aworld-cli/src/aworld_cli/executors/base_executor.py
    • Added an asynchronous cleanup_resources method for subclasses to override, facilitating resource release.
    • Adjusted padding for tool call panels from (1, 2) to (0, 2).
    • Introduced _format_tool_calls_display_lines to standardize tool call display formatting, including handling of code execution and argument truncation.
    • Modified _render_simple_message_output to use the new tool call formatting function and accept a content_already_streamed flag.
    • Updated _render_simple_tool_result_output to display tool results on a single, truncated line.
  • aworld-cli/src/aworld_cli/executors/local.py
    • Imported re, time, Group, Live from rich and StreamTokenStats, format_elapsed from a new stats module.
    • Implemented cleanup_resources to close MCP and other resources.
    • Refactored stream consumption logic to integrate rich.Live for real-time display of agent output, tool calls, and token statistics.
    • Updated _update_elapsed_time, _start_loading_status, and _stop_loading_status to manage rich.Live and StreamTokenStats during streaming.
    • Added handling for ChunkOutput to accumulate streaming content and update token statistics dynamically.
    • Modified MessageOutput and ToolResultOutput processing to coordinate with streaming display, avoiding redundant output.
  • aworld-cli/src/aworld_cli/executors/stats.py
    • Added new file stats.py containing utility functions format_tokens, format_chars, format_elapsed.
    • Defined StreamTokenStats class for tracking and formatting token usage and tool call statistics during streaming, including methods for updating, clearing, and formatting display lines.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/aworld_agent.py
    • Added a path restriction directive to the terminal_tool description in the prompt.
    • Included a directive for handling consecutive user messages in the prompt.
    • Enabled llm_stream_call for the AWorld agent's LLM configuration.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/developer/developer.py
    • Enabled llm_stream_call for the Developer agent's LLM configuration.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/developer/prompt.txt
    • Added a core directive prohibiting one-shot large file creation or modification, enforcing segmented output.
    • Added path restriction to the terminal tool usage in the 'Iterative Code Generation' section.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/evaluator/evaluator.py
    • Enabled llm_stream_call for the Evaluator agent's LLM configuration.
    • Removed 'human' from the list of tool_names for the Evaluator agent.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/evaluator/mcp_config.py
    • Removed the ms-playwright configuration from the MCP config.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/evaluator/prompt.txt
    • Added a path restriction directive to the terminal_tool description in the prompt.
    • Added a directive prohibiting the use of browser_take_screenshot due to large file size issues.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/explorer/explorer.py
    • Enabled llm_stream_call for the Explorer agent's LLM configuration.
  • aworld-cli/src/aworld_cli/inner_plugins/smllc/agents/explorer/prompt.txt
    • Added a path restriction directive to the terminal tool usage in the prompt.
  • aworld-cli/src/aworld_cli/main.py
    • Implemented _suppress_keyboard_interrupt_traceback to handle KeyboardInterrupt gracefully and exit cleanly.
    • Removed the import of console from ._globals.
  • aworld-cli/src/aworld_cli/runtime/base.py
    • Wrapped the main CLI loop in a try...finally block to ensure executor.cleanup_resources() is always called on exit.
  • aworld/agents/llm_agent.py
    • Imported ModelUtils for token calculation.
    • Added logic to pre-calculate estimated prompt tokens for streaming display.
    • Refined tool call accumulation during streaming to handle 'unknown' tool calls and merge arguments.
    • Integrated ChunkOutput into task outputs to provide real-time streaming data to the local executor.
    • Removed the if not response: return check in send_agent_response_output to allow sending empty responses.
  • aworld/experimental/cast/tools/cast_coder_tool.py
    • Updated the description for the target_dir parameter to explicitly require an absolute path.
  • aworld/mcp_client/utils.py
    • Added traceback.format_exc() to error logging for call_mcp_tool_with_reuse to provide more detailed debugging information.
  • aworld/models/model_response.py
    • Reordered imports for consistency.
    • Updated from_openai_stream_chunk to correctly extract content and tool_calls from OpenAI stream chunks.
  • aworld/models/openai_provider.py
    • Reordered imports for consistency.
    • Added debug logging for stream processing.
    • Ensured func_args is initialized to an empty string to prevent None values in early tool call chunks.
    • Updated the call to ModelResponse.from_openai_stream_chunk to correctly pass content and tool calls.
  • aworld/output/init.py
    • Imported ChunkOutput.
  • aworld/output/base.py
    • Added a new ChunkOutput class for representing streaming LLM chunks.
  • aworld/runners/event_runner.py
    • Modified mark_completed call to ensure a valid response object is always passed, even if the original response is None.
  • examples/init.py
    • Implemented _suppress_keyboard_interrupt_traceback to handle KeyboardInterrupt gracefully and exit cleanly for example scripts.
  • examples/gaia/mcp_collections/tools/terminal.py
    • Imported subprocess module.
    • Added start_new_session=True for Unix and CREATE_NEW_PROCESS_GROUP for Windows to _execute_command_async to ensure commands run in isolated process groups, improving Ctrl+C handling.
    • Added logging configuration to reduce verbose MCP SDK output.
    • Implemented silent exit on KeyboardInterrupt and asyncio.CancelledError for the main execution block to prevent noisy tracebacks.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant enhancement to the CLI by adding a real-time streaming interface for agent interactions, complete with token usage statistics. The changes also include substantial improvements to user experience, such as more graceful handling of keyboard interrupts and cleaner exit behavior. Additionally, several agent prompts have been refined to provide clearer instructions and constraints, which should improve agent performance and reliability. My review includes a couple of suggestions to enhance the robustness of the new streaming logic and error handling.

Comment on lines +970 to +971
except Exception:
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a bare except Exception: pass is generally discouraged as it can silently swallow any and all errors, making debugging difficult. It would be more robust to catch specific expected exceptions (e.g., AttributeError) or at least log the exception that was caught.

except Exception as e:
    logger.debug(f"Could not get prompt buffer content on interrupt: {e}")
    pass

Comment on lines +902 to +907
for tc in chunk.tool_calls:
if tc.function.name == "unknown" and llm_response.tool_calls:
last = llm_response.tool_calls[-1]
last.function.arguments = (last.function.arguments or "") + (tc.function.arguments or "")
else:
llm_response.tool_calls.append(tc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic to merge tool call arguments for chunks with tc.function.name == "unknown" seems fragile. It assumes that such a chunk always belongs to the immediately preceding tool call. This might not hold true if tool call chunks arrive out of order or if a new tool call starts with an "unknown" name. This could lead to incorrectly merged arguments. Consider making this logic more robust, for example by using the tool call index (if available from the provider) to ensure arguments are appended to the correct tool call.

@tallate tallate changed the title Cli activeskill Cli stream Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants