Refactor cockpit to use DockerTmuxController pattern

Based on claude-code-tools TmuxCLIController, this refactor:

- Added DockerTmuxController class for robust tmux session management
- Implements send_keys() with configurable delay_enter
- Implements capture_pane() for output retrieval
- Implements wait_for_prompt() for pattern-based completion detection
- Implements wait_for_idle() for content-hash-based idle detection
- Implements wait_for_shell_prompt() for shell prompt detection

Also includes workflow improvements:
- Pre-task git snapshot before agent execution
- Post-task commit protocol in agent guidelines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
admin
2026-01-14 10:42:16 -03:00
commit ec33ac1936
265 changed files with 92011 additions and 0 deletions

View File

@@ -0,0 +1,229 @@
#!/usr/bin/env python3
"""
Chat Response Formatter - Format responses for readability
"""
from typing import Dict, Any
import json
class ChatResponseFormatter:
"""Format chat responses in readable markdown"""
def format_kg_search_results(self, results: Dict) -> str:
"""Format KG search results"""
output = []
output.append(f"**Search:** {results.get('query', 'N/A')}")
output.append(f"**Time:** {results.get('execution_time_ms', 0)}ms")
output.append("")
domains = results.get('domains', {})
if not domains:
return "\n".join(output) + "\nNo results found."
for domain, domain_results in domains.items():
if domain_results.get('error'):
continue
entities = domain_results.get('entities', [])
if entities:
output.append(f"### {domain.upper()}")
for entity in entities:
output.append(f"- **{entity['name']}** (`{entity['type']}`)")
output.append("")
if results.get('timeout'):
output.append("⏱️ *Search timed out, showing partial results*")
return "\n".join(output)
def format_entity_details(self, entity: Dict) -> str:
"""Format entity details"""
if 'error' in entity:
return f"{entity['error']}"
output = []
output.append(f"# {entity.get('name', 'Unknown')}")
output.append(f"**Type:** {entity.get('type', 'N/A')}")
output.append(f"**Domain:** {entity.get('domain', 'N/A')}")
output.append("")
if entity.get('description'):
output.append(f"**Description:** {entity['description']}")
output.append("")
if entity.get('observations'):
output.append("**Observations:**")
for obs in entity['observations'][:3]:
output.append(f"- {obs}")
output.append("")
if entity.get('relations'):
output.append("**Relations:**")
for rel in entity['relations'][:5]:
output.append(f"- {rel['from']} **{rel['type']}** {rel['to']}")
output.append("")
return "\n".join(output)
def format_system_status(self, status: Dict) -> str:
"""Format system status"""
output = []
output.append("# System Status")
output.append("")
components = status.get('components', {})
# Uptime
if components.get('uptime', {}).get('output'):
output.append(f"**Uptime:** {components['uptime']['output']}")
# Load
if components.get('load', {}).get('output'):
output.append(f"**Load:** {components['load']['output']}")
# Disk
if components.get('disk', {}).get('output'):
disk_lines = components['disk']['output'].split('\n')
if disk_lines:
output.append(f"**Disk:** {disk_lines[1] if len(disk_lines) > 1 else disk_lines[0]}")
# Memory
if components.get('memory', {}).get('output'):
mem_lines = components['memory']['output'].split('\n')
if mem_lines:
output.append(f"**Memory:** {mem_lines[1] if len(mem_lines) > 1 else mem_lines[0]}")
output.append("")
return "\n".join(output)
def format_command_output(self, result: Dict) -> str:
"""Format bash command output"""
output = []
if not result.get('success'):
error = result.get('error', 'Unknown error')
return f"❌ **Error:** {error}"
output.append(f"**Command:** `{result.get('command', 'N/A')}`")
output.append(f"**Time:** {result.get('execution_time_ms', 0)}ms")
output.append("")
cmd_output = result.get('output', '').strip()
if cmd_output:
# Format output as code block
output.append("```")
# Limit to 20 lines
lines = cmd_output.split('\n')
for line in lines[:20]:
output.append(line)
if len(lines) > 20:
output.append(f"... ({len(lines) - 20} more lines)")
output.append("```")
return "\n".join(output)
def format_project_list(self, projects: Dict) -> str:
"""Format list of projects"""
output = []
output.append("# Projects")
output.append("")
project_list = projects.get('projects', [])
if not project_list:
return "No projects found."
for proj in project_list:
output.append(f"- **{proj['name']}**")
if proj.get('description'):
output.append(f" > {proj['description']}")
output.append("")
output.append(f"*Total: {projects.get('count', len(project_list))} projects*")
return "\n".join(output)
def format_memory_statistics(self, stats: Dict) -> str:
"""Format memory database statistics"""
if not stats.get('available'):
return "❌ Memory database not available"
output = []
output.append("# Memory Database Status")
output.append("")
output.append(f"**Entities:** {stats.get('entities', 0)}")
output.append(f"**Relations:** {stats.get('relations', 0)}")
output.append("")
return "\n".join(output)
def format_help(self) -> str:
"""Format help message"""
output = [
"# Luzia Chat Help",
"",
"## Commands",
"",
"### Search",
"```",
"luzia chat \"search term\"",
"luzia chat --kg \"knowledge graph search\"",
"luzia chat --local \"project memory search\"",
"```",
"",
"### System Status",
"```",
"luzia chat \"system status\"",
"luzia chat --bash \"uptime\"",
"luzia chat --bash \"disk usage\"",
"```",
"",
"### Information",
"```",
"luzia chat \"list projects\"",
"luzia chat \"architecture\"",
"luzia chat --think \"analyze performance\"",
"```",
"",
"### Interactive",
"```",
"luzia chat # Start interactive session",
"> your query",
"> another query",
"> exit",
"```",
"",
]
return "\n".join(output)
def format_error(self, error: str, suggestions: list = None) -> str:
"""Format error message"""
output = [f"❌ **Error:** {error}"]
if suggestions:
output.append("")
output.append("**Suggestions:**")
for suggestion in suggestions[:3]:
output.append(f"- {suggestion}")
return "\n".join(output)
def format_response_time(self, time_ms: float) -> str:
"""Format response time indicator"""
if time_ms < 100:
indicator = "⚡ instant"
elif time_ms < 300:
indicator = "✓ quick"
elif time_ms < 500:
indicator = "↻ normal"
else:
indicator = "⏱ slow"
return f"{indicator} ({time_ms:.0f}ms)"
if __name__ == '__main__':
formatter = ChatResponseFormatter()
# Test
print(formatter.format_help())