Skip to content

Commit 1bef7bf

Browse files
doriwaldori
andauthored
feat: improve memory cleanup when plan approve (#26)
* feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve * feat: improve memory cleanup when plan approve --------- Co-authored-by: dori <dori.waldman@catonetworks.com>
1 parent 7a636d9 commit 1bef7bf

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

src/mcp_as_a_judge/db/interface.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,16 @@ async def get_recent_sessions(self, limit: int = 10) -> list[tuple[str, int]]:
7878
List of tuples: (session_id, last_activity_timestamp), ordered by most recent first
7979
"""
8080
pass
81+
82+
@abstractmethod
83+
async def delete_previous_plan(self, session_id: str) -> None:
84+
"""
85+
Delete all previous judge_coding_plan records except the most recent one.
86+
87+
This method removes all but the last conversation record with source='judge_coding_plan'
88+
for the given session to avoid keeping multiple failed plan attempts.
89+
90+
Args:
91+
session_id: Session identifier
92+
"""
93+
pass

src/mcp_as_a_judge/db/providers/sqlite_provider.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import time
99
import uuid
1010

11-
from sqlalchemy import create_engine, func
11+
from sqlalchemy import create_engine, delete, func
1212
from sqlmodel import Session, SQLModel, asc, desc, select
1313

1414
from mcp_as_a_judge.core.constants import MAX_CONTEXT_TOKENS
@@ -303,3 +303,61 @@ async def get_recent_sessions(self, limit: int = 10) -> list[tuple[str, int]]:
303303
results = session.exec(stmt).all()
304304
# results are tuples (session_id, last_activity)
305305
return [(row[0], int(row[1])) for row in results]
306+
307+
async def delete_previous_plan(self, session_id: str) -> None:
308+
"""
309+
Delete all previous judge_coding_plan records except the most recent one.
310+
311+
Uses SQL ORM to find all judge_coding_plan records for the session,
312+
keeps only the most recent one, and deletes the rest.
313+
"""
314+
try:
315+
with Session(self.engine) as session:
316+
# Find all judge_coding_plan records for this session, ordered by timestamp DESC
317+
stmt = (
318+
select(ConversationRecord)
319+
.where(ConversationRecord.session_id == session_id)
320+
.where(ConversationRecord.source == "judge_coding_plan")
321+
.order_by(
322+
desc(ConversationRecord.timestamp),
323+
desc(ConversationRecord.id),
324+
)
325+
)
326+
plan_records = list(session.exec(stmt).all())
327+
328+
if len(plan_records) <= 1:
329+
# No previous plans to delete
330+
logger.info(
331+
f"No previous judge_coding_plan records to delete for session {session_id}"
332+
)
333+
return
334+
335+
# Keep the first record (most recent), delete the rest
336+
records_to_delete = plan_records[1:] # Skip the first (most recent)
337+
record_ids_to_delete: list[str] = [
338+
record.id for record in records_to_delete if record.id is not None
339+
]
340+
341+
if not record_ids_to_delete:
342+
logger.info(
343+
f"No valid record IDs to delete for session {session_id}"
344+
)
345+
return
346+
347+
# Delete records using SQL IN clause with underlying SQLAlchemy session
348+
# Use the table name from ConversationRecord to avoid type issues
349+
table_name = ConversationRecord.__tablename__
350+
table = SQLModel.metadata.tables[table_name]
351+
delete_stmt = delete(table).where(table.c.id.in_(record_ids_to_delete))
352+
# Use the underlying SQLAlchemy session for delete operations
353+
session.execute(delete_stmt)
354+
session.commit()
355+
356+
logger.info(
357+
f"Successfully deleted {len(records_to_delete)} previous judge_coding_plan records for session {session_id}"
358+
)
359+
360+
except Exception as e:
361+
logger.error(
362+
f"Error deleting previous judge_coding_plan records for session {session_id}: {e}"
363+
)

src/mcp_as_a_judge/server.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,12 @@ async def judge_coding_plan(
16861686
# Mark plan as approved for completion validation and update state
16871687
updated_task_metadata.mark_plan_approved()
16881688
updated_task_metadata.update_state(TaskState.PLAN_APPROVED)
1689+
1690+
# Delete previous failed plan attempts, keeping only the most recent approved one
1691+
await conversation_service.db.delete_previous_plan(
1692+
updated_task_metadata.task_id
1693+
)
1694+
16891695
# Force next step to code review implementation gate
16901696
workflow_guidance.next_tool = "judge_code_change"
16911697
if not workflow_guidance.reasoning:

0 commit comments

Comments
 (0)