Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
33448dd
add web_search and logger_manager
Coco-XiangLi Aug 14, 2025
a436658
tools formatting
Coco-XiangLi Aug 16, 2025
37c2d05
fix
Coco-XiangLi Aug 16, 2025
2ad9e19
remove broken mcp
Coco-XiangLi Aug 16, 2025
76917b6
fix: tool node
Coco-XiangLi Aug 16, 2025
ca58c28
add log for web_search tool
Coco-XiangLi Aug 16, 2025
369436a
add web_search mcp
Coco-XiangLi Aug 26, 2025
3ab613d
Merge branch 'main' into mcp-fc
Coco-XiangLi Aug 27, 2025
21f3812
fix
Coco-XiangLi Aug 27, 2025
bcd2b82
adapt ’main‘
Coco-XiangLi Sep 1, 2025
ea16657
Merge branch 'dev' into mcp-fc
Coco-XiangLi Sep 2, 2025
16881b6
fix tools
Coco-XiangLi Sep 2, 2025
4cca9c0
Merge branch 'dev' into mcp-fc
Coco-XiangLi Sep 2, 2025
2730625
fix
Coco-XiangLi Sep 2, 2025
c1bf9a0
fix merge
Coco-XiangLi Sep 3, 2025
b7509ef
Merge branch 'main' into mcp-fc
dcloud347 Sep 4, 2025
a03e0c1
Merge remote-tracking branch 'origin/mcp-fc' into mcp-fc
dcloud347 Sep 4, 2025
03b87e6
refactor: Remove unused logging imports across multiple files
dcloud347 Sep 4, 2025
1aa0c89
feat: Add Tavily API key configuration to Docker Compose files and up…
dcloud347 Sep 4, 2025
4a840c0
refactor: Remove unused logger initialization in bug_fix_verification…
dcloud347 Sep 4, 2025
3f8c4a3
refactor: Correct spelling errors in file operation messages and upda…
dcloud347 Sep 4, 2025
f221867
fix log
Coco-XiangLi Sep 4, 2025
a3cbe57
Merge branch 'mcp-fc' of https://github.com/Pantheon-temple/Prometheu…
Coco-XiangLi Sep 4, 2025
ac107e1
refactor: Replace standard logging with custom logger manager in patc…
dcloud347 Sep 5, 2025
6f034c9
refactor: Update KnowledgeGraph initialization parameters and adjust …
dcloud347 Sep 5, 2025
fa2b6d3
refactor: Simplify Tavily client initialization and introduce custom …
dcloud347 Sep 5, 2025
3c6f031
refactor: Remove unused import from test_issue_bug_analyzer_node.py
dcloud347 Sep 5, 2025
bb5b07a
bump: Update project version to 1.2.0
dcloud347 Sep 5, 2025
0fb2228
refactor: Remove unused import from test_issue_bug_analyzer_node.py
dcloud347 Sep 5, 2025
f889be7
Merge remote-tracking branch 'origin/main' into mcp-fc
dcloud347 Sep 5, 2025
588b7b0
Merge remote-tracking branch 'origin/main' into mcp-fc
dcloud347 Sep 5, 2025
04edac4
fix log
Coco-XiangLi Sep 5, 2025
591f18a
fix: Remove unused threading imports across multiple files
dcloud347 Sep 5, 2025
6001f3e
Merge remote-tracking branch 'origin/main' into mcp-fc
dcloud347 Sep 6, 2025
f7e827b
fix log
Coco-XiangLi Sep 7, 2025
11326c3
fix
Coco-XiangLi Sep 7, 2025
6133f87
Merge branch 'main' into mcp-fc
dcloud347 Sep 7, 2025
06084ed
fix: Refactor logger_manager.py for improved readability and formatting
dcloud347 Sep 7, 2025
5ccdb66
fix: Clarify failure log descriptions in regression test structure
dcloud347 Sep 7, 2025
f9daf85
fix: Simplify logger initialization in get_pass_regression_test_patch…
dcloud347 Sep 7, 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
3 changes: 3 additions & 0 deletions .github/workflows/pytest_and_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ jobs:
# GitHub settings
PROMETHEUS_GITHUB_ACCESS_TOKEN: github_access_token

# Tavily API key
PROMETHEUS_TAVILY_API_KEY: tavily_api_key

# DATABASE settings
PROMETHEUS_DATABASE_URL: postgresql://postgres:password@localhost:5432/postgres?sslmode=disable

Expand Down
3 changes: 3 additions & 0 deletions docker-compose.win_mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ services:
- PROMETHEUS_BASE_MODEL_MAX_OUTPUT_TOKENS=${PROMETHEUS_BASE_MODEL_MAX_OUTPUT_TOKENS}
- PROMETHEUS_BASE_MODEL_TEMPERATURE=${PROMETHEUS_BASE_MODEL_TEMPERATURE}

# Tavily API key
- PROMETHEUS_TAVILY_API_KEY=${PROMETHEUS_TAVILY_API_KEY}

# Database settings
- PROMETHEUS_DATABASE_URL=${PROMETHEUS_DATABASE_URL}

Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ services:
- PROMETHEUS_BASE_MODEL_MAX_OUTPUT_TOKENS=${PROMETHEUS_BASE_MODEL_MAX_OUTPUT_TOKENS}
- PROMETHEUS_BASE_MODEL_TEMPERATURE=${PROMETHEUS_BASE_MODEL_TEMPERATURE}

# Tavily API key
- PROMETHEUS_TAVILY_API_KEY=${PROMETHEUS_TAVILY_API_KEY}

# Database settings
- PROMETHEUS_DATABASE_URL=${PROMETHEUS_DATABASE_URL}

Expand Down
3 changes: 3 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ PROMETHEUS_BASE_MODEL_MAX_INPUT_TOKENS=64000
PROMETHEUS_BASE_MODEL_TEMPERATURE=0.3
PROMETHEUS_BASE_MODEL_MAX_OUTPUT_TOKENS=15000

# Tavily API settings
PROMETHEUS_TAVILY_API_KEY=your_tavily_api_key

# Database settings
PROMETHEUS_DATABASE_URL=postgresql+asyncpg://postgres:password@postgres:5432/postgres

Expand Down
8 changes: 6 additions & 2 deletions prometheus/app/api/routes/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ async def list_repositories(request: Request):
response_model=Response,
)
@requireLogin
async def delete(repository_id: int, request: Request):
async def delete(
repository_id: int,
request: Request,
force: bool = False,
):
knowledge_graph_service: KnowledgeGraphService = request.app.state.service[
"knowledge_graph_service"
]
Expand All @@ -189,7 +193,7 @@ async def delete(repository_id: int, request: Request):
if not repository:
raise ServerException(code=404, message="Repository not found")
# Check if the repository is being processed
if repository.is_working:
if repository.is_working and not force:
raise ServerException(
code=400, message="Repository is currently being processed, please try again later"
)
Expand Down
24 changes: 3 additions & 21 deletions prometheus/app/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import inspect
import logging
from contextlib import asynccontextmanager
from datetime import datetime, timezone

Expand All @@ -16,27 +15,10 @@
register_login_required_routes,
)
from prometheus.configuration.config import settings
from prometheus.utils.logger_manager import get_thread_logger

# Create a logger for the application's namespace
logger = logging.getLogger("prometheus")
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.setLevel(getattr(logging, settings.LOGGING_LEVEL))
logger.propagate = False

# Log the configuration settings
logger.info(f"LOGGING_LEVEL={settings.LOGGING_LEVEL}")
logger.info(f"ENVIRONMENT={settings.ENVIRONMENT}")
logger.info(f"BACKEND_CORS_ORIGINS={settings.BACKEND_CORS_ORIGINS}")
logger.info(f"ADVANCED_MODEL={settings.ADVANCED_MODEL}")
logger.info(f"BASE_MODEL={settings.BASE_MODEL}")
logger.info(f"NEO4J_BATCH_SIZE={settings.NEO4J_BATCH_SIZE}")
logger.info(f"WORKING_DIRECTORY={settings.WORKING_DIRECTORY}")
logger.info(f"KNOWLEDGE_GRAPH_MAX_AST_DEPTH={settings.KNOWLEDGE_GRAPH_MAX_AST_DEPTH}")
logger.info(f"KNOWLEDGE_GRAPH_CHUNK_SIZE={settings.KNOWLEDGE_GRAPH_CHUNK_SIZE}")
logger.info(f"KNOWLEDGE_GRAPH_CHUNK_OVERLAP={settings.KNOWLEDGE_GRAPH_CHUNK_OVERLAP}")
# Create main thread logger with file handler - ONE LINE!
logger, file_handler = get_thread_logger(__name__)


@asynccontextmanager
Expand Down
5 changes: 2 additions & 3 deletions prometheus/app/services/database_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import logging

from sqlalchemy.ext.asyncio import create_async_engine
from sqlmodel import SQLModel

from prometheus.app.services.base_service import BaseService
from prometheus.utils.logger_manager import get_thread_logger


class DatabaseService(BaseService):
def __init__(self, DATABASE_URL: str):
self.engine = create_async_engine(DATABASE_URL, echo=True)
self._logger = logging.getLogger("prometheus.app.services.database_service")
self._logger, file_handler = get_thread_logger(__name__)

# Create the database and tables
async def create_db_and_tables(self):
Expand Down
4 changes: 2 additions & 2 deletions prometheus/app/services/invitation_code_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import datetime
import logging
import uuid
from typing import Sequence

Expand All @@ -9,13 +8,14 @@
from prometheus.app.entity.invitation_code import InvitationCode
from prometheus.app.services.base_service import BaseService
from prometheus.app.services.database_service import DatabaseService
from prometheus.utils.logger_manager import get_thread_logger


class InvitationCodeService(BaseService):
def __init__(self, database_service: DatabaseService):
self.database_service = database_service
self.engine = database_service.engine
self._logger = logging.getLogger("prometheus.app.services.invitation_code_service")
self._logger, file_handler = get_thread_logger(__name__)

async def create_invitation_code(self) -> InvitationCode:
"""
Expand Down
19 changes: 5 additions & 14 deletions prometheus/app/services/issue_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import logging
import threading
import traceback
from datetime import datetime
from pathlib import Path
from typing import Mapping, Optional, Sequence

Expand All @@ -13,6 +10,7 @@
from prometheus.graph.knowledge_graph import KnowledgeGraph
from prometheus.lang_graph.graphs.issue_graph import IssueGraph
from prometheus.lang_graph.graphs.issue_state import IssueType
from prometheus.utils.logger_manager import get_thread_logger, remove_multi_threads_log_file_handler


class IssueService(BaseService):
Expand Down Expand Up @@ -79,15 +77,8 @@ def answer_issue(
- issue_type (IssueType): The type of the issue (BUG or QUESTION).
"""

# Set up a dedicated logger for this thread
logger = logging.getLogger(f"thread-{threading.get_ident()}.prometheus")
logger.setLevel(getattr(logging, self.logging_level))
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
log_file = self.answer_issue_log_dir / f"{timestamp}_{threading.get_ident()}.log"
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Create thread-specific logger with file handler - ONE LINE!
logger, file_handler = get_thread_logger(__name__, force_new_file=True)

# Construct the working directory
if dockerfile_content or image_name:
Expand Down Expand Up @@ -141,5 +132,5 @@ def answer_issue(
logger.error(f"Error in answer_issue: {str(e)}\n{traceback.format_exc()}")
return None, False, False, False, None, None
finally:
logger.removeHandler(file_handler)
file_handler.close()
# Remove multi-thread file handler
remove_multi_threads_log_file_handler(file_handler, logger.name)
4 changes: 2 additions & 2 deletions prometheus/app/services/knowledge_graph_service.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""Service for managing and interacting with Knowledge Graphs in Neo4j."""

import asyncio
import logging
from pathlib import Path

from prometheus.app.services.base_service import BaseService
from prometheus.app.services.neo4j_service import Neo4jService
from prometheus.graph.knowledge_graph import KnowledgeGraph
from prometheus.neo4j import knowledge_graph_handler
from prometheus.utils.logger_manager import get_thread_logger


class KnowledgeGraphService(BaseService):
Expand Down Expand Up @@ -42,7 +42,7 @@ def __init__(
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
self.writing_lock = asyncio.Lock()
self._logger = logging.getLogger("prometheus.app.services.knowledge_graph_service")
self._logger, file_handler = get_thread_logger(__name__)

async def start(self):
# Initialize the Neo4j database for Knowledge Graph operations
Expand Down
5 changes: 2 additions & 3 deletions prometheus/app/services/neo4j_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"""Service for managing Neo4j database driver."""

import logging

from neo4j import AsyncGraphDatabase

from prometheus.app.services.base_service import BaseService
from prometheus.utils.logger_manager import get_thread_logger


class Neo4jService(BaseService):
def __init__(self, neo4j_uri: str, neo4j_username: str, neo4j_password: str):
self._logger = logging.getLogger("prometheus.app.services.neo4j_service")
self._logger, file_handler = get_thread_logger(__name__)
self.neo4j_driver = AsyncGraphDatabase.driver(
neo4j_uri,
auth=(neo4j_username, neo4j_password),
Expand Down
4 changes: 2 additions & 2 deletions prometheus/app/services/user_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
from typing import Optional, Sequence

from argon2 import PasswordHasher
Expand All @@ -11,13 +10,14 @@
from prometheus.app.services.database_service import DatabaseService
from prometheus.exceptions.server_exception import ServerException
from prometheus.utils.jwt_utils import JWTUtils
from prometheus.utils.logger_manager import get_thread_logger


class UserService(BaseService):
def __init__(self, database_service: DatabaseService):
self.database_service = database_service
self.engine = database_service.engine
self._logger = logging.getLogger("prometheus.app.services.user_service")
self._logger, file_handler = get_thread_logger(__name__)
self.ph = PasswordHasher()
self.jwt_utils = JWTUtils()

Expand Down
3 changes: 3 additions & 0 deletions prometheus/configuration/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,8 @@ class Settings(BaseSettings):
# Default normal user repository number
DEFAULT_USER_REPOSITORY_LIMIT: int = 5

# tool for Websearch
TAVILY_API_KEY: str


settings = Settings()
7 changes: 3 additions & 4 deletions prometheus/docker/base_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import shutil
import tarfile
import tempfile
import threading
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Optional, Sequence

import docker

from prometheus.utils.logger_manager import get_thread_logger


class BaseContainer(ABC):
"""An abstract base class for managing Docker containers with file synchronization capabilities.
Expand Down Expand Up @@ -41,9 +42,7 @@ def __init__(
Args:
project_path: Path to the project directory to be containerized.
"""
self._logger = logging.getLogger(
f"thread-{threading.get_ident()}.{self.__class__.__module__}.{self.__class__.__name__}"
)
self._logger, file_handler = get_thread_logger(__name__)
temp_dir = Path(tempfile.mkdtemp())
temp_project_path = temp_dir / project_path.name
shutil.copytree(project_path, temp_project_path)
Expand Down
4 changes: 4 additions & 0 deletions prometheus/exceptions/web_search_tool_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class WebSearchToolException(Exception):
"""Custom exception for web search tool errors."""

pass
7 changes: 4 additions & 3 deletions prometheus/git/git_repository.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Git repository management module."""

import asyncio
import logging
import shutil
import tempfile
from pathlib import Path
from typing import Optional, Sequence

from git import Git, GitCommandError, InvalidGitRepositoryError, Repo

from prometheus.utils.logger_manager import get_thread_logger


class GitRepository:
"""A class for managing Git repositories with support for both local and remote operations.
Expand All @@ -23,12 +24,12 @@ def __init__(self):
"""
Initialize a GitRepository instance.
"""
self._logger = logging.getLogger("prometheus.git.git_repository")
self._logger, file_handler = get_thread_logger(__name__)

# Configure git command to use our logger
g = Git()
type(g).GIT_PYTHON_TRACE = "full"
git_cmd_logger = logging.getLogger("git.cmd")
git_cmd_logger, file_handler = get_thread_logger("git.cmd")

# Ensure git command output goes to our logger
for handler in git_cmd_logger.handlers:
Expand Down
4 changes: 2 additions & 2 deletions prometheus/graph/knowledge_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import asyncio
import itertools
import logging
from collections import defaultdict, deque
from pathlib import Path
from typing import Mapping, Optional, Sequence
Expand All @@ -43,6 +42,7 @@
Neo4jTextNode,
TextNode,
)
from prometheus.utils.logger_manager import get_thread_logger


class KnowledgeGraph:
Expand Down Expand Up @@ -79,7 +79,7 @@ def __init__(
self._next_node_id = root_node_id + len(self._knowledge_graph_nodes)

self._file_graph_builder = FileGraphBuilder(max_ast_depth, chunk_size, chunk_overlap)
self._logger = logging.getLogger("prometheus.graph.knowledge_graph")
self._logger, file_handler = get_thread_logger(__name__)

async def build_graph(self, root_dir: Path):
"""Asynchronously builds knowledge graph for a codebase at a location.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import logging
import threading

from langchain_core.language_models.chat_models import BaseChatModel
from langgraph.errors import GraphRecursionError

from prometheus.docker.base_container import BaseContainer
from prometheus.git.git_repository import GitRepository
from prometheus.lang_graph.subgraphs.bug_fix_verification_subgraph import BugFixVerificationSubgraph
from prometheus.lang_graph.subgraphs.issue_verified_bug_state import IssueVerifiedBugState
from prometheus.utils.logger_manager import get_thread_logger


class BugFixVerificationSubgraphNode:
Expand All @@ -17,9 +15,7 @@ def __init__(
container: BaseContainer,
git_repo: GitRepository,
):
self._logger = logging.getLogger(
f"thread-{threading.get_ident()}.prometheus.lang_graph.nodes.bug_fix_verification_subgraph_node"
)
self._logger, file_handler = get_thread_logger(__name__)
self.git_repo = git_repo
self.subgraph = BugFixVerificationSubgraph(
model=model,
Expand Down
Loading