Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
ead7a4f
Add server module and update requirements for FastMCP
BrunoV21 Jun 29, 2025
e39f18a
Add utility functions for workspace retrieval and safe printing
BrunoV21 Jun 29, 2025
df6571a
Refactor get method in CodeTide to enhance parameter naming and impro…
BrunoV21 Jun 29, 2025
9dec4f0
Initialize __init__.py with server and tools imports, and define __al…
BrunoV21 Jun 29, 2025
464afdf
Add getRepoTree function and update public API in __init__.py
BrunoV21 Jun 29, 2025
b9447c2
Add example script for CodeTide MCP server integration
BrunoV21 Jun 29, 2025
d48a49d
Enhance getContext docstring with detailed argument descriptions and …
BrunoV21 Jun 29, 2025
7b450a5
Update getRepoTree function to require show_contents parameter
BrunoV21 Jun 29, 2025
1a4d334
Refactor CodeBase class to inherit from BaseModel instead of RootModel
BrunoV21 Jun 29, 2025
28359c9
Refactor resolve_intra_file_dependencies method to include CodeBase p…
BrunoV21 Jun 29, 2025
932233a
Remove unnecessary await from tide.get call in getContext function
BrunoV21 Jun 29, 2025
044cd2e
Add initial implementation of agent_tide example with LLM integration
BrunoV21 Jun 29, 2025
84000c3
Update return type of getContext function to str and enhance error me…
BrunoV21 Jun 29, 2025
1d97a3e
Improve logging in CodeBase class by conditionally logging retrieved …
BrunoV21 Jun 30, 2025
7fa0b15
Replace json with orjson for improved performance in serialization an…
BrunoV21 Jun 30, 2025
dc244ea
Enhance AutoComplete class with type hints and add validate_code_iden…
BrunoV21 Jun 30, 2025
926b058
Add cached_ids property to CodeTide and update serialization methods …
BrunoV21 Jun 30, 2025
16aab9a
Add checkCodeIdentifiers function for validating code identifiers and…
BrunoV21 Jun 30, 2025
c21d038
Refactor getContext docstring for clarity and conciseness in paramete…
BrunoV21 Jun 30, 2025
401a218
Refactor agent_tide.py to improve structure and readability; separate…
BrunoV21 Jun 30, 2025
44ae566
Add ASCII art headers to CodeTide and AgentTide for enhanced visual a…
BrunoV21 Jun 30, 2025
205cf8a
Implement patch application utility and related parsing functionality
BrunoV21 Jul 1, 2025
cc8f721
Add applyPatch to exports in __init__.py for tools and mcp modules
BrunoV21 Jul 1, 2025
4adfe93
Refactor getContext function to enforce list type for code_identifier…
BrunoV21 Jul 2, 2025
f78806a
Refactor patch handling: consolidate patch processing logic into new …
BrunoV21 Jul 2, 2025
7787fe8
Add comprehensive tests for patch application functionality in MockFi…
BrunoV21 Jul 2, 2025
4fe6d8a
Add MCP server support to README, detailing integration with AI agent…
BrunoV21 Jul 2, 2025
4cdf75f
Update resolve_intra_file_dependencies method to accept Optional list…
BrunoV21 Jul 2, 2025
2a36fa7
Add initial implementation of Agent Tide system prompt for CLI-based …
BrunoV21 Jul 2, 2025
47a4ea5
Replace MCP_USE_INSTRUCTIONS with AGENT_TIDE_SYSTEM_PROMPT in FastMCP…
BrunoV21 Jul 2, 2025
f53b2ea
Enhance agent_tide.py to include keyboard input handling for graceful…
BrunoV21 Jul 3, 2025
ceea48f
Refactor find_context and peek_next_section for improved handling of …
BrunoV21 Jul 4, 2025
659f43a
Add tests for peek_next_section functionality in apply_patch.py
BrunoV21 Jul 4, 2025
fcaba2b
Enhance applyPatch function documentation with detailed patch format …
BrunoV21 Jul 4, 2025
3b670f4
Refactor applyPatch function to improve patch handling; remove unnece…
BrunoV21 Jul 4, 2025
42a88f3
feat: updated agent tide prompt
BrunoV21 Jul 4, 2025
6a0ce05
feat: implement async prompt handling and key bindings for exit funct…
BrunoV21 Jul 4, 2025
c3aa419
fix: correct formatting of context_depth descriptions in getContext f…
BrunoV21 Jul 4, 2025
0dcbab9
refactor: rename getContext to getCodeContext and update imports; rem…
BrunoV21 Jul 4, 2025
3deaaf8
feat: add agent tide main functionality with async prompt handling an…
BrunoV21 Jul 7, 2025
14be4f6
refactor: remove unused agent tide components and related utility fun…
BrunoV21 Jul 18, 2025
fec0f59
refactor: update documentation and usage guidelines for code context …
BrunoV21 Jul 18, 2025
c8b5e6e
fix: remove unnecessary print statement in Parser class to clean up o…
BrunoV21 Jul 18, 2025
21fcca3
feat: add ASCII art and system prompts for Agent Tide to enhance user…
BrunoV21 Jul 18, 2025
0f0f5f3
feat: implement AgentTide class with async handling and utility funct…
BrunoV21 Jul 18, 2025
d58edca
feat: enhance TypeScriptParser to handle intra-file dependencies and …
BrunoV21 Jul 18, 2025
f5f55c5
feat: update intra-file dependency resolution to utilize CodeBase for…
BrunoV21 Jul 18, 2025
3493a93
feat: add comprehensive tests for TypeScriptParser including edge cas…
BrunoV21 Jul 18, 2025
7c3185c
refactor: remove debug print statements from TestTypeScriptParser
BrunoV21 Jul 18, 2025
bbf18e8
feat: add replace_newline_in_quotes function to handle newlines in qu…
BrunoV21 Jul 18, 2025
fd8ee35
feat: add requirements-agents.txt and update setup.py to include agen…
BrunoV21 Jul 18, 2025
6f09f64
feat: refactor parse_xml_content to parse_patch_blocks for improved p…
BrunoV21 Jul 18, 2025
fa701f9
refactor: enhance patch generation guidelines for clarity and precision
BrunoV21 Jul 18, 2025
263d372
refactor: replace parse_xml_content with parse_patch_blocks for impro…
BrunoV21 Jul 18, 2025
dee4bb4
test: add unit tests for parse_patch_blocks function
BrunoV21 Jul 18, 2025
24c3ccf
feat: introduce AgentTide module for enhanced code context and patch …
BrunoV21 Jul 18, 2025
87e418f
test: add comprehensive unit tests for parse_patch_blocks function
BrunoV21 Jul 18, 2025
32a8e11
feat: add agent testing to CI workflow and configure pytest to ignore…
BrunoV21 Jul 18, 2025
5620a10
fix: ensure newline at end of requirements.txt for proper formatting
BrunoV21 Jul 18, 2025
f03c8c4
fix: update core-for-ai version in requirements-agents.txt to >=0.1.97
BrunoV21 Jul 18, 2025
102c3c0
fix: update setup.py to include author details and project URL
BrunoV21 Jul 18, 2025
8375a7c
fix: update pytest command to ignore agents tests and remove pytest.i…
BrunoV21 Jul 18, 2025
0eee810
fix: enhance docstring detection to ensure minimum length
BrunoV21 Jul 19, 2025
4c8d3dd
test: add comprehensive tests for docstring detection and parsing
BrunoV21 Jul 19, 2025
99ccf74
feat: add support for processing export statements and enhance functi…
BrunoV21 Jul 19, 2025
772a6f4
refactor: comment out unused server imports and enhance code context …
BrunoV21 Jul 19, 2025
9c7f69d
feat: enhance import processing to support multiple names and aliases…
BrunoV21 Jul 19, 2025
cb5bb02
feat: enhance code identifier validation and improve prompt instructi…
BrunoV21 Jul 19, 2025
fb6a02d
feat: add comprehensive tests for TypeScriptParser handling of decora…
BrunoV21 Jul 19, 2025
d5e479f
feat: enhance patch processing to handle specific line prefixes in te…
BrunoV21 Jul 19, 2025
152051f
feat: add support for processing interface declarations and enhance c…
BrunoV21 Jul 19, 2025
39fe2a2
feat: add tests for TypeScriptParser handling of interfaces, methods,…
BrunoV21 Jul 19, 2025
29512a0
fix: correct parameter reference in interface declaration processing
BrunoV21 Jul 19, 2025
81b46dc
feat: implement processing for interface and type alias declarations …
BrunoV21 Jul 19, 2025
2f70b9d
feat: add tests for type aliases and interface extensions in TypeScri…
BrunoV21 Jul 19, 2025
050d319
feat: enhance newline replacement to exclude triple-quoted strings in…
BrunoV21 Jul 19, 2025
ffa7049
feat: add comprehensive test suite for replace_newline_in_quotes func…
BrunoV21 Jul 19, 2025
394c107
fix: refine line handling in text_to_patch to correctly process speci…
BrunoV21 Jul 19, 2025
4b51985
feat: enhance identifier resolution prompt to prioritize code identif…
BrunoV21 Jul 19, 2025
de0bb10
updated requirements-agents
BrunoV21 Jul 19, 2025
3bf9e9d
.
BrunoV21 Jul 19, 2025
e535b0c
updated agents reqs
BrunoV21 Jul 19, 2025
5f76457
updated server with serve and serve async methods
BrunoV21 Jul 20, 2025
2fd66e1
added codetide-mcp-server entry point
BrunoV21 Jul 20, 2025
9acff45
added pyproject.toml and uv.lock
BrunoV21 Jul 20, 2025
3d84d24
updated README
BrunoV21 Jul 20, 2025
0620ef2
added mcp server instructions
BrunoV21 Jul 20, 2025
c25260d
version bump to 0.0.22
BrunoV21 Jul 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/python_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ jobs:
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: pytest tests/
run: pytest tests --ignore=tests/agents
- name: Install package with agents requirements
run: |
python -m pip install .[agents]
- name: Test agents with pytest
run: pytest tests/agents
security:
name: Security Check
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,5 @@ cython_debug/

storage/
logs/
observability_data/

96 changes: 93 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,48 @@ CodeTide is available as a native [**Visual Studio Code extension**](https://mar

---

## 🖧 CodeTide as an MCP Server

CodeTide now supports acting as an **MCP Server**, enabling seamless integration with AI agents and tools. This feature allows agents to dynamically interact with your codebase and retrieve context efficiently.

#### Why This Helps Agents
Agents working with codebases often need:
- **Contextual Understanding**: Retrieve declarations, imports, and references for any part of the code.
- **Tool Integration**: Use built-in tools to navigate and analyze code.

#### Available Tools
CodeTide provides the following tools for agents:
1. **`getContext`**: Retrieve code context for identifiers (e.g., functions, classes).
2. **`getRepoTree`**: Explore the repository structure.

#### Example: Initializing an LLM with CodeTide
Here’s a snippet from `agent_tide.py` demonstrating how to initialize an LLM with CodeTide as an MCP server:

```python
from aicore.llm import Llm, LlmConfig
from codetide.mcp import codeTideMCPServer
import os

def init_llm() -> Llm:
llm = Llm.from_config(
LlmConfig(
model="deepseek-chat",
provider="deepseek",
temperature=0,
api_key=os.getenv("DEEPSEEK-API-KEY")
)
)
llm.provider.mcp.add_server(name=codeTideMCPServer.name, parameters=codeTideMCPServer)
return llm
```

This setup allows the LLM to leverage CodeTide’s tools for codebase interactions.

CodeTide can now be used as an MCP (Multi-Code Processor) Server! This allows seamless integration with AI tools and workflows. Below are the tools available:
The available tools are:
- **getContext**: Retrieve code context for identifiers.
- **getRepoTree**: Generate a visual tree representation of the repository.

## ⚙️ Installation

### 📦 From PyPI
Expand Down Expand Up @@ -399,9 +441,57 @@ Here’s what’s next for CodeTide:

~~- 🧭 **Handle relative imports** in Python projects
→ Improve resolution for intra-package navigation.~~
- 🤖 **Long-term vision**: Release a native **CodeTide Agent**
→ Seamless, intelligent context resolution directly integrated into the CodeTide core.
→ Unlock **clinical issue detection**, **guided refactors**, and **agent-level navigation**.

---

## 🤖 Agents Module: AgentTide

CodeTide now includes an `agents` module, featuring **AgentTide**—a precision-driven software engineering agent that connects directly to your codebase and executes your requests with full code context.

**AgentTide** leverages CodeTide’s symbolic code understanding to:
- Retrieve and reason about relevant code context for any request
- Generate atomic, high-precision patches using strict protocols
- Apply changes directly to your codebase, with robust validation

### Where to Find It
- Source: [`codetide/agents/tide/agent.py`](codetide/agents/tide/agent.py)

### What It Does
AgentTide acts as an autonomous agent that:
- Connects to your codebase using CodeTide’s parsing and context tools
- Interacts with users via a conversational interface
- Identifies relevant files, classes, and functions for any request
- Generates and applies diff-style patches, ensuring code quality and requirements fidelity

### Example Usage
To use AgentTide, ensure you have the `aicore` package installed (`pip install codetide[agents]`), then instantiate and run the agent:

```python
from codetide import CodeTide
from codetide.agents.tide.agent import AgentTide
from aicore.llm import Llm, LlmConfig
import os, asyncio

async def main():
tide = await CodeTide.from_path("/path/to/your/repo")
llm = Llm.from_config(
LlmConfig(
model="deepseek-chat",
provider="deepseek",
temperature=0,
api_key=os.getenv("DEEPSEEK-API-KEY")
)
)
agent = AgentTide(llm=llm, tide=tide)
await agent.run()

if __name__ == "__main__":
asyncio.run(main())
```

AgentTide will prompt you for requests, retrieve the relevant code context, and generate precise patches to fulfill your requirements.

For more details, see the [agents module source code](codetide/agents/tide/agent.py).

---

Expand Down
67 changes: 41 additions & 26 deletions codetide/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from codetide.core.defaults import (
DEFAULT_SERIALIZATION_PATH, DEFAULT_MAX_CONCURRENT_TASKS,
CODETIDE_ASCII_ART, DEFAULT_SERIALIZATION_PATH, DEFAULT_MAX_CONCURRENT_TASKS,
DEFAULT_BATCH_SIZE, DEFAULT_CACHED_ELEMENTS_FILE, DEFAULT_CACHED_IDS_FILE,
LANGUAGE_EXTENSIONS
)
Expand All @@ -17,7 +17,7 @@
import asyncio
import pygit2
import time
import json
import orjson
import os

class CodeTide(BaseModel):
Expand Down Expand Up @@ -80,7 +80,7 @@ async def from_path(

codeTide._add_results_to_codebase(results)
codeTide._resolve_files_dependencies()
logger.info(f"CodeTide initialized with {len(results)} files processed in {time.time() - st:.2f}s")
logger.info(f"\n{CODETIDE_ASCII_ART}\nInitialized with {len(results)} files processed in {time.time() - st:.2f}s")

return codeTide

Expand All @@ -90,6 +90,10 @@ def relative_filepaths(self)->List[str]:
str(filepath.relative_to(self.rootpath)).replace("\\", "/") for filepath in self.files
]

@property
def cached_ids(self)->List[str]:
return self.codebase.unique_ids+self.relative_filepaths

async def _reset(self):
self = await self.from_path(self.rootpath)

Expand Down Expand Up @@ -138,7 +142,7 @@ def serialize(self,

if include_cached_ids:
cached_ids_path = dir_path / DEFAULT_CACHED_IDS_FILE
writeFile(json.dumps(self.codebase.unique_ids+self.relative_filepaths, indent=4), cached_ids_path)
writeFile(str(orjson.dumps(self.cached_ids, option=orjson.OPT_INDENT_2)), cached_ids_path)

@classmethod
def deserialize(cls, filepath :Optional[Union[str, Path]]=DEFAULT_SERIALIZATION_PATH, rootpath :Optional[Union[str, Path]] = None)->"CodeTide":
Expand All @@ -158,7 +162,7 @@ def deserialize(cls, filepath :Optional[Union[str, Path]]=DEFAULT_SERIALIZATION_
if not os.path.exists(filepath):
raise FileNotFoundError(f"{filepath} is not a valid path")

kwargs = json.loads(readFile(filepath))
kwargs = orjson.loads(readFile(filepath))
tideInstance = cls(**kwargs)

# dir_path = Path(os.path.split(filepath))[0]
Expand Down Expand Up @@ -458,7 +462,7 @@ async def check_for_updates(self,
if self.rootpath / newFile.file_path in filepaths
]
parser.resolve_inter_files_dependencies(self.codebase, filteredNewFiles)
parser.resolve_intra_file_dependencies(filteredNewFiles)
parser.resolve_intra_file_dependencies(self.codebase, filteredNewFiles)

for codeFile in filteredNewFiles:
i = changedPaths.get(codeFile.file_path)
Expand All @@ -485,36 +489,47 @@ def _precheck_id_is_file(self, unique_ids : List[str])->Dict[Path, str]:
if self.rootpath / unique_id in self.files
}

def get(self, unique_id :Union[str, List[str]], degree :int=1, slim :bool=False, as_string :bool=True, as_list_str :bool=False)->Union[CodeContextStructure, str, List[str]]:
def get(
self,
code_identifiers: Union[str, List[str]],
context_depth: int = 1,
concise_mode: bool = False,
as_string: bool = True,
as_string_list: bool = False
) -> Union[CodeContextStructure, str, List[str]]:
"""
Retrieve context around code by unique ID(s).
Retrieves code context for given identifiers with flexible return formats.
Returns None if no matching identifiers are found.

Args:
unique_id: Single or list of unique IDs for code entities.
degree: Depth of context to fetch.
as_string: Whether to return as a single string.
as_list_str: Whether to return as list of strings.
code_identifiers: One or more code element IDs or file paths to analyze.
Examples: 'package.ClassName', 'dir/module.py:function', ['file.py', 'module.var']
context_depth: Number of reference levels to include (1=direct references only)
concise_mode: If True, returns minimal docstrings instead of full code (slim=True)
as_string: Return as single formatted string (default)
as_string_list: Return as list of strings (overrides as_string if True)

Returns:
Code context in the requested format.
- CodeContextStructure if both format flags are False
- Single concatenated string if as_string=True
- List of context strings if as_string_list=True
- None if no matching identifiers exist
"""
if isinstance(unique_id, str):
unique_id = [unique_id]
if isinstance(code_identifiers, str):
code_identifiers = [code_identifiers]

# Log the incoming request
logger.info(
f"Getting code context - IDs: {unique_id}, "
f"degree: {degree}, "
f"as_string: {as_string}, "
f"as_list_str: {as_list_str}"
f"Context request - IDs: {code_identifiers}, "
f"Depth: {context_depth}, "
f"Formats: string={as_string}, list={as_string_list}"
)

requestedFiles = self._precheck_id_is_file(unique_id)
requested_files = self._precheck_id_is_file(code_identifiers)
return self.codebase.get(
unique_id=unique_id,
degree=degree,
slim=slim,
unique_id=code_identifiers,
degree=context_depth,
slim=concise_mode,
as_string=as_string,
as_list_str=as_list_str,
preloaded_files=requestedFiles
as_list_str=as_string_list,
preloaded_files=requested_files
)
5 changes: 5 additions & 0 deletions codetide/agents/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .tide import AgentTide

__all__ = [
"AgentTide"
]
5 changes: 5 additions & 0 deletions codetide/agents/tide/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .agent import AgentTide

__all__ = [
"AgentTide"
]
Loading