Skip to content

Commit 9c2f5bb

Browse files
author
dori
committed
feat: refactor ai code
1 parent f65f622 commit 9c2f5bb

File tree

7 files changed

+117
-92
lines changed

7 files changed

+117
-92
lines changed

src/mcp_as_a_judge/constants.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@
1515
DATABASE_URL = "sqlite://:memory:"
1616
MAX_SESSION_RECORDS = 20 # Maximum records to keep per session (FIFO)
1717
MAX_TOTAL_SESSIONS = 50 # Maximum total sessions to keep (LRU cleanup)
18-
MAX_CONTEXT_TOKENS = 50000 # Maximum tokens for conversation history context (1 token ≈ 4 characters)
19-
18+
MAX_CONTEXT_TOKENS = 50000 # Maximum tokens for session token (1 token ≈ 4 characters)

src/mcp_as_a_judge/db/conversation_history_service.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
create_database_provider,
1414
)
1515
from mcp_as_a_judge.db.db_config import Config
16-
from mcp_as_a_judge.logging_config import get_logger
1716
from mcp_as_a_judge.db.token_utils import filter_records_by_token_limit
17+
from mcp_as_a_judge.logging_config import get_logger
1818

1919
# Set up logger
2020
logger = get_logger(__name__)
@@ -36,7 +36,9 @@ def __init__(
3636
self.config = config
3737
self.db = db_provider or create_database_provider(config)
3838

39-
async def load_context_for_enrichment(self, session_id: str, current_prompt: str = "") -> list[ConversationRecord]:
39+
async def load_filtered_context_for_enrichment(
40+
self, session_id: str, current_prompt: str = ""
41+
) -> list[ConversationRecord]:
4042
"""
4143
Load recent conversation records for LLM context enrichment.
4244
@@ -61,7 +63,9 @@ async def load_context_for_enrichment(self, session_id: str, current_prompt: str
6163

6264
# Apply LLM context filtering: ensure history + current prompt will fit within token limit
6365
# This filters the list without modifying the database (only token limit matters for LLM)
64-
filtered_records = filter_records_by_token_limit(recent_records, current_prompt=current_prompt)
66+
filtered_records = filter_records_by_token_limit(
67+
recent_records, current_prompt=current_prompt
68+
)
6569

6670
logger.info(
6771
f"✅ Returning {len(filtered_records)} conversation records for LLM context"
@@ -102,23 +106,9 @@ async def save_tool_interaction_and_cleanup(
102106
logger.info(f"✅ Saved conversation record with ID: {record_id}")
103107
return record_id
104108

105-
async def save_tool_interaction(
106-
self, session_id: str, tool_name: str, tool_input: str, tool_output: str
107-
) -> str:
108-
"""
109-
Save a tool interaction as a conversation record.
110-
111-
DEPRECATED: Use save_tool_interaction_and_cleanup() instead.
112-
This method is kept for backward compatibility.
113-
"""
114-
logger.warning(
115-
"save_tool_interaction() is deprecated. Use save_tool_interaction_and_cleanup() instead."
116-
)
117-
return await self.save_tool_interaction_and_cleanup(
118-
session_id, tool_name, tool_input, tool_output
119-
)
120-
121-
def format_conversation_history_as_json_array( self, conversation_history: list[ConversationRecord]) -> list[dict]:
109+
def format_conversation_history_as_json_array(
110+
self, conversation_history: list[ConversationRecord]
111+
) -> list[dict]:
122112
"""
123113
Convert conversation history list to JSON array for prompt injection.
124114

src/mcp_as_a_judge/db/providers/sqlite_provider.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
from datetime import UTC, datetime
1010

1111
from sqlalchemy import create_engine
12-
from sqlmodel import Session, SQLModel, asc, desc, select
12+
from sqlmodel import Session, SQLModel, desc, select
1313

1414
from mcp_as_a_judge.constants import MAX_CONTEXT_TOKENS
1515
from mcp_as_a_judge.db.cleanup_service import ConversationCleanupService
1616
from mcp_as_a_judge.db.interface import ConversationHistoryDB, ConversationRecord
17-
from mcp_as_a_judge.logging_config import get_logger
1817
from mcp_as_a_judge.db.token_utils import calculate_record_tokens
18+
from mcp_as_a_judge.logging_config import get_logger
1919

2020
# Set up logger
2121
logger = get_logger(__name__)
@@ -107,9 +107,11 @@ def _cleanup_old_messages(self, session_id: str) -> int:
107107
"""
108108
with Session(self.engine) as session:
109109
# Get current records ordered by timestamp DESC (newest first for token calculation)
110-
count_stmt = select(ConversationRecord).where(
111-
ConversationRecord.session_id == session_id
112-
).order_by(desc(ConversationRecord.timestamp))
110+
count_stmt = (
111+
select(ConversationRecord)
112+
.where(ConversationRecord.session_id == session_id)
113+
.order_by(desc(ConversationRecord.timestamp))
114+
)
113115
current_records = session.exec(count_stmt).all()
114116
current_count = len(current_records)
115117

src/mcp_as_a_judge/db/token_utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
from mcp_as_a_judge.constants import MAX_CONTEXT_TOKENS
99

10-
from mcp_as_a_judge.db.interface import ConversationRecord
11-
1210

1311
def calculate_tokens(text: str) -> int:
1412
"""
@@ -60,9 +58,7 @@ def calculate_total_tokens(records: list) -> int:
6058
return sum(record.tokens for record in records if hasattr(record, "tokens"))
6159

6260

63-
def filter_records_by_token_limit(
64-
records: list, current_prompt: str = ""
65-
) -> list:
61+
def filter_records_by_token_limit(records: list, current_prompt: str = "") -> list:
6662
"""
6763
Filter conversation records to stay within token and record limits.
6864
@@ -81,7 +77,9 @@ def filter_records_by_token_limit(
8177
return []
8278

8379
# Calculate current prompt tokens
84-
current_prompt_tokens = calculate_record_tokens(current_prompt, "") if current_prompt else 0
80+
current_prompt_tokens = (
81+
calculate_record_tokens(current_prompt, "") if current_prompt else 0
82+
)
8583

8684
# Calculate total tokens including current prompt
8785
history_tokens = calculate_total_tokens(records)
@@ -96,7 +94,9 @@ def filter_records_by_token_limit(
9694
filtered_records = records.copy()
9795
current_history_tokens = history_tokens
9896

99-
while (current_history_tokens + current_prompt_tokens) > MAX_CONTEXT_TOKENS and len(filtered_records) > 1:
97+
while (current_history_tokens + current_prompt_tokens) > MAX_CONTEXT_TOKENS and len(
98+
filtered_records
99+
) > 1:
100100
# Remove the oldest record (last in the list)
101101
removed_record = filtered_records.pop()
102102
current_history_tokens -= getattr(removed_record, "tokens", 0)

src/mcp_as_a_judge/server.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from mcp.server.fastmcp import Context, FastMCP
1313
from pydantic import ValidationError
1414

15+
from mcp_as_a_judge.constants import MAX_CONTEXT_TOKENS
1516
from mcp_as_a_judge.db.conversation_history_service import ConversationHistoryService
1617
from mcp_as_a_judge.db.db_config import load_config
1718
from mcp_as_a_judge.elicitation_provider import elicitation_provider
@@ -48,8 +49,6 @@
4849
tool_description_provider,
4950
)
5051

51-
from src.mcp_as_a_judge.constants import MAX_CONTEXT_TOKENS
52-
5352
# Initialize centralized logging
5453
setup_logging()
5554

@@ -90,9 +89,16 @@ async def build_workflow(
9089

9190
try:
9291
# STEP 1: Load conversation history and format as JSON array
93-
conversation_history = await conversation_service.load_filtered_context_for_enrichment(session_id, json.dumps(original_input))
94-
history_json_array = conversation_service.format_conversation_history_as_json_array(conversation_history)
95-
92+
conversation_history = (
93+
await conversation_service.load_filtered_context_for_enrichment(
94+
session_id, json.dumps(original_input)
95+
)
96+
)
97+
history_json_array = (
98+
conversation_service.format_conversation_history_as_json_array(
99+
conversation_history
100+
)
101+
)
96102

97103
# STEP 2: Create system and user messages with separate context and conversation history
98104
system_vars = WorkflowGuidanceSystemVars(
@@ -135,7 +141,7 @@ async def build_workflow(
135141
log_error(e, "build_workflow")
136142
# Return a default workflow guidance in case of error
137143
return WorkflowGuidance(
138-
next_tool="elicit_missing_requirements",
144+
next_tool="raise_missing_requirements",
139145
reasoning="An error occurred during workflow generation. Please provide more details.",
140146
preparation_needed=[
141147
"Review the error and provide more specific requirements"
@@ -558,9 +564,16 @@ async def judge_coding_plan(
558564

559565
try:
560566
# STEP 1: Load conversation history and format as JSON array
561-
conversation_history = await conversation_service.load_filtered_context_for_enrichment(session_id, json.dumps(original_input))
562-
history_json_array = conversation_service.format_conversation_history_as_json_array(conversation_history)
563-
567+
conversation_history = (
568+
await conversation_service.load_filtered_context_for_enrichment(
569+
session_id, json.dumps(original_input)
570+
)
571+
)
572+
history_json_array = (
573+
conversation_service.format_conversation_history_as_json_array(
574+
conversation_history
575+
)
576+
)
564577

565578
# STEP 2: Use helper function for main evaluation with JSON array conversation history
566579
evaluation_result = await _evaluate_coding_plan(
@@ -639,8 +652,16 @@ async def judge_code_change(
639652

640653
try:
641654
# STEP 1: Load conversation history and format as JSON array
642-
conversation_history = await conversation_service.load_filtered_context_for_enrichment(session_id,json.dumps(original_input))
643-
history_json_array = conversation_service.format_conversation_history_as_json_array(conversation_history)
655+
conversation_history = (
656+
await conversation_service.load_filtered_context_for_enrichment(
657+
session_id, json.dumps(original_input)
658+
)
659+
)
660+
history_json_array = (
661+
conversation_service.format_conversation_history_as_json_array(
662+
conversation_history
663+
)
664+
)
644665

645666
# STEP 2: Create system and user messages with separate context and conversation history
646667
system_vars = JudgeCodeChangeSystemVars(

tests/test_conversation_history_service_integration.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ async def test_service_save_and_retrieve_lifecycle(self, service):
5353
# PHASE 2: Retrieve conversation history
5454
print("\n📖 PHASE 2: Retrieving conversation history...")
5555

56-
conversation_history = await service.load_context_for_enrichment(session_id)
56+
conversation_history = await service.load_filtered_context_for_enrichment(
57+
session_id
58+
)
5759
assert len(conversation_history) == 2, (
5860
f"Expected 2 records, got {len(conversation_history)}"
5961
)
@@ -101,7 +103,7 @@ async def test_service_save_and_retrieve_lifecycle(self, service):
101103
)
102104

103105
# Should only get max_session_records (20) records
104-
limited_history = await service.load_context_for_enrichment(session_id)
106+
limited_history = await service.load_filtered_context_for_enrichment(session_id)
105107
expected_count = service.config.database.max_session_records
106108
assert len(limited_history) == expected_count, (
107109
f"Expected {expected_count} records, got {len(limited_history)}"
@@ -151,7 +153,7 @@ async def test_service_with_context_ids(self, service):
151153
)
152154

153155
# Retrieve and verify
154-
history = await service.load_context_for_enrichment(session_id)
156+
history = await service.load_filtered_context_for_enrichment(session_id)
155157
assert len(history) == 3
156158

157159
# Verify the conversation flow makes sense
@@ -168,7 +170,9 @@ async def test_service_empty_and_error_cases(self, service):
168170
print("=" * 60)
169171

170172
# Test empty session
171-
empty_history = await service.load_context_for_enrichment("nonexistent_session")
173+
empty_history = await service.load_filtered_context_for_enrichment(
174+
"nonexistent_session"
175+
)
172176
assert len(empty_history) == 0
173177
print("✅ Empty session handled correctly")
174178

@@ -180,14 +184,16 @@ async def test_service_empty_and_error_cases(self, service):
180184

181185
# Test with special characters in data
182186
special_session = "special_chars_session"
183-
await service.save_tool_interaction(
187+
await service.save_tool_interaction_and_cleanup(
184188
session_id=special_session,
185189
tool_name="test_tool",
186190
tool_input="Input with 'quotes' and \"double quotes\" and \n newlines",
187191
tool_output="Result with émojis 🎉 and unicode ñ characters",
188192
)
189193

190-
special_history = await service.load_context_for_enrichment(special_session)
194+
special_history = await service.load_filtered_context_for_enrichment(
195+
special_session
196+
)
191197
assert len(special_history) == 1
192198

193199
special_json = service.format_conversation_history_as_json_array(
@@ -223,7 +229,7 @@ async def test_service_performance_with_large_dataset(self, service):
223229

224230
# Retrieve records
225231
start_time = datetime.now()
226-
history = await service.load_context_for_enrichment(session_id)
232+
history = await service.load_filtered_context_for_enrichment(session_id)
227233
retrieve_time = datetime.now() - start_time
228234

229235
print(

0 commit comments

Comments
 (0)