""" CLI entry point for the Sisyphus LangChain agent. This mirrors Loki's `loki --agent sisyphus` entry point. In Loki: loki --agent sisyphus # Starts a REPL with the sisyphus agent loaded In this LangChain version: python -m sisyphus_langchain.cli # or: sisyphus (if installed via pip) Usage: # Interactive REPL mode sisyphus # One-shot query sisyphus "Add a health check endpoint to the API" # With custom models sisyphus --supervisor-model gpt-4o --explore-model gpt-4o-mini "Find auth patterns" Environment variables: OPENAI_API_KEY — Required for OpenAI models ANTHROPIC_API_KEY — Required if using Anthropic models """ from __future__ import annotations import argparse import sys import uuid from langchain_core.messages import HumanMessage from sisyphus_langchain.graph import build_graph def run_query(graph, query: str, thread_id: str) -> str: """ Run a single query through the Sisyphus graph. Args: graph: Compiled LangGraph. query: User's natural language request. thread_id: Session identifier for checkpointing. Returns: The final output string. """ result = graph.invoke( { "messages": [HumanMessage(content=query)], "intent": "ambiguous", "next_agent": "", "iteration_count": 0, "todos": [], "agent_outputs": {}, "final_output": "", "project_dir": ".", }, config={ "configurable": {"thread_id": thread_id}, "recursion_limit": 50, }, ) return result.get("final_output", "(no output)") def repl(graph, thread_id: str) -> None: """ Interactive REPL loop — mirrors Loki's REPL mode. Maintains conversation across turns via the thread_id (checkpointer). """ print("Sisyphus (LangChain) — type 'quit' to exit") print("=" * 50) while True: try: query = input("\n> ").strip() except (EOFError, KeyboardInterrupt): print("\nBye.") break if not query: continue if query.lower() in ("quit", "exit", "q"): print("Bye.") break try: output = run_query(graph, query, thread_id) print(f"\n{output}") except Exception as e: print(f"\nError: {e}") def main() -> None: """CLI entry point.""" parser = argparse.ArgumentParser( description="Sisyphus — multi-agent coding orchestrator (LangChain edition)" ) parser.add_argument( "query", nargs="?", help="One-shot query (omit for REPL mode)", ) parser.add_argument( "--supervisor-model", default="gpt-4o", help="Model for the supervisor (default: gpt-4o)", ) parser.add_argument( "--explore-model", default="gpt-4o-mini", help="Model for the explore agent (default: gpt-4o-mini)", ) parser.add_argument( "--oracle-model", default="gpt-4o", help="Model for the oracle agent (default: gpt-4o)", ) parser.add_argument( "--coder-model", default="gpt-4o", help="Model for the coder agent (default: gpt-4o)", ) parser.add_argument( "--thread-id", default=None, help="Session thread ID for persistence (auto-generated if omitted)", ) args = parser.parse_args() graph = build_graph( supervisor_model=args.supervisor_model, explore_model=args.explore_model, oracle_model=args.oracle_model, coder_model=args.coder_model, ) thread_id = args.thread_id or f"sisyphus-{uuid.uuid4().hex[:8]}" if args.query: output = run_query(graph, args.query, thread_id) print(output) else: repl(graph, thread_id) if __name__ == "__main__": main()