fix new servers added bug in output processing
This commit is contained in:
@@ -108,10 +108,37 @@ class MCPHostManager:
|
||||
def _wait_for_ready(self) -> bool:
|
||||
"""Wait for the process to be ready"""
|
||||
try:
|
||||
self.child.expect(self.config.PROMPT_INDICATOR)
|
||||
logger.success("MCPHost started and ready")
|
||||
self._clear_buffer()
|
||||
return True
|
||||
logger.info("Waiting for MCPHost to be ready...")
|
||||
|
||||
# Collect all output until we see the prompt
|
||||
output = ""
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < self.config.SPAWN_TIMEOUT:
|
||||
try:
|
||||
# Read any available data
|
||||
chunk = self.child.read_nonblocking(size=1000, timeout=0.5)
|
||||
output += chunk
|
||||
|
||||
# Check if we've seen the prompt indicator
|
||||
if self.config.PROMPT_INDICATOR in output:
|
||||
logger.success("MCPHost started and ready")
|
||||
self._clear_buffer()
|
||||
return True
|
||||
|
||||
except pexpect.TIMEOUT:
|
||||
# No data available, continue waiting
|
||||
continue
|
||||
except pexpect.EOF:
|
||||
logger.error("Process ended unexpectedly")
|
||||
logger.debug("Output so far: {}", output)
|
||||
return False
|
||||
|
||||
# If we get here, we've timed out
|
||||
logger.error("Timeout waiting for MCPHost to be ready")
|
||||
logger.debug("Output collected: {}", output[-500:]) # Last 500 chars
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error waiting for prompt: {}", e)
|
||||
return False
|
||||
|
||||
@@ -7,30 +7,12 @@ class Config:
|
||||
# Patterns for cleaning debug output
|
||||
ANSI_PATTERN = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
||||
TUI_BORDER = '┃'
|
||||
|
||||
# Updated patterns to match the actual output format
|
||||
SKIP_PATTERNS = [
|
||||
'alt+enter / ctrl+j new line',
|
||||
'ctrl+e open editor',
|
||||
'enter submit',
|
||||
'ctrl+c to quit',
|
||||
'Enter your prompt',
|
||||
'Type /help for commands'
|
||||
]
|
||||
|
||||
# Updated log pattern to match the actual format: "2025/05/11 00:38:45 INFO <cmd/root.go:495> Model loaded..."
|
||||
DEBUG_LOG_PATTERN = re.compile(r'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \w+ <.*?>.*$', re.MULTILINE)
|
||||
|
||||
# Pattern for thinking spinner (if used)
|
||||
SKIP_PATTERNS = ['alt+enter', 'Enter your prompt']
|
||||
DEBUG_LOG_PATTERN = re.compile(r'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \w+ <.*?>.*$')
|
||||
THINKING_SPINNER_PATTERN = re.compile(r'[⣽⢿⡿⣟⣯⣷⣾⣻] Thinking\.\.\.')
|
||||
|
||||
# Markers and indicators
|
||||
ASSISTANT_MARKER = "Assistant:"
|
||||
PROMPT_INDICATOR = "Enter your prompt"
|
||||
|
||||
# Pattern to match control hints at the bottom
|
||||
CONTROL_HINTS_PATTERN = re.compile(r'(alt\+enter|ctrl\+[a-z]).*?(•|$)', re.IGNORECASE)
|
||||
|
||||
|
||||
def clean_response(response: str, original_prompt: str) -> str:
|
||||
"""Clean and format MCP response"""
|
||||
@@ -38,7 +20,7 @@ def clean_response(response: str, original_prompt: str) -> str:
|
||||
return ""
|
||||
|
||||
# Debug log the raw response
|
||||
logger.debug(f"Raw response before cleaning: {response[:500]}...")
|
||||
logger.debug(f"Raw response before cleaning: {response}")
|
||||
|
||||
# Remove ANSI escape sequences
|
||||
response = Config.ANSI_PATTERN.sub('', response)
|
||||
@@ -82,125 +64,49 @@ def clean_assistant_section(assistant_response: str) -> str:
|
||||
if Config.THINKING_SPINNER_PATTERN.search(line):
|
||||
continue
|
||||
|
||||
# Skip control hints
|
||||
if Config.CONTROL_HINTS_PATTERN.search(line):
|
||||
continue
|
||||
|
||||
# Handle TUI borders
|
||||
if stripped.startswith(Config.TUI_BORDER):
|
||||
content = line.lstrip(Config.TUI_BORDER).strip()
|
||||
# Only add if there's actual content after the border and it's not a skip pattern
|
||||
if content and not any(skip_pattern.lower() in content.lower() for skip_pattern in Config.SKIP_PATTERNS):
|
||||
content = stripped.strip(Config.TUI_BORDER).strip()
|
||||
if content:
|
||||
cleaned_lines.append(content)
|
||||
else:
|
||||
# Add if not a skip pattern
|
||||
if not any(skip_pattern.lower() in stripped.lower() for skip_pattern in Config.SKIP_PATTERNS):
|
||||
cleaned_lines.append(stripped)
|
||||
cleaned_lines.append(stripped)
|
||||
|
||||
return '\n'.join(cleaned_lines).strip()
|
||||
|
||||
|
||||
def clean_entire_response(response: str, original_prompt: str) -> str:
|
||||
"""Clean the entire response when no Assistant: marker is found"""
|
||||
# First remove all debug log lines
|
||||
response = Config.DEBUG_LOG_PATTERN.sub('', response)
|
||||
|
||||
lines = response.split('\n')
|
||||
cleaned_lines = []
|
||||
|
||||
# Flag to track if we've started seeing actual content
|
||||
content_started = False
|
||||
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip empty lines before content starts
|
||||
if not stripped:
|
||||
if content_started:
|
||||
cleaned_lines.append('')
|
||||
# Skip empty lines and original prompt
|
||||
if not stripped or stripped == original_prompt:
|
||||
continue
|
||||
|
||||
# Skip lines that match the original prompt
|
||||
if stripped == original_prompt:
|
||||
content_started = True
|
||||
# Skip debug log lines
|
||||
if Config.DEBUG_LOG_PATTERN.match(line):
|
||||
continue
|
||||
|
||||
# Skip thinking spinner lines
|
||||
if Config.THINKING_SPINNER_PATTERN.search(line):
|
||||
continue
|
||||
|
||||
# Skip control hints
|
||||
if Config.CONTROL_HINTS_PATTERN.search(line):
|
||||
continue
|
||||
|
||||
# Handle TUI decorations
|
||||
if line.startswith(Config.TUI_BORDER):
|
||||
content = line.lstrip(Config.TUI_BORDER).strip()
|
||||
# Skip if it matches any skip pattern
|
||||
if any(skip_pattern.lower() in content.lower() for skip_pattern in Config.SKIP_PATTERNS):
|
||||
continue
|
||||
# Skip if it's empty or just whitespace
|
||||
if not content:
|
||||
continue
|
||||
# Skip if it's the original prompt
|
||||
if content == original_prompt:
|
||||
content_started = True
|
||||
continue
|
||||
|
||||
# If we have actual content, add it
|
||||
if content:
|
||||
content_started = True
|
||||
if stripped.startswith(Config.TUI_BORDER):
|
||||
content = stripped.strip(Config.TUI_BORDER).strip()
|
||||
if content and content != original_prompt:
|
||||
cleaned_lines.append(content)
|
||||
continue
|
||||
|
||||
# Skip navigation hints and other skip patterns
|
||||
if any(skip_pattern.lower() in line.lower() for skip_pattern in Config.SKIP_PATTERNS):
|
||||
# Skip navigation hints
|
||||
if any(pattern in line for pattern in Config.SKIP_PATTERNS):
|
||||
continue
|
||||
|
||||
# Add non-empty, non-decoration lines
|
||||
content_started = True
|
||||
cleaned_lines.append(stripped)
|
||||
|
||||
# Clean up any trailing empty lines
|
||||
while cleaned_lines and not cleaned_lines[-1]:
|
||||
cleaned_lines.pop()
|
||||
|
||||
return '\n'.join(cleaned_lines).strip()
|
||||
|
||||
|
||||
def remove_tui_artifacts(text: str) -> str:
|
||||
"""Remove any remaining TUI artifacts from the text"""
|
||||
# Remove lines that are just TUI borders with spaces
|
||||
lines = text.split('\n')
|
||||
cleaned = []
|
||||
|
||||
for line in lines:
|
||||
# Skip lines that are just TUI borders with spaces
|
||||
if line.strip() == Config.TUI_BORDER or line.strip() == '':
|
||||
if cleaned and cleaned[-1] != '': # Preserve single line breaks
|
||||
cleaned.append('')
|
||||
else:
|
||||
cleaned.append(line)
|
||||
|
||||
return '\n'.join(cleaned).strip()
|
||||
|
||||
|
||||
def post_process_response(response: str) -> str:
|
||||
"""Final post-processing of the cleaned response"""
|
||||
# Remove any remaining TUI artifacts
|
||||
response = remove_tui_artifacts(response)
|
||||
|
||||
# Remove multiple consecutive newlines
|
||||
response = re.sub(r'\n{3,}', '\n\n', response)
|
||||
|
||||
# Remove any remaining debug artifacts that might have slipped through
|
||||
response = re.sub(r'DEBUG|INFO|ERROR|WARN.*?>', '', response)
|
||||
|
||||
return response.strip()
|
||||
|
||||
|
||||
# Export the main cleaning function with additional post-processing
|
||||
def clean_mcphost_response(response: str, original_prompt: str) -> str:
|
||||
"""Main entry point for cleaning MCPHost responses"""
|
||||
cleaned = clean_response(response, original_prompt)
|
||||
return post_process_response(cleaned)
|
||||
return '\n'.join(cleaned_lines).strip()
|
||||
Reference in New Issue
Block a user