From e4a65e511777eaaa9e1c42b9ad145ac20f6f2c08 Mon Sep 17 00:00:00 2001 From: Val-sss <154882199@qq.com> Date: Thu, 7 May 2026 14:20:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AD=98=E6=A0=B9=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E4=B8=89=E4=B8=AA=E6=A0=B9=E6=9C=AC=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. gap_detector: TypeError/takes no arguments也识别为stub_returns_none (之前只匹配assert None==和NoneType,漏掉了TypeError模式) 2. generator: 逐函数patch全失败时fallback到whole_file路径 (之前返回None导致patches=0) 3. generator: codegen路径文件已存在时走whole_file覆盖 (之前生成pipeline_1.py,测试跑的还是原文件) Co-Authored-By: Claude Opus 4.6 (1M context) --- kaiwu/core/gap_detector.py | 7 +++++++ kaiwu/experts/generator.py | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/kaiwu/core/gap_detector.py b/kaiwu/core/gap_detector.py index b5ba9cd..97c184e 100644 --- a/kaiwu/core/gap_detector.py +++ b/kaiwu/core/gap_detector.py @@ -134,6 +134,13 @@ class GapDetector: none_calls = len(re.findall(r'where None = \w+\(', output)) if none_calls >= 2: return True + # 扩展模式:TypeError: XxxClass() takes no arguments(pass的__init__被调用) + if 'TypeError' in output and 'takes no arguments' in output: + return True + # 扩展模式:多个TypeError(存根类被实例化/调用) + type_errors = len(re.findall(r'TypeError:', output)) + if type_errors >= 3: + return True return False def _all_passed(self, output: str) -> bool: diff --git a/kaiwu/experts/generator.py b/kaiwu/experts/generator.py index 6eacf80..5009335 100644 --- a/kaiwu/experts/generator.py +++ b/kaiwu/experts/generator.py @@ -297,8 +297,9 @@ class GeneratorExpert: explanation_parts.append(f"{fpath}:{func_name}") if not patches: - logger.warning("Generator: no patches produced") - return None + # Fallback: 逐函数patch全失败时,尝试whole_file路径 + logger.warning("Generator: no patches produced, trying whole_file fallback") + return self._run_whole_file(ctx, files) result = { "patches": patches, @@ -570,15 +571,14 @@ class GeneratorExpert: import os full_path = os.path.join(ctx.project_root, target_file) - # 防止覆盖已有文件:如果文件已存在,加数字后缀 + # 如果文件已存在,走whole_file覆盖(不生成_1.py) if os.path.exists(full_path): - base, ext = os.path.splitext(target_file) - for i in range(1, 100): - candidate = f"{base}_{i}{ext}" - if not os.path.exists(os.path.join(ctx.project_root, candidate)): - target_file = candidate - full_path = os.path.join(ctx.project_root, candidate) - break + result = { + "patches": [{"file": target_file, "content": code, "write_mode": "whole_file"}], + "explanation": f"已覆盖:{target_file}", + } + ctx.generator_output = result + return result result = { "patches": [{"file": target_file, "original": "", "modified": code}],