diff --git a/src/epochx/core/prompt_generator.py b/src/epochx/core/prompt_generator.py index 846aad8..aa7c115 100644 --- a/src/epochx/core/prompt_generator.py +++ b/src/epochx/core/prompt_generator.py @@ -7,23 +7,59 @@ from epochx.core.task import OutputType, Task, WorkspaceInfo +def _skill_name(task: Task) -> str: + """Generate a skill name from benchmark + task external_id. + + e.g. "swebench-verified-django-11099" + """ + parts = task.external_id.replace("__", "-").replace("_", "-").lower() + return f"{task.benchmark}-{parts}" + + def generate_prompt(task: Task, ws_info: WorkspaceInfo) -> str: """Generate a standardized markdown prompt for an agent. Sections: - Task ID + - Before You Start (search for existing skills) - Instructions - Workspace path - Environment Commands (SSH if docker, direct if host) - Available Tools - Output instructions (based on OutputType) + - After Completion (distill & publish skill) - When Done """ sections: list[str] = [] + skill_name = _skill_name(task) + # Header sections.append(f"# Task: {task.id}\n") + # Before You Start — search for skills + sections.append("## Before You Start\n") + sections.append( + "Search the EpochX skill marketplace for existing solutions or strategies " + "that might help with this task:\n" + ) + sections.append("```bash") + sections.append(f"epochx skill search \"{task.benchmark} {task.external_id}\"") + sections.append("```\n") + sections.append( + "If relevant skills are found (score > 0.3), download and review them — " + "especially the `references/` directory which may contain trajectories " + "from previous successful attempts:\n" + ) + sections.append("```bash") + sections.append("epochx skill use --out ./skill-ref") + sections.append("```\n") + sections.append( + "Use any helpful patterns, but solve the task independently. " + "Do not blindly copy solutions." + ) + sections.append("") + # Instructions sections.append("## Instructions\n") sections.append(task.prompt) @@ -91,13 +127,80 @@ def generate_prompt(task: Task, ws_info: WorkspaceInfo) -> str: ) sections.append("") + # Trajectory + sections.append("## Trajectory (optional)\n") + sections.append( + "Your SSH commands are logged automatically. " + "For richer trajectory data (reasoning, tool choices), " + "append JSONL to `/.epochx/trajectory.jsonl` inside the container:\n" + ) + sections.append("```json") + sections.append('{"step":1,"type":"thought","content":"analyzing the issue..."}') + sections.append('{"step":2,"type":"tool_call","tool_name":"grep","tool_input":"grep -r pattern .","tool_output":"..."}') + sections.append("```") + sections.append("") + + # After Completion — distill skill + sections.append("## After Completion — Publish Skill\n") + sections.append( + "After solving the task, distill your approach into a reusable skill " + "so future agents can learn from your experience.\n" + ) + sections.append( + "**Step 1.** Create the skill directory in the workspace:\n" + ) + sections.append("```bash") + sections.append(f"mkdir -p {ws_info.path}/skill/references") + sections.append("```\n") + sections.append( + "**Step 2.** Write a SKILL.md summarizing your approach:\n" + ) + sections.append("```bash") + sections.append(f"cat > {ws_info.path}/skill/SKILL.md << 'SKILLEOF'") + sections.append(f"# {skill_name}\n") + sections.append(f"## Task\n{task.benchmark} / {task.external_id}\n") + sections.append("## Approach\n(Describe your strategy: what you looked at, " + "what the root cause was, how you fixed it)\n") + sections.append("## Key Insight\n(One-line takeaway that helps future agents)\n") + sections.append("## Files Changed\n(List the files you modified and why)") + sections.append("SKILLEOF") + sections.append("```\n") + sections.append( + "**Step 3.** Copy the trajectory (auto-recorded) into the skill:\n" + ) + sections.append("```bash") + epochx_dir = f"{ws_info.path}/.epochx" + sections.append( + f"cp {epochx_dir}/trajectory_collected.json " + f"{ws_info.path}/skill/references/trajectory.json 2>/dev/null || true" + ) + sections.append( + f"cp {epochx_dir}/output.txt " + f"{ws_info.path}/skill/references/output.txt 2>/dev/null || true" + ) + sections.append("```\n") + sections.append( + "**Step 4.** Publish the skill to EpochX:\n" + ) + sections.append("```bash") + sections.append( + f"epochx skill submit --name \"{skill_name}\" " + f"--dir {ws_info.path}/skill" + ) + sections.append("```") + sections.append("") + # When Done sections.append("## When Done\n") sections.append( - f"Run the following command to collect your output:\n" + f"Run these commands in order:\n" ) - sections.append(f"```bash") + sections.append("```bash") + sections.append(f"# 1. Collect your solution output") sections.append(f"epochx-bench collect {task.id}") + sections.append(f"") + sections.append(f"# 2. Then publish skill (after collect, so trajectory is available)") + sections.append(f"# Follow the 'After Completion' steps above") sections.append(f"```") return "\n".join(sections)