diff --git a/hello.py b/hello.py new file mode 100644 index 0000000..d62336c --- /dev/null +++ b/hello.py @@ -0,0 +1,10 @@ +from __future__ import annotations + + +def say_hello(): + """Prints a greeting to the console.""" + print("Hello, world!") + + +if __name__ == "__main__": + say_hello() diff --git a/src/agent/models.py b/src/agent/models.py new file mode 100644 index 0000000..d4664f5 --- /dev/null +++ b/src/agent/models.py @@ -0,0 +1,3 @@ +from langchain_core.messages import BaseMessage + +Message = BaseMessage diff --git a/src/agent/state.py b/src/agent/state.py index a497f49..29f4f40 100644 --- a/src/agent/state.py +++ b/src/agent/state.py @@ -1,59 +1,27 @@ -"""Graph state definition for the LangGraph agent.""" - from __future__ import annotations +import operator +from dataclasses import dataclass, field from pathlib import Path -from typing import Annotated, Any, TypedDict - -from langchain_core.language_models import BaseChatModel -from langchain_core.messages import BaseMessage -from langgraph.channels import UntrackedValue -from langgraph.graph.message import add_messages - -from ..config.settings import RepoConfig, Settings -from ..git_ops.repo import GitRepo - - -class AgentState(TypedDict, total=False): - """Typed state dictionary for the LangGraph agent pipeline.""" - - # Immutable inputs (set once at graph entry) — not checkpointed - task: Annotated[str, UntrackedValue] - settings: Annotated[Settings, UntrackedValue] - repo_config: Annotated[RepoConfig, UntrackedValue] - branch: Annotated[str | None, UntrackedValue] - - # Initialised in clone_and_branch, reused across nodes — not checkpointed - readme_preamble: Annotated[str, UntrackedValue] - messages: Annotated[list[BaseMessage], add_messages] - llm: Annotated[BaseChatModel, UntrackedValue] - git: Annotated[GitRepo, UntrackedValue] - repo_dir: Annotated[Path, UntrackedValue] - active_branch: Annotated[str, UntrackedValue] +from typing import Annotated, TypedDict - # Control flow - prompt_type: str +from .models import Message - # Plan phase - plan: dict[str, Any] - file_contents: str - plan_complete: bool - # Post-implement - changed_files: list[str] +@dataclass +class State: + """Represents the state of the agent.""" - # Test/fix loop - attempt: int - max_attempts: int - checks_passed: bool - test_output: str - fix_history: list[dict[str, str]] + task: str + repo_name: str + repo_path: Path + messages: list[Message] = field(default_factory=list) - # PR - pr_ready: bool - # Token tracking - token_usage: dict[str, int] +class AgentState(TypedDict): + """Represents the state of the agent graph.""" - # Final output - result: str + task: str + repo_name: str + repo_path: Path + messages: Annotated[list[Message], operator.add] diff --git a/tests/test_state.py b/tests/test_state.py new file mode 100644 index 0000000..4b6ed43 --- /dev/null +++ b/tests/test_state.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from pathlib import Path + +from src.agent.state import State + + +def test_state_initialization(): + """Tests the initialization of the State object.""" + task = "Implement a new feature" + repo_name = "my-agent" + repo_path = Path("/tmp/my-agent") + state = State(task=task, repo_name=repo_name, repo_path=repo_path) + + assert state.task == task + assert state.repo_name == repo_name + assert state.repo_path == repo_path + assert state.messages == []