From 067d228d9e821c29c10bcdd649b4ca3b5589c251 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 3 Jun 2026 08:20:28 -0400 Subject: [PATCH] feat(sloppy): add --web-host and --web-port args for web mode --- sloppy.py | 34 +++++++++++++++++++++++++++++++--- src/markdown_helper.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/sloppy.py b/sloppy.py index eeebd6d0..e09db99c 100644 --- a/sloppy.py +++ b/sloppy.py @@ -1,3 +1,4 @@ +import argparse import sys import os @@ -16,7 +17,34 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false" from defer.sugar import install as _install_defer _install_defer() -from src.gui_2 import main +parser = argparse.ArgumentParser(description="Manual Slop entry point") +parser.add_argument("--headless", action="store_true", help="Run in headless mode without GUI") +parser.add_argument("--web-host", default=None, help="Enable web mode and bind to this host (e.g., 0.0.0.0)") +parser.add_argument("--web-port", type=int, default=8080, help="Web mode port (default: 8080)") +parser.add_argument("--enable-test-hooks", action="store_true", help="Enable the HookServer on :8999 for external automation") +args = parser.parse_args() -if __name__ == "__main__": - main() +if args.web_host is not None: + from imgui_bundle import hello_imgui + from src.api_hooks import HookServer + + if args.enable_test_hooks: + hook_server = HookServer() + hook_server.start() + + runner_params = hello_imgui.RunnerParams() + runner_params.app_window_params.window_title = "Manual Slop (Web)" + runner_params.app_window_params.borderless = True + runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_docker_space + runner_params.app_window_params.restore_previous_window_size = True + + from src.gui_2 import App + app = App() + hello_imgui.run(runner_params, lambda: app.render_frame()) +elif args.headless: + from src.app_controller import AppController + controller = AppController(headless=True) + controller.run() +else: + from src.gui_2 import main + main() \ No newline at end of file diff --git a/src/markdown_helper.py b/src/markdown_helper.py index 95a61918..5d3ee168 100644 --- a/src/markdown_helper.py +++ b/src/markdown_helper.py @@ -130,10 +130,20 @@ class MarkdownRenderer: """Render Markdown text with automatic unindentation.""" imgui_md.render_unindented(text) - def render_code(self, code: str, lang: str = "", context_id: str = "default", block_idx: int = 0) -> None: - """Render a code block directly with syntax highlighting.""" - # Wrap in fake markdown markers for the internal renderer - self._render_code_block(f"```{lang}\n{code}```", context_id, block_idx) + def _render_code_block(self, block: str, context_id: str, block_idx: int) -> None: + """Render a code block using TextEditor for syntax highlighting.""" + lines = block.strip('`').split('\n') + lang_tag = lines[0].strip().lower() if lines else "" + + # Heuristic to separate lang tag from code + if lang_tag and lang_tag not in self._lang_map and not self._is_likely_lang_tag(lang_tag): + lang_tag = "" + code = '\n'.join(lines) + else: + code = '\n'.join(lines[1:]) if len(lines) > 1 else "" + + if not lang_tag: + lang_tag = self.detect_language(code) # Cache management if len(self._editor_cache) > self._max_cache_size: @@ -166,6 +176,19 @@ class MarkdownRenderer: _set_editor_language(editor, lang_id) self._editor_lang_cache[cache_key] = lang_tag + # Dynamic height calculation + line_count = code.count('\n') + 1 + line_height = imgui.get_text_line_height() + height = (line_count * line_height) + 20 + height = min(max(height, 40), 500) + + editor.render(f"##code_{context_id}_{block_idx}", a_size=imgui.ImVec2(0, height)) + + def render_code(self, code: str, lang: str = "", context_id: str = "default", block_idx: int = 0) -> None: + """Render a code block directly with syntax highlighting.""" + # Wrap in fake markdown markers for the internal renderer + self._render_code_block(f"```{lang}\n{code}```", context_id, block_idx) + def _is_likely_lang_tag(self, tag: str) -> bool: return bool(re.match(r'^[a-zA-Z0-9+#-]+$', tag)) and len(tag) < 15