Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve cmdline colors in Console #5875

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Dandelionym
Copy link

Why are these changes needed?

This PR enhances the readability of multi-agent conversations in the command line interface by improving the color display system. By adding colorama support with proper type definitions, agent messages are now more distinguishable with customizable colors, making it easier to follow conversations between different agents in the terminal.

image

Related issue number

Enhances UI readability. No specific issue number.

Checks

@Dandelionym
Copy link
Author

@Dandelionym please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree [company="{your company}"]

@microsoft-github-policy-service agree [company="{Westlake University}"]

@Dandelionym
Copy link
Author

@microsoft-github-policy-service agree company="your company"

@microsoft-github-policy-service agree company="Westlake University"

@Dandelionym Dandelionym changed the title Improve cmdline colors in Concole Improve cmdline colors in Console Mar 8, 2025
@@ -16,6 +16,7 @@ classifiers = [
]
dependencies = [
"autogen-core==0.4.8",
"colorama>=0.4.6",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use native coloring code e.g.

# Define ANSI escape sequences for text colors
RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
MAGENTA = '\033[35m'
CYAN = '\033[36m'
RESET = '\033[0m'  # Resets the text to default color

# Example usage
print(f"{RED}This text is red.{RESET}")
print(f"{GREEN}This text is green.{RESET}")
print(f"{YELLOW}This text is yellow.{RESET}")

We don't need to introduce a new dependency just for coloring. For more advanced features like markdown formatting that requires dependencies, we should use autogen-ext package instead of autogen-agentchat.

@@ -85,22 +128,24 @@ async def Console(
no_inline_images: bool = False,
output_stats: bool = False,
user_input_manager: UserInputManager | None = None,
colormap: Optional[Dict[str, str]] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

To make it easier to use, we can automatically assign colors based on the source field observed in the message stream. Each new source gets assigned a new color based on a predefined or an automatically generated sequence of colors.

for example:

def color_generator(step=30):
    """Yields an infinite sequence of distinct RGB colors."""
    hue = 0  # Start from 0
    while True:
        hue = (hue + step) % 360  # Keep hue within 0-360
        r, g, b = hue_to_rgb(hue)
        yield (r, g, b)

def hue_to_rgb(hue):
    """Convert a hue (0-360) to an RGB color (0-255) manually."""
    x = (255 * (1 - abs((hue / 60) % 2 - 1)))  # Intermediate color mixing
    if 0 <= hue < 60:
        return (255, int(x), 0)
    elif 60 <= hue < 120:
        return (int(x), 255, 0)
    elif 120 <= hue < 180:
        return (0, 255, int(x))
    elif 180 <= hue < 240:
        return (0, int(x), 255)
    elif 240 <= hue < 300:
        return (int(x), 0, 255)
    else:
        return (255, 0, int(x))

# Example usage:
color_seq = color_generator()
for _ in range(10):  # Generate 10 distinct colors
    print(next(color_seq))

Copy link
Collaborator

Choose a reason for hiding this comment

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

To convert RGB to ANSI color code using approximation. For example:

def rgb_to_ansi_256(r, g, b):
    """Convert RGB (0-255) to the closest ANSI 256 color."""
    if r == g == b:
        if r < 8:
            return 16
        if r > 248:
            return 231
        return round(((r - 8) / 247) * 24) + 232  # Grayscale range

    return 16 + (36 * round(r / 255 * 5) + 6 * round(g / 255 * 5) + round(b / 255 * 5))

def ansi_256_color_text(text, r, g, b):
    """Wrap text with ANSI escape codes for 256-color mode."""
    color_code = rgb_to_ansi_256(r, g, b)
    return f"\033[38;5;{color_code}m{text}\033[0m"

# Example usage:
print(ansi_256_color_text("Hello in 256-color!", 255, 100, 50))

Copy link
Collaborator

Choose a reason for hiding this comment

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

We can enable automatic coloring by default. The colormap can be a simple boolean type for turning on or off the color printing feature. If in the future a custom colormap is needed, we can come back and add a dictionary option to this parameter.

Copy link
Collaborator

@ekzhu ekzhu left a comment

Choose a reason for hiding this comment

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

We need unit test for this feature to ensure it is working. Please add unit tests to verify colors are added when printing to console. For example,

import pytest

def my_function():
    print("Hello, pytest!")

def test_my_function(capsys: pytest.CaptureFixture[str]) -> None:
    my_function()
    captured = capsys.readouterr()
    assert captured.out.strip() == "Hello, pytest!"

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