mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-20 18:35:14 +00:00
Align all 4 language recipes (Node.js, Python, .NET, Go) with the Ralph Playbook architecture: - Simple version: minimal outer loop with fresh session per iteration - Ideal version: planning/building modes, backpressure, git integration - Fresh context isolation instead of in-session context accumulation - Disk-based shared state via IMPLEMENTATION_PLAN.md - Example prompt templates (PROMPT_plan.md, PROMPT_build.md, AGENTS.md) - Updated cookbook README descriptions
85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Ralph loop: autonomous AI task loop with fresh context per iteration.
|
|
|
|
Two modes:
|
|
- "plan": reads PROMPT_plan.md, generates/updates IMPLEMENTATION_PLAN.md
|
|
- "build": reads PROMPT_build.md, implements tasks, runs tests, commits
|
|
|
|
Each iteration creates a fresh session so the agent always operates in
|
|
the "smart zone" of its context window. State is shared between
|
|
iterations via files on disk (IMPLEMENTATION_PLAN.md, AGENTS.md, specs/*).
|
|
|
|
Usage:
|
|
python ralph_loop.py # build mode, 50 iterations
|
|
python ralph_loop.py plan # planning mode
|
|
python ralph_loop.py 20 # build mode, 20 iterations
|
|
python ralph_loop.py plan 5 # planning mode, 5 iterations
|
|
"""
|
|
|
|
import asyncio
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from copilot import CopilotClient, MessageOptions, SessionConfig
|
|
|
|
|
|
async def ralph_loop(mode: str = "build", max_iterations: int = 50):
|
|
prompt_file = "PROMPT_plan.md" if mode == "plan" else "PROMPT_build.md"
|
|
|
|
client = CopilotClient()
|
|
await client.start()
|
|
|
|
branch = subprocess.check_output(
|
|
["git", "branch", "--show-current"], text=True
|
|
).strip()
|
|
|
|
print("━" * 40)
|
|
print(f"Mode: {mode}")
|
|
print(f"Prompt: {prompt_file}")
|
|
print(f"Branch: {branch}")
|
|
print(f"Max: {max_iterations} iterations")
|
|
print("━" * 40)
|
|
|
|
try:
|
|
prompt = Path(prompt_file).read_text()
|
|
|
|
for i in range(1, max_iterations + 1):
|
|
print(f"\n=== Iteration {i}/{max_iterations} ===")
|
|
|
|
# Fresh session — each task gets full context budget
|
|
session = await client.create_session(
|
|
SessionConfig(model="claude-sonnet-4.5")
|
|
)
|
|
try:
|
|
await session.send_and_wait(
|
|
MessageOptions(prompt=prompt), timeout=600
|
|
)
|
|
finally:
|
|
await session.destroy()
|
|
|
|
# Push changes after each iteration
|
|
try:
|
|
subprocess.run(
|
|
["git", "push", "origin", branch], check=True
|
|
)
|
|
except subprocess.CalledProcessError:
|
|
subprocess.run(
|
|
["git", "push", "-u", "origin", branch], check=True
|
|
)
|
|
|
|
print(f"\nIteration {i} complete.")
|
|
|
|
print(f"\nReached max iterations: {max_iterations}")
|
|
finally:
|
|
await client.stop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv[1:]
|
|
mode = "plan" if "plan" in args else "build"
|
|
max_iter = next((int(a) for a in args if a.isdigit()), 50)
|
|
asyncio.run(ralph_loop(mode, max_iter))
|