OK.
This commit is contained in:
@@ -17,7 +17,6 @@ def save_config(config: dict[str, Any]) -> None:
|
||||
with open(CONFIG_PATH, "wb") as f:
|
||||
tomli_w.dump(config, f)
|
||||
|
||||
# Global constants for agent tools
|
||||
AGENT_TOOL_NAMES = [
|
||||
"run_powershell",
|
||||
"read_file",
|
||||
@@ -40,7 +39,6 @@ AGENT_TOOL_NAMES = [
|
||||
]
|
||||
|
||||
def parse_history_entries(history_strings: list[str], roles: list[str]) -> list[dict[str, Any]]:
|
||||
"""Parse stored history strings back to disc entry dicts."""
|
||||
import re
|
||||
entries = []
|
||||
for raw in history_strings:
|
||||
@@ -64,10 +62,6 @@ def parse_history_entries(history_strings: list[str], roles: list[str]) -> list[
|
||||
|
||||
@dataclass
|
||||
class Ticket:
|
||||
"""
|
||||
Represents a discrete unit of work within a track.
|
||||
"""
|
||||
|
||||
id: str
|
||||
description: str
|
||||
status: str = "todo"
|
||||
@@ -81,16 +75,13 @@ class Ticket:
|
||||
retry_count: int = 0
|
||||
|
||||
def mark_blocked(self, reason: str) -> None:
|
||||
"""Sets the ticket status to 'blocked' and records the reason."""
|
||||
self.status = "blocked"
|
||||
self.blocked_reason = reason
|
||||
|
||||
def mark_complete(self) -> None:
|
||||
"""Sets the ticket status to 'completed'."""
|
||||
self.status = "completed"
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""Helper to provide dictionary-like access to dataclass fields."""
|
||||
return getattr(self, key, default)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
@@ -127,16 +118,11 @@ class Ticket:
|
||||
|
||||
@dataclass
|
||||
class Track:
|
||||
"""
|
||||
Represents a collection of tickets that together form an architectural track or epic.
|
||||
"""
|
||||
|
||||
id: str
|
||||
description: str
|
||||
tickets: List[Ticket] = field(default_factory=list)
|
||||
|
||||
def get_executable_tickets(self) -> List[Ticket]:
|
||||
"""Returns tickets that are ready to be executed (dependencies met)."""
|
||||
from src.dag_engine import TrackDAG
|
||||
dag = TrackDAG(self.tickets)
|
||||
return dag.get_ready_tasks()
|
||||
@@ -159,10 +145,6 @@ class Track:
|
||||
|
||||
@dataclass
|
||||
class WorkerContext:
|
||||
"""
|
||||
State preserved for a specific worker throughout its ticket lifecycle.
|
||||
"""
|
||||
|
||||
ticket_id: str
|
||||
model_name: str
|
||||
messages: List[Dict[str, Any]] = field(default_factory=list)
|
||||
@@ -172,17 +154,17 @@ class WorkerContext:
|
||||
class Metadata:
|
||||
id: str
|
||||
name: str
|
||||
status: str
|
||||
created_at: Union[str, Any]
|
||||
updated_at: Union[str, Any]
|
||||
status: Optional[str] = None
|
||||
created_at: Optional[datetime.datetime] = None
|
||||
updated_at: Optional[datetime.datetime] = None
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"status": self.status,
|
||||
"created_at": str(self.created_at),
|
||||
"updated_at": str(self.updated_at),
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None,
|
||||
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -193,16 +175,16 @@ class Metadata:
|
||||
try:
|
||||
created = datetime.datetime.fromisoformat(created)
|
||||
except ValueError:
|
||||
pass
|
||||
created = None
|
||||
if isinstance(updated, str):
|
||||
try:
|
||||
updated = datetime.datetime.fromisoformat(updated)
|
||||
except ValueError:
|
||||
pass
|
||||
updated = None
|
||||
return cls(
|
||||
id=data["id"],
|
||||
name=data.get("name", ""),
|
||||
status=data.get("status", "todo"),
|
||||
status=data.get("status"),
|
||||
created_at=created,
|
||||
updated_at=updated,
|
||||
)
|
||||
@@ -215,16 +197,39 @@ class TrackState:
|
||||
tasks: List[Ticket] = field(default_factory=list)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
serialized_discussion = []
|
||||
for item in self.discussion:
|
||||
if isinstance(item, dict):
|
||||
new_item = dict(item)
|
||||
if "ts" in new_item and isinstance(new_item["ts"], datetime.datetime):
|
||||
new_item["ts"] = new_item["ts"].isoformat()
|
||||
serialized_discussion.append(new_item)
|
||||
else:
|
||||
serialized_discussion.append(item)
|
||||
return {
|
||||
"metadata": self.metadata.to_dict(),
|
||||
"discussion": self.discussion,
|
||||
"discussion": serialized_discussion,
|
||||
"tasks": [t.to_dict() for t in self.tasks],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "TrackState":
|
||||
discussion = data.get("discussion", [])
|
||||
parsed_discussion = []
|
||||
for item in discussion:
|
||||
if isinstance(item, dict):
|
||||
new_item = dict(item)
|
||||
ts = new_item.get("ts")
|
||||
if isinstance(ts, str):
|
||||
try:
|
||||
new_item["ts"] = datetime.datetime.fromisoformat(ts)
|
||||
except ValueError:
|
||||
pass
|
||||
parsed_discussion.append(new_item)
|
||||
else:
|
||||
parsed_discussion.append(item)
|
||||
return cls(
|
||||
metadata=Metadata.from_dict(data["metadata"]),
|
||||
discussion=data.get("discussion", []),
|
||||
discussion=parsed_discussion,
|
||||
tasks=[Ticket.from_dict(t) for t in data.get("tasks", [])],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user