From f173396b0ac57cd20272744275ba8057a3ce165b Mon Sep 17 00:00:00 2001 From: BrunoV21 Date: Fri, 29 Aug 2025 18:12:26 +0100 Subject: [PATCH 1/5] colouredCODETIDE and AGENTIDE ASCII Art --- codetide/__init__.py | 3 ++- codetide/agents/tide/agent.py | 3 ++- codetide/agents/tide/consts.py | 14 ++++++-------- codetide/core/defaults.py | 14 ++++++-------- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/codetide/__init__.py b/codetide/__init__.py index d134df2..913c0d7 100644 --- a/codetide/__init__.py +++ b/codetide/__init__.py @@ -86,7 +86,8 @@ async def from_path( codeTide._add_results_to_codebase(results) codeTide._resolve_files_dependencies() - logger.info(f"\n{CODETIDE_ASCII_ART}\nInitialized with {len(results)} files processed in {time.time() - st:.2f}s") + print(f"\n{CODETIDE_ASCII_ART}\n") + logger.info(f"Initialized with {len(results)} files processed in {time.time() - st:.2f}s") return codeTide diff --git a/codetide/agents/tide/agent.py b/codetide/agents/tide/agent.py index c6621cd..d298c91 100644 --- a/codetide/agents/tide/agent.py +++ b/codetide/agents/tide/agent.py @@ -275,7 +275,8 @@ def _(event): # 2. Create a prompt session with the custom key bindings session = PromptSession(key_bindings=bindings) - _logger.logger.info(f"\n{AGENT_TIDE_ASCII_ART}\nReady to surf. Press ESC to exit.\n") + print(f"\n{AGENT_TIDE_ASCII_ART}\n") + _logger.logger.info("Ready to surf. Press ESC to exit.") try: while True: try: diff --git a/codetide/agents/tide/consts.py b/codetide/agents/tide/consts.py index 6f818a1..14185cb 100644 --- a/codetide/agents/tide/consts.py +++ b/codetide/agents/tide/consts.py @@ -1,10 +1,8 @@ AGENT_TIDE_ASCII_ART = """ - -█████╗ ██████╗ ███████╗███╗ ██╗████████╗ ████████╗██╗██████╗ ███████╗ -██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ╚══██╔══╝██║██╔══██╗██╔════╝ -███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ ██║██║ ██║█████╗ -██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██╔══╝ -██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ██║ ██║██████╔╝███████╗ -╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝ - +\033[1;38;5;25m█████╗ ██████╗ ███████╗███╗ ██╗████████╗ ████████╗██╗██████╗ ███████╗\033[0m +\033[1;38;5;33m██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ╚══██╔══╝██║██╔══██╗██╔════╝\033[0m +\033[1;38;5;39m███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ ██║██║ ██║█████╗\033[0m +\033[1;38;5;45m██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██╔══╝\033[0m +\033[1;38;5;51m██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ██║ ██║██████╔╝███████╗\033[0m +\033[1;38;5;255m╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝\033[0m """ \ No newline at end of file diff --git a/codetide/core/defaults.py b/codetide/core/defaults.py index 9e4b7ca..618239f 100644 --- a/codetide/core/defaults.py +++ b/codetide/core/defaults.py @@ -92,12 +92,10 @@ DEFAULT_BYTES_CONTENT_PLACEHOLDERS = "< suppressed bytes content >" CODETIDE_ASCII_ART = """ - -███████╗ ██████╗ ██████╗ ███████╗████████╗██╗██████╗ ███████╗ -██╔════╝██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔══██╗██╔════╝ -██║ ██║ ██║██║ ██║█████╗ ██║ ██║██║ ██║█████╗ -██║ ██║ ██║██║ ██║██╔══╝ ██║ ██║██║ ██║██╔══╝ -╚██████╗╚██████╔╝██████╔╝███████╗ ██║ ██║██████╔╝███████╗ - ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝ - +\033[1;38;5;25m███████╗ ██████╗ ██████╗ ███████╗████████╗██╗██████╗ ███████╗\033[0m +\033[1;38;5;33m██╔════╝██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔══██╗██╔════╝\033[0m +\033[1;38;5;39m██║ ██║ ██║██║ ██║█████╗ ██║ ██║██║ ██║█████╗\033[0m +\033[1;38;5;45m██║ ██║ ██║██║ ██║██╔══╝ ██║ ██║██║ ██║██╔══╝\033[0m +\033[1;38;5;51m╚██████╗╚██████╔╝██████╔╝███████╗ ██║ ██║██████╔╝███████╗\033[0m +\033[1;38;5;255m ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝\033[0m """ \ No newline at end of file From 45ade869928938ea75a96ee6f27b6ebbfcac619d Mon Sep 17 00:00:00 2001 From: BrunoV21 Date: Fri, 29 Aug 2025 22:39:19 +0100 Subject: [PATCH 2/5] added support to pass rootpath to process_patch --- codetide/mcp/tools/patch_code/__init__.py | 6 +++--- codetide/mcp/tools/patch_code/parser.py | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/codetide/mcp/tools/patch_code/__init__.py b/codetide/mcp/tools/patch_code/__init__.py index b933065..813bbdb 100644 --- a/codetide/mcp/tools/patch_code/__init__.py +++ b/codetide/mcp/tools/patch_code/__init__.py @@ -10,7 +10,7 @@ # --------------------------------------------------------------------------- # # User-facing API # --------------------------------------------------------------------------- # -def text_to_patch(text: str, orig: Dict[str, str]) -> Tuple[Patch, int]: +def text_to_patch(text: str, orig: Dict[str, str], rootpath: Optional[pathlib.Path]=None) -> Tuple[Patch, int]: """Improved version with better splitlines handling.""" lines = text.splitlines() @@ -37,7 +37,7 @@ def text_to_patch(text: str, orig: Dict[str, str]) -> Tuple[Patch, int]: if not lines or not Parser._norm(lines[-1]) == "*** End Patch": raise DiffError(f"Invalid patch text - must end with '*** End Patch'. Found: '{lines[-1] if lines else 'empty'}'") - parser = Parser(current_files=orig, lines=lines, index=1) + parser = Parser(current_files=orig, lines=lines, index=1, rootpath=rootpath) parser.parse() return parser.patch, parser.fuzz @@ -138,7 +138,7 @@ def process_patch( path = str(root_path / path) orig_files[path] = open_fn(path) - patch, _fuzz = text_to_patch(text, orig_files) + patch, _fuzz = text_to_patch(text, orig_files, rootpath=root_path) commit = patch_to_commit(patch, orig_files) apply_commit(commit, write_fn, remove_fn, exists_fn) diff --git a/codetide/mcp/tools/patch_code/parser.py b/codetide/mcp/tools/patch_code/parser.py index bf81f89..8a58e6c 100644 --- a/codetide/mcp/tools/patch_code/parser.py +++ b/codetide/mcp/tools/patch_code/parser.py @@ -2,6 +2,7 @@ from typing import Dict, List, Optional, Tuple, Union from dataclasses import dataclass, field +from pathlib import Path # --------------------------------------------------------------------------- # # Helper functions for parsing update chunks @@ -218,6 +219,7 @@ class Parser: index: int = 0 patch: Patch = field(default_factory=Patch) fuzz: int = 0 + rootpath: Optional[Path]=None def _cur_line(self) -> str: if self.index >= len(self.lines): @@ -261,6 +263,8 @@ def parse(self) -> None: while not self.is_done(("*** End Patch",)): # ---------- UPDATE ---------- # if path := self.read_str("*** Update File: "): + if self.rootpath is not None: + path = str(self.rootpath / path) if path in self.patch.actions: raise DiffError(f"Duplicate update for file: {path}") move_to = self.read_str("*** Move to: ") From ffb1619c2de42c046251af8e975372e402521361 Mon Sep 17 00:00:00 2001 From: BrunoV21 Date: Fri, 29 Aug 2025 23:11:22 +0100 Subject: [PATCH 3/5] fixed steps timing --- codetide/agents/tide/ui/app.py | 4 ++-- examples/hf_demo_space/app.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/codetide/agents/tide/ui/app.py b/codetide/agents/tide/ui/app.py index 85dd357..568ec56 100644 --- a/codetide/agents/tide/ui/app.py +++ b/codetide/agents/tide/ui/app.py @@ -321,7 +321,8 @@ async def agent_loop(message: Optional[cl.Message]=None, codeIdentifiers: Option break await stream_processor.process_chunk(chunk) - + + await asyncio.sleep(0.5) if agent_tide_ui.agent_tide.steps: cl.user_session.set("latest_step_message", msg) msg.actions = [ @@ -355,7 +356,6 @@ async def agent_loop(message: Optional[cl.Message]=None, codeIdentifiers: Option chat_history.append({"role": "assistant", "content": msg.content}) await agent_tide_ui.add_to_history(msg.content) - await asyncio.sleep(0.5) if agent_tide_ui.agent_tide._has_patch: choice = await cl.AskActionMessage( content="AgentTide is asking you to review the Patch before applying it.", diff --git a/examples/hf_demo_space/app.py b/examples/hf_demo_space/app.py index 788dc24..c39892c 100644 --- a/examples/hf_demo_space/app.py +++ b/examples/hf_demo_space/app.py @@ -355,6 +355,7 @@ async def agent_loop(message: Optional[cl.Message]=None, codeIdentifiers: Option await stream_processor.process_chunk(chunk) + await asyncio.sleep(0.5) if agent_tide_ui.agent_tide.steps: cl.user_session.set("latest_step_message", msg) msg.actions = [ @@ -397,7 +398,6 @@ async def agent_loop(message: Optional[cl.Message]=None, codeIdentifiers: Option chat_history.append({"role": "assistant", "content": msg.content}) await agent_tide_ui.add_to_history(msg.content) - await asyncio.sleep(0.5) if agent_tide_ui.agent_tide._has_patch: choice = await cl.AskActionMessage( content="AgentTide is asking you to review the Patch before applying it.", From 5488db9ac2fe5ff2a37556626a9183a2ea29533d Mon Sep 17 00:00:00 2001 From: BrunoV21 Date: Fri, 29 Aug 2025 23:11:44 +0100 Subject: [PATCH 4/5] added missing index.write --- codetide/agents/tide/agent.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codetide/agents/tide/agent.py b/codetide/agents/tide/agent.py index d298c91..16bd3c9 100644 --- a/codetide/agents/tide/agent.py +++ b/codetide/agents/tide/agent.py @@ -191,6 +191,8 @@ async def _stage(self)->str: for path in self.changed_paths: index.add(path) + index.write() + staged_diff = await self.get_git_diff_staged_simple(self.tide.rootpath) staged_diff = staged_diff.strip() return staged_diff if staged_diff else "No files were staged. Nothing to commit. Tell the user to request some changes so there is something to commit" From 958113abf45fc6cb619dba315adf95caca1fee82 Mon Sep 17 00:00:00 2001 From: BrunoV21 Date: Fri, 29 Aug 2025 23:37:38 +0100 Subject: [PATCH 5/5] fixed bug with latent commit markers --- codetide/agents/tide/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/codetide/agents/tide/utils.py b/codetide/agents/tide/utils.py index 496a8e3..7fca8cc 100644 --- a/codetide/agents/tide/utils.py +++ b/codetide/agents/tide/utils.py @@ -57,24 +57,24 @@ def parse_patch_blocks(text: str, multiple: bool = True) -> Union[str, List[str] def parse_commit_blocks(text: str, multiple: bool = True) -> Union[str, List[str], None]: """ - Extract content between *** Begin Patch and *** End Patch markers (inclusive), + Extract content between *** Begin Commit and *** End Commit markers (exclusive), ensuring that both markers are at zero indentation (start of line, no leading spaces). Args: - text: Full input text containing one or more patch blocks. - multiple: If True, return a list of all patch blocks. If False, return the first match. + text: Full input text containing one or more commit blocks. + multiple: If True, return a list of all commit blocks. If False, return the first match. Returns: - A string (single patch), list of strings (multiple patches), or None if not found. + A string (single commit), list of strings (multiple commits), or None if not found. """ - pattern = r"(?m)^(\*\*\* Begin Commit[\s\S]*?^\*\*\* End Commit)$" + pattern = r"(?m)^\*\*\* Begin Commit\n([\s\S]*?)^\*\*\* End Commit$" matches = re.findall(pattern, text) if not matches: return None - return matches if multiple else matches[0] + return matches if multiple else matches[0].strip() def parse_steps_markdown(md: str): steps = []