diff --git a/ga.py b/ga.py index 4ccd84f4..0173a633 100644 --- a/ga.py +++ b/ga.py @@ -7,6 +7,7 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from agent_loop import BaseHandler, StepOutcome, json_default +from turn_policy import register_turn_policies script_dir = os.path.dirname(os.path.abspath(__file__)) def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop_signal=None, maxlen=10000): @@ -268,6 +269,8 @@ def __init__(self, parent, last_history=None, cwd='./temp'): self.history_info = last_history if last_history else [] self.code_stop_signal = [] self._done_hooks = [] + # Turn policy hooks - pluggable strategy chain (from turn_policy.py) + register_turn_policies(self) def _get_abs_path(self, path): if not path: return "" @@ -543,7 +546,7 @@ def _get_anchor_prompt(self, skip=False): try: print(prompt) except: pass return prompt - + def turn_end_callback(self, response, tool_calls, tool_results, turn, next_prompt, exit_reason): _c = re.sub(r'```.*?```|.*?', '', response.content, flags=re.DOTALL) rsumm = re.search(r"(.*?)", _c, re.DOTALL) @@ -559,15 +562,9 @@ def turn_end_callback(self, response, tool_calls, tool_results, turn, next_promp self.history_info.append(f'[Agent] {summary}') _plan = self._in_plan_mode() - if turn % 75 == 0 and (not _plan): - next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。必须总结情况进行ask_user,不允许继续重试。" - elif turn % 7 == 0: - next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。禁止无效重试。若无有效进展,必须切换策略:1. 探测物理边界 2. 请求用户协助。如有需要,可调用 update_working_checkpoint 保存关键上下文。" - elif turn % 10 == 0: next_prompt += get_global_memory() - - if _plan and turn >= 10 and turn % 5 == 0: - next_prompt = f"[Plan Hint] 正在计划模式。必须 file_read({_plan}) 确认当前步骤,回复开头引用:📌 当前步骤:...\n\n" + next_prompt - if _plan and turn >= 120: next_prompt += f"\n\n[DANGER] Plan模式已运行 {turn} 轮,已达上限。必须 ask_user 汇报进度并确认是否继续。" + # Policy hook chain - each policy returns "" or a string to append + for policy in self._turn_policies: + next_prompt += policy(turn, _plan, next_prompt) or "" injkeyinfo = consume_file(self.parent.task_dir, '_keyinfo') injprompt = consume_file(self.parent.task_dir, '_intervene') diff --git a/pyproject.toml b/pyproject.toml index 8a67ca22..063b9a46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,4 +43,7 @@ py-modules = [] packages = ["ga_cli"] [project.scripts] -ga = "ga_cli.cli:main" \ No newline at end of file +ga = "ga_cli.cli:main" + +[tool.ruff] +exclude = ["TMWebDriver.py"] \ No newline at end of file diff --git a/turn_policy.py b/turn_policy.py new file mode 100644 index 00000000..d2b51156 --- /dev/null +++ b/turn_policy.py @@ -0,0 +1,61 @@ + +import os + +def policy_danger_ask_user(turn, _plan, next_prompt): + """每75轮强制ask_user(非plan模式)""" + if turn % 75 == 0 and (not _plan): + return ( + "\n\n[DANGER] 已连续执行第 " + str(turn) + " 轮。" + "必须总结情况进行ask_user,不允许继续重试。" + ) + return "" + + +def policy_danger_retry(turn, _plan, next_prompt): + """每7轮禁止无效重试""" + if turn % 7 == 0: + return ( + "\n\n[DANGER] 已连续执行第 " + str(turn) + " 轮。禁止无效重试。" + "若无有效进展,必须切换策略:1. 探测物理边界 " + "2. 请求用户协助。如有需要,可调用 update_working_checkpoint " + "保存关键上下文。" + ) + return "" + + +def policy_inject_memory(turn, _plan, next_prompt): + """每10轮注入全局记忆""" + if turn % 10 == 0: + from ga import get_global_memory + return get_global_memory() + return "" + + +def policy_plan_limit(turn, _plan, next_prompt): + """Plan模式上限检测""" + if _plan and turn >= 10 and turn % 5 == 0 and turn <= 110: + return ( + "[Plan Hint] 正在计划模式。必须 file_read(" + str(_plan) + ") " + "确认当前步骤,回复开头引用:当前步骤:...\n\n" + ) + if _plan and turn >= 120: + return ( + "\n\n[DANGER] Plan模式已运行 " + str(turn) + " 轮,已达上限。" + "必须 ask_user 汇报进度并确认是否继续。" + ) + return "" + +# Default turn policies that ship with the agent +DEFAULT_TURN_POLICIES = [ + policy_danger_ask_user, + policy_danger_retry, + policy_inject_memory, + policy_plan_limit, +] + +def register_turn_policies(handler, policies=None): + """Register turn policies onto a GenericAgentHandler instance. + """ + if policies is None: + policies = DEFAULT_TURN_POLICIES + handler._turn_policies = list(policies)