feat(mma): Implement Deep AST-Driven Context Pruning and mark track complete
This commit is contained in:
167
src/models.py
167
src/models.py
@@ -1,59 +1,35 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import os
|
||||
from __future__ import annotations
|
||||
import tomllib
|
||||
from src import project_manager
|
||||
|
||||
CONFIG_PATH: Path = Path(os.environ.get("SLOP_CONFIG", "config.toml"))
|
||||
DISC_ROLES: list[str] = ["User", "AI", "Vendor API", "System"]
|
||||
AGENT_TOOL_NAMES: list[str] = [
|
||||
"run_powershell",
|
||||
"read_file",
|
||||
"list_directory",
|
||||
"search_files",
|
||||
"get_file_summary",
|
||||
"web_search",
|
||||
"fetch_url",
|
||||
"py_get_skeleton",
|
||||
"py_get_code_outline",
|
||||
"get_file_slice",
|
||||
"py_get_definition",
|
||||
"py_get_signature",
|
||||
"py_get_class_summary",
|
||||
"py_get_var_declaration",
|
||||
"get_git_diff",
|
||||
"py_find_usages",
|
||||
"py_get_imports",
|
||||
"py_check_syntax",
|
||||
"py_get_hierarchy",
|
||||
"py_get_docstring",
|
||||
"get_tree",
|
||||
"get_ui_performance",
|
||||
# Mutating tools — disabled by default
|
||||
"set_file_slice",
|
||||
"py_update_definition",
|
||||
"py_set_signature",
|
||||
"py_set_var_declaration",
|
||||
]
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional, Dict, Any, Union
|
||||
from pathlib import Path
|
||||
|
||||
CONFIG_PATH = Path("config.toml")
|
||||
|
||||
def load_config() -> dict[str, Any]:
|
||||
with open(CONFIG_PATH, "rb") as f:
|
||||
return tomllib.load(f)
|
||||
|
||||
|
||||
def parse_history_entries(
|
||||
history: list[str], roles: list[str] | None = None
|
||||
) -> list[dict[str, Any]]:
|
||||
known = roles if roles is not None else DISC_ROLES
|
||||
entries = []
|
||||
for raw in history:
|
||||
entry = project_manager.str_to_entry(raw, known)
|
||||
entries.append(entry)
|
||||
return entries
|
||||
|
||||
# Global constants for agent tools
|
||||
AGENT_TOOL_NAMES = [
|
||||
"read_file",
|
||||
"list_directory",
|
||||
"search_files",
|
||||
"web_search",
|
||||
"fetch_url",
|
||||
"get_file_summary",
|
||||
"py_get_skeleton",
|
||||
"py_get_code_outline",
|
||||
"py_get_definition",
|
||||
"py_get_signature",
|
||||
"py_get_class_summary",
|
||||
"py_get_var_declaration",
|
||||
"py_get_docstring",
|
||||
"py_find_usages",
|
||||
"py_get_imports",
|
||||
"py_check_syntax",
|
||||
"py_get_hierarchy"
|
||||
]
|
||||
|
||||
@dataclass
|
||||
class Ticket:
|
||||
@@ -66,6 +42,7 @@ class Ticket:
|
||||
status: str = "todo"
|
||||
assigned_to: str = "unassigned"
|
||||
target_file: Optional[str] = None
|
||||
target_symbols: List[str] = field(default_factory=list)
|
||||
context_requirements: List[str] = field(default_factory=list)
|
||||
depends_on: List[str] = field(default_factory=list)
|
||||
blocked_reason: Optional[str] = None
|
||||
@@ -92,6 +69,7 @@ class Ticket:
|
||||
"status": self.status,
|
||||
"assigned_to": self.assigned_to,
|
||||
"target_file": self.target_file,
|
||||
"target_symbols": self.target_symbols,
|
||||
"context_requirements": self.context_requirements,
|
||||
"depends_on": self.depends_on,
|
||||
"blocked_reason": self.blocked_reason,
|
||||
@@ -107,6 +85,7 @@ class Ticket:
|
||||
status=data.get("status", "todo"),
|
||||
assigned_to=data.get("assigned_to", ""),
|
||||
target_file=data.get("target_file"),
|
||||
target_symbols=data.get("target_symbols", []),
|
||||
context_requirements=data.get("context_requirements", []),
|
||||
depends_on=data.get("depends_on", []),
|
||||
blocked_reason=data.get("blocked_reason"),
|
||||
@@ -125,104 +104,78 @@ class Track:
|
||||
description: str
|
||||
tickets: List[Ticket] = field(default_factory=list)
|
||||
|
||||
def get_executable_tickets(self) -> List[Ticket]:
|
||||
"""
|
||||
Returns all 'todo' tickets whose dependencies are all 'completed'.
|
||||
"""
|
||||
# Map ticket IDs to their current status for efficient lookup
|
||||
status_map = {t.id: t.status for t in self.tickets}
|
||||
executable = []
|
||||
for ticket in self.tickets:
|
||||
if ticket.status != "todo":
|
||||
continue
|
||||
# Check if all dependencies are completed
|
||||
all_deps_completed = True
|
||||
for dep_id in ticket.depends_on:
|
||||
# If a dependency is missing from the track, we treat it as not completed (or we could raise an error)
|
||||
if status_map.get(dep_id) != "completed":
|
||||
all_deps_completed = False
|
||||
break
|
||||
if all_deps_completed:
|
||||
executable.append(ticket)
|
||||
return executable
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": self.id,
|
||||
"description": self.description,
|
||||
"tickets": [t.to_dict() for t in self.tickets],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "Track":
|
||||
return cls(
|
||||
id=data["id"],
|
||||
description=data.get("description", ""),
|
||||
tickets=[Ticket.from_dict(t) for t in data.get("tickets", [])],
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class WorkerContext:
|
||||
"""
|
||||
Represents the context provided to a Tier 3 Worker for a specific ticket.
|
||||
State preserved for a specific worker throughout its ticket lifecycle.
|
||||
"""
|
||||
|
||||
ticket_id: str
|
||||
model_name: str
|
||||
messages: List[Dict[str, Any]]
|
||||
messages: List[Dict[str, Any]] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Metadata:
|
||||
id: str
|
||||
name: str
|
||||
status: Optional[str] = None
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
status: str
|
||||
created_at: Union[str, Any]
|
||||
updated_at: Union[str, Any]
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"status": self.status,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
||||
"created_at": str(self.created_at),
|
||||
"updated_at": str(self.updated_at),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "Metadata":
|
||||
return cls(
|
||||
id=data["id"],
|
||||
name=data["name"],
|
||||
status=data.get("status"),
|
||||
created_at=datetime.fromisoformat(data["created_at"])
|
||||
if data.get("created_at")
|
||||
else None,
|
||||
updated_at=datetime.fromisoformat(data["updated_at"])
|
||||
if data.get("updated_at")
|
||||
else None,
|
||||
name=data.get("name", ""),
|
||||
status=data.get("status", "todo"),
|
||||
created_at=data.get("created_at"),
|
||||
updated_at=data.get("updated_at"),
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TrackState:
|
||||
metadata: Metadata
|
||||
discussion: List[Dict[str, Any]]
|
||||
tasks: List[Ticket]
|
||||
discussion: List[str] = field(default_factory=list)
|
||||
tasks: List[Ticket] = field(default_factory=list)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"metadata": self.metadata.to_dict(),
|
||||
"discussion": [
|
||||
{
|
||||
k: v.isoformat() if isinstance(v, datetime) else v
|
||||
for k, v in item.items()
|
||||
}
|
||||
for item in self.discussion
|
||||
],
|
||||
"tasks": [task.to_dict() for task in self.tasks],
|
||||
"discussion": self.discussion,
|
||||
"tasks": [t.to_dict() for t in self.tasks],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "TrackState":
|
||||
metadata = Metadata.from_dict(data["metadata"])
|
||||
tasks = [Ticket.from_dict(task_data) for task_data in data["tasks"]]
|
||||
return cls(
|
||||
metadata=metadata,
|
||||
discussion=[
|
||||
{
|
||||
k: datetime.fromisoformat(v)
|
||||
if isinstance(v, str) and "T" in v
|
||||
else v # Basic check for ISO format
|
||||
for k, v in item.items()
|
||||
}
|
||||
for item in data["discussion"]
|
||||
],
|
||||
tasks=tasks,
|
||||
metadata=Metadata.from_dict(data["metadata"]),
|
||||
discussion=data.get("discussion", []),
|
||||
tasks=[Ticket.from_dict(t) for t in data.get("tasks", [])],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user