a digital person for bluesky

Simplify logging format to use plain text with underscores

Replace Rich panel formatting with simple text output using underscores
for titles. This provides a cleaner, more minimal logging style without
external dependencies.

Changes:
- Remove all Rich imports (Panel, Console, Table, Text)
- Replace panel displays with title + underscores format
- Remove --rich command line option
- Update log_with_panel to use simple print statements
- Remove USE_RICH and console global variables

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

+45 -154
+45 -154
bsky.py
··· 1 - from rich import print # pretty printing tools 2 - from rich.console import Console 3 - from rich.table import Table 4 - from rich.panel import Panel 5 - from rich.text import Text 6 from time import sleep 7 from letta_client import Letta 8 from bsky_utils import thread_to_yaml_string ··· 48 # Logging will be configured after argument parsing 49 logger = None 50 prompt_logger = None 51 - console = None 52 - USE_RICH = False 53 SHOW_REASONING = False 54 last_archival_query = "archival memory search" 55 56 def log_with_panel(message, title=None, border_color="white"): 57 - """Log a message with Rich panel if USE_RICH is enabled, otherwise use regular logger""" 58 - if USE_RICH and console: 59 - if title: 60 - panel = Panel( 61 - message, 62 - title=title, 63 - title_align="left", 64 - border_style=border_color, 65 - padding=(0, 1) 66 - ) 67 - console.print(panel) 68 - else: 69 - console.print(message) 70 else: 71 - logger.info(message) 72 73 74 # Create a client with extended timeout for LLM operations ··· 348 # Continue without user blocks rather than failing completely 349 350 # Get response from Letta agent 351 - if USE_RICH: 352 - # Create and print Rich panel directly 353 - mention_panel = Panel( 354 - mention_text, 355 - title=f"MENTION FROM @{author_handle}", 356 - title_align="left", 357 - border_style="cyan", 358 - padding=(0, 1) 359 - ) 360 - console.print(mention_panel) 361 - else: 362 - # Simple text format when Rich is disabled 363 - print(f"\n{'='*60}") 364 - print(f"MENTION FROM @{author_handle}") 365 - print('='*60) 366 - print(f"{mention_text}") 367 - print('='*60 + "\n") 368 369 # Log prompt details to separate logger 370 prompt_logger.debug(f"Full prompt being sent:\n{prompt}") ··· 389 if hasattr(chunk, 'message_type'): 390 if chunk.message_type == 'reasoning_message': 391 # Show full reasoning without truncation 392 - if SHOW_REASONING and USE_RICH: 393 - # Create and print Rich panel for reasoning 394 - reasoning_panel = Panel( 395 - chunk.reasoning, 396 - title="Reasoning", 397 - title_align="left", 398 - border_style="yellow", 399 - padding=(0, 1) 400 - ) 401 - console.print(reasoning_panel) 402 - elif SHOW_REASONING: 403 - # Simple text format when Rich is disabled but reasoning is enabled 404 - print(f"\n{'='*60}") 405 - print("Reasoning") 406 - print('='*60) 407 - print(f"{chunk.reasoning}") 408 - print('='*60 + "\n") 409 else: 410 # Default log format (only when --reasoning is used due to log level) 411 - if USE_RICH: 412 - reasoning_panel = Panel( 413 - chunk.reasoning, 414 - title="Reasoning", 415 - title_align="left", 416 - border_style="yellow", 417 - padding=(0, 1) 418 - ) 419 - console.print(reasoning_panel) 420 - else: 421 - logger.info(f"Reasoning: {chunk.reasoning}") 422 elif chunk.message_type == 'tool_call_message': 423 # Parse tool arguments for better display 424 tool_name = chunk.tool_call.name ··· 429 # Extract the text being posted 430 text = args.get('text', '') 431 if text: 432 - if USE_RICH: 433 - post_panel = Panel( 434 - text, 435 - title="Bluesky Post", 436 - title_align="left", 437 - border_style="blue", 438 - padding=(0, 1) 439 - ) 440 - console.print(post_panel) 441 - else: 442 - print(f"\n{'='*60}") 443 - print("Bluesky Post") 444 - print('='*60) 445 - print(text) 446 - print('='*60 + "\n") 447 else: 448 log_with_panel(chunk.tool_call.arguments[:150] + "...", f"Tool call: {tool_name}", "blue") 449 elif tool_name == 'archival_memory_search': 450 query = args.get('query', 'unknown') 451 global last_archival_query 452 last_archival_query = query 453 - if USE_RICH: 454 - tool_panel = Panel( 455 - f"query: \"{query}\"", 456 - title=f"Tool call: {tool_name}", 457 - title_align="left", 458 - border_style="blue", 459 - padding=(0, 1) 460 - ) 461 - console.print(tool_panel) 462 - else: 463 - log_with_panel(f"query: \"{query}\"", f"Tool call: {tool_name}", "blue") 464 elif tool_name == 'archival_memory_insert': 465 content = args.get('content', '') 466 # Show the full content being inserted 467 - if USE_RICH: 468 - tool_panel = Panel( 469 - content, 470 - title=f"Tool call: {tool_name}", 471 - title_align="left", 472 - border_style="blue", 473 - padding=(0, 1) 474 - ) 475 - console.print(tool_panel) 476 - else: 477 - log_with_panel(content, f"Tool call: {tool_name}", "blue") 478 elif tool_name == 'update_block': 479 label = args.get('label', 'unknown') 480 value_preview = str(args.get('value', ''))[:50] + "..." if len(str(args.get('value', ''))) > 50 else str(args.get('value', '')) ··· 535 content = entry.get('content', '') 536 content_text += f"[{i}/{len(results)}] {timestamp}\n{content}\n\n" 537 538 - if USE_RICH: 539 - # Create and print Rich panel directly 540 - memory_panel = Panel( 541 - content_text.strip(), 542 - title=f"{search_query} ({len(results)} results)", 543 - title_align="left", 544 - border_style="blue", 545 - padding=(0, 1) 546 - ) 547 - console.print(memory_panel) 548 - else: 549 - # Use simple text format when Rich is disabled 550 - print(f"\n{search_query} ({len(results)} results)") 551 - print("="*80) 552 - print(content_text.strip()) 553 - print("="*80 + "\n") 554 555 except Exception as e: 556 logger.error(f"Error formatting archival memory results: {e}") ··· 588 else: 589 logger.info(f"Tool result: {tool_name} - {status}") 590 elif chunk.message_type == 'assistant_message': 591 - if USE_RICH: 592 - # Create and print Rich panel directly 593 - response_panel = Panel( 594 - chunk.content, 595 - title="Assistant Response", 596 - title_align="left", 597 - border_style="green", 598 - padding=(0, 1) 599 - ) 600 - console.print(response_panel) 601 - else: 602 - # Simple text format when Rich is disabled 603 - print(f"\n{'='*60}") 604 - print("Assistant Response") 605 - print('='*60) 606 - print(f"{chunk.content}") 607 - print('='*60 + "\n") 608 else: 609 # Filter out verbose message types 610 if chunk.message_type not in ['usage_statistics', 'stop_reason']: ··· 818 content = "\n\n".join([f"{j}. {msg}" for j, msg in enumerate(reply_messages, 1)]) 819 title = f"Reply Thread to @{author_handle} ({len(reply_messages)} messages)" 820 821 - if USE_RICH: 822 - reply_panel = Panel( 823 - content, 824 - title=title, 825 - title_align="left", 826 - border_style="green", 827 - padding=(0, 1) 828 - ) 829 - console.print(reply_panel) 830 - else: 831 - print(f"\n{title}") 832 - print("="*60) 833 - print(content) 834 - print("="*60 + "\n") 835 836 # Send the reply(s) with language (unless in testing mode) 837 if testing_mode: ··· 1265 parser.add_argument('--test', action='store_true', help='Run in testing mode (no messages sent, queue files preserved)') 1266 parser.add_argument('--no-git', action='store_true', help='Skip git operations when exporting agent state') 1267 parser.add_argument('--simple-logs', action='store_true', help='Use simplified log format (void - LEVEL - message)') 1268 - parser.add_argument('--rich', action='store_true', help='Enable Rich formatting for archival memory display') 1269 parser.add_argument('--reasoning', action='store_true', help='Display reasoning in panels and set reasoning log level to INFO') 1270 args = parser.parse_args() 1271 ··· 1295 logging.getLogger("httpx").setLevel(logging.CRITICAL) 1296 1297 # Create Rich console for pretty printing 1298 - console = Console() 1299 1300 - global TESTING_MODE, SKIP_GIT, USE_RICH, SHOW_REASONING 1301 TESTING_MODE = args.test 1302 1303 # Store no-git flag globally for use in export_agent_state calls 1304 SKIP_GIT = args.no_git 1305 1306 # Store rich flag globally 1307 - USE_RICH = args.rich 1308 1309 # Store reasoning flag globally 1310 SHOW_REASONING = args.reasoning
··· 1 + # Rich imports removed - using simple text formatting 2 from time import sleep 3 from letta_client import Letta 4 from bsky_utils import thread_to_yaml_string ··· 44 # Logging will be configured after argument parsing 45 logger = None 46 prompt_logger = None 47 + # Simple text formatting (Rich no longer used) 48 SHOW_REASONING = False 49 last_archival_query = "archival memory search" 50 51 def log_with_panel(message, title=None, border_color="white"): 52 + """Log a message with simple text format""" 53 + if title: 54 + print(f"\n{title}") 55 + print("_" * len(title)) 56 + print(message) 57 else: 58 + print(message) 59 60 61 # Create a client with extended timeout for LLM operations ··· 335 # Continue without user blocks rather than failing completely 336 337 # Get response from Letta agent 338 + # Simple text format with underscores 339 + title = f"MENTION FROM @{author_handle}" 340 + print(f"\n{title}") 341 + print("_" * len(title)) 342 + print(mention_text) 343 344 # Log prompt details to separate logger 345 prompt_logger.debug(f"Full prompt being sent:\n{prompt}") ··· 364 if hasattr(chunk, 'message_type'): 365 if chunk.message_type == 'reasoning_message': 366 # Show full reasoning without truncation 367 + if SHOW_REASONING: 368 + # Simple text format with underscores 369 + print("\nReasoning") 370 + print("_________") 371 + print(chunk.reasoning) 372 else: 373 # Default log format (only when --reasoning is used due to log level) 374 + # Simple text format with underscores 375 + print("\nReasoning") 376 + print("_________") 377 + print(chunk.reasoning) 378 elif chunk.message_type == 'tool_call_message': 379 # Parse tool arguments for better display 380 tool_name = chunk.tool_call.name ··· 385 # Extract the text being posted 386 text = args.get('text', '') 387 if text: 388 + # Simple text format with underscores 389 + print("\nBluesky Post") 390 + print("____________") 391 + print(text) 392 else: 393 log_with_panel(chunk.tool_call.arguments[:150] + "...", f"Tool call: {tool_name}", "blue") 394 elif tool_name == 'archival_memory_search': 395 query = args.get('query', 'unknown') 396 global last_archival_query 397 last_archival_query = query 398 + log_with_panel(f"query: \"{query}\"", f"Tool call: {tool_name}", "blue") 399 elif tool_name == 'archival_memory_insert': 400 content = args.get('content', '') 401 # Show the full content being inserted 402 + log_with_panel(content, f"Tool call: {tool_name}", "blue") 403 elif tool_name == 'update_block': 404 label = args.get('label', 'unknown') 405 value_preview = str(args.get('value', ''))[:50] + "..." if len(str(args.get('value', ''))) > 50 else str(args.get('value', '')) ··· 460 content = entry.get('content', '') 461 content_text += f"[{i}/{len(results)}] {timestamp}\n{content}\n\n" 462 463 + # Simple text format with underscores 464 + title = f"{search_query} ({len(results)} results)" 465 + print(f"\n{title}") 466 + print("_" * len(title)) 467 + print(content_text.strip()) 468 469 except Exception as e: 470 logger.error(f"Error formatting archival memory results: {e}") ··· 502 else: 503 logger.info(f"Tool result: {tool_name} - {status}") 504 elif chunk.message_type == 'assistant_message': 505 + # Simple text format with underscores 506 + print("\nAssistant Response") 507 + print("__________________") 508 + print(chunk.content) 509 else: 510 # Filter out verbose message types 511 if chunk.message_type not in ['usage_statistics', 'stop_reason']: ··· 719 content = "\n\n".join([f"{j}. {msg}" for j, msg in enumerate(reply_messages, 1)]) 720 title = f"Reply Thread to @{author_handle} ({len(reply_messages)} messages)" 721 722 + # Simple text format with underscores 723 + print(f"\n{title}") 724 + print("_" * len(title)) 725 + print(content) 726 727 # Send the reply(s) with language (unless in testing mode) 728 if testing_mode: ··· 1156 parser.add_argument('--test', action='store_true', help='Run in testing mode (no messages sent, queue files preserved)') 1157 parser.add_argument('--no-git', action='store_true', help='Skip git operations when exporting agent state') 1158 parser.add_argument('--simple-logs', action='store_true', help='Use simplified log format (void - LEVEL - message)') 1159 + # --rich option removed as we now use simple text formatting 1160 parser.add_argument('--reasoning', action='store_true', help='Display reasoning in panels and set reasoning log level to INFO') 1161 args = parser.parse_args() 1162 ··· 1186 logging.getLogger("httpx").setLevel(logging.CRITICAL) 1187 1188 # Create Rich console for pretty printing 1189 + # Console no longer used - simple text formatting 1190 1191 + global TESTING_MODE, SKIP_GIT, SHOW_REASONING 1192 TESTING_MODE = args.test 1193 1194 # Store no-git flag globally for use in export_agent_state calls 1195 SKIP_GIT = args.no_git 1196 1197 # Store rich flag globally 1198 + # Rich formatting no longer used 1199 1200 # Store reasoning flag globally 1201 SHOW_REASONING = args.reasoning