@@ -93,6 +93,8 @@ def __init__(
9393
9494 # 编译错误计数(防止在编译错误上无限循环)
9595 self ._compile_fix_count : int = 0
96+ # LeetCode 验证失败修复计数
97+ self ._leetcode_fix_count : int = 0
9698
9799 def _load_env (self ) -> None :
98100 """加载环境变量"""
@@ -285,12 +287,13 @@ def _init_conversation(self, problem_id: int, is_daily: bool) -> None:
285287 ]
286288 self ._current_reasoning = ""
287289 self ._compile_fix_count = 0 # 重置编译错误计数
290+ self ._leetcode_fix_count = 0 # 重置 LeetCode 修复计数
288291
289292 def _run_conversation_loop (self ) -> bool :
290293 """运行对话循环
291294
292295 Returns:
293- bool: 是否成功完成解题
296+ bool: 是否成功完成解题(包括本地测试通过和 LeetCode 验证通过)
294297 """
295298 model_name = self .provider .model
296299 self ._print_model_info (model_name )
@@ -317,14 +320,34 @@ def _run_conversation_loop(self) -> bool:
317320 handle_elapsed = time .time () - handle_start
318321 log_with_time (f"🛠️ 工具执行完成 ({ handle_elapsed :.1f} s)" , ColorCode .CYAN )
319322 else :
320- # 没有工具调用,解题完成
323+ # 没有工具调用,表示 AI 认为解题完成
321324 round_elapsed = time .time () - round_start
322325 log_with_time (f"✅ 第 { iteration + 1 } 轮完成 ({ round_elapsed :.1f} s)" , ColorCode .GREEN )
323326 self ._print_completion (message )
324327 self ._generate_solution_report ()
328+
325329 # 自动提交到 LeetCode 验证
326- self ._submit_to_leetcode ()
327- return True
330+ leetcode_success , feedback = self ._submit_to_leetcode ()
331+
332+ if leetcode_success :
333+ # 验证通过,解题成功
334+ return True
335+
336+ # LeetCode 验证失败,需要继续修复
337+ self ._leetcode_fix_count += 1
338+ max_leetcode_fix = getattr (AIConfig , 'MAX_LEETCODE_FIX_ATTEMPTS' , 3 )
339+
340+ if self ._leetcode_fix_count >= max_leetcode_fix :
341+ log_with_time (f"⚠️ 达到 LeetCode 验证失败最大修复次数 ({ max_leetcode_fix } ),停止修复" , ColorCode .YELLOW )
342+ return False
343+
344+ log_with_time (f"🔧 LeetCode 验证失败,开始第 { self ._leetcode_fix_count } /{ max_leetcode_fix } 次修复尝试..." , ColorCode .YELLOW )
345+
346+ # 将错误反馈添加到对话,让 AI 继续修复
347+ self .messages .append ({"role" : "user" , "content" : feedback })
348+
349+ # 继续下一轮对话进行修复
350+ continue
328351
329352 # 达到最大迭代次数
330353 log_with_time ("⚠️ 达到最大迭代次数,停止处理" , ColorCode .YELLOW )
@@ -671,174 +694,121 @@ def _print_model_info(self, model_name: str) -> None:
671694 else :
672695 log_with_time (f"💬 使用 { model_name } 模型" , ColorCode .CYAN )
673696
674- def _submit_to_leetcode (self ) -> bool :
697+ def _submit_to_leetcode (self ) -> tuple [ bool , Optional [ str ]] :
675698 """本地测试通过后,提交到 LeetCode 验证
676699
677700 Returns:
678- bool: 是否通过 LeetCode 验证
701+ tuple[bool, Optional[str]]: (是否通过验证, 错误反馈信息用于AI修复)
702+ - 通过验证: (True, None)
703+ - 未通过验证: (False, 错误反馈信息)
704+ - 无 Cookie 跳过验证: (True, None)
679705 """
680706 if not self .problem_id :
681- return False
707+ return False , "无法获取题目 ID"
682708
683709 # 检查是否有 LEETCODE_COOKIE
684710 if not os .getenv ("LEETCODE_COOKIE" ):
685711 print ()
686712 print (color_text ("💡 提示: 设置 LEETCODE_COOKIE 后可自动提交到 LeetCode 验证" , ColorCode .CYAN .value ))
687- return True # 返回 True 表示本地已通过
713+ return True , None # 返回 True 表示本地已通过
688714
689- max_retries = AIConfig .LEETCODE_SUBMIT_MAX_RETRIES
690- for attempt in range (max_retries ):
691- print ()
692- log_with_time (f"🌐 第 { attempt + 1 } /{ max_retries } 次提交到 LeetCode 验证..." , ColorCode .CYAN )
693-
694- try :
695- # 导入提交模块
696- from script .leetcode .submit import LeetCodeSubmitter
697-
698- submitter = LeetCodeSubmitter ()
699- # 提交并获取详细结果
700- result = submitter .submit_problem_with_result (self .problem_id , solution_num = 1 )
701-
702- if result .status == "Accepted" :
703- log_with_time ("✅ LeetCode 验证通过!" , ColorCode .GREEN )
704- return True
705-
706- # 处理不同类型的失败
707- if result .status == "Wrong Answer" and result .failed_test_case :
708- log_with_time (f"❌ Wrong Answer (测试用例 { result .passed_test_cases + 1 } /{ result .total_test_cases } )" , ColorCode .RED )
709-
710- # 获取失败信息
711- failed = result .failed_test_case
712- log_with_time ("\n 失败的测试用例:" , ColorCode .YELLOW )
713- log_with_time (f"输入: { failed .get ('input' , 'N/A' )[:200 ]} ..." )
714- log_with_time (f"输出: { failed .get ('actual' , 'N/A' )[:200 ]} ..." )
715- log_with_time (f"期望: { failed .get ('expected' , 'N/A' )[:200 ]} ..." )
716-
717- # 更新本地测试用例并修复
718- if attempt < max_retries - 1 :
719- log_with_time ("🔧 更新本地测试用例并修复代码..." , ColorCode .YELLOW )
720- if self ._fix_with_leetcode_test_case (failed ):
721- log_with_time ("✅ 代码修复完成,重新提交..." , ColorCode .GREEN )
722- continue
723- else :
724- log_with_time ("❌ 自动修复失败" , ColorCode .RED )
725- return False
726-
727- elif result .status == "Runtime Error" :
728- log_with_time (f"💥 Runtime Error: { result .error_message } " , ColorCode .RED )
729- if attempt < max_retries - 1 :
730- log_with_time ("🔧 尝试修复运行时错误..." , ColorCode .YELLOW )
731- if self ._fix_runtime_error (result .error_message ):
732- continue
733- return False
734-
735- elif result .status == "Time Limit Exceeded" :
736- log_with_time ("⏱️ Time Limit Exceeded" , ColorCode .YELLOW )
737- return False
738-
739- else :
740- log_with_time (f"❌ { result .status } " , ColorCode .RED )
741- return False
742-
743- except Exception as e :
744- log_with_time (f"⚠️ 提交到 LeetCode 时出错: { e } " , ColorCode .YELLOW )
745- return False
715+ print ()
716+ log_with_time ("🌐 正在提交到 LeetCode 验证..." , ColorCode .CYAN )
746717
747- return False
748-
749- def _fix_with_leetcode_test_case (self , failed_test_case : Dict ) -> bool :
750- """使用 LeetCode 失败的测试用例修复代码"""
751718 try :
752- # 构建修复提示
753- fix_prompt = f"""本地测试已通过,但 LeetCode 提交失败。
754-
755- 失败的测试用例:
756- - 输入: { failed_test_case .get ('input' , 'N/A' )}
757- - 输出: { failed_test_case .get ('actual' , 'N/A' )}
758- - 期望: { failed_test_case .get ('expected' , 'N/A' )}
759-
760- 请按以下步骤修复:
761-
762- **步骤 1: 添加失败的测试用例**
763- 使用 `append_test_case` 工具将此测试用例添加到本地测试文件。
764- test_name 建议使用 "WrongAnswerCase1" 或描述性名称如 "EdgeCaseEmptyArray"
765- test_code 格式示例(注意缩进为2个空格):
766- ```
767- // 输入: nums = [1,2,3], target = 4
768- // 期望: [0,1]
769- vector<int> nums = {{1, 2, 3}};
770- int target = 4;
771- vector<int> expected = {{0, 1}};
772- vector<int> result = solution.twoSum(nums, target);
773- EXPECT_EQ(expected, result);
774- ```
775-
776- **步骤 2: 分析并修复**
777- 使用 `retrieve_file_content` 查看当前代码,分析失败原因,然后使用 `create_or_update_file` 修复源文件中的问题。
778-
779- **步骤 3: 验证**
780- 调用 `compile_and_test` 确保修复后的代码通过所有测试。
781-
782- 请开始修复。"""
783-
784- # 添加修复提示到对话
785- self .messages .append ({"role" : "user" , "content" : fix_prompt })
719+ # 导入提交模块
720+ from script .leetcode .submit import LeetCodeSubmitter
786721
787- # 运行一轮对话让 AI 修复
788- message = self . _call_api ( self . provider . model )
789- self . messages . append (self ._build_message_to_save ( message ) )
722+ submitter = LeetCodeSubmitter ()
723+ # 提交并获取详细结果
724+ result = submitter . submit_problem_with_result (self .problem_id , solution_num = 1 )
790725
791- if message .tool_calls :
792- self ._handle_tool_calls (message .tool_calls )
793- # 修复后需要验证编译和测试是否通过
794- log_with_time ("🔍 验证修复结果..." , ColorCode .CYAN )
795- result = self .tool_executor .execute ("compile_and_test" , {"problem_id" : self .problem_id })
796- if not result .get ("is_successful" ):
797- log_with_time ("❌ 修复未完成" , ColorCode .RED )
798- return False
799- log_with_time ("✅ 编译和测试通过" , ColorCode .GREEN )
800- return True
801-
802- return False
726+ if result .status == "Accepted" :
727+ log_with_time ("✅ LeetCode 验证通过!" , ColorCode .GREEN )
728+ return True , None
803729
730+ # 构建错误反馈信息用于 AI 修复
731+ feedback = self ._build_leetcode_error_feedback (result )
732+ return False , feedback
733+
804734 except Exception as e :
805- print (color_text (f"修复过程出错: { e } " , ColorCode .RED .value ))
806- return False
735+ error_msg = f"提交到 LeetCode 时出错: { e } "
736+ log_with_time (f"⚠️ { error_msg } " , ColorCode .YELLOW )
737+ return False , error_msg
807738
808- def _fix_runtime_error (self , error_message : str ) -> bool :
809- """修复运行时错误"""
810- try :
811- fix_prompt = f"""代码出现 Runtime Error:
812-
813- 错误信息:
814- { error_message }
815-
816- 请:
817- 1. 分析错误原因(数组越界?空指针?除以零?)
818- 2. 使用 `retrieve_file_content` 查看代码
819- 3. 修复问题并调用 `compile_and_test` 验证"""
820-
821- self .messages .append ({"role" : "user" , "content" : fix_prompt })
822-
823- message = self ._call_api (self .provider .model )
824- self .messages .append (self ._build_message_to_save (message ))
739+ def _build_leetcode_error_feedback (self , result ) -> str :
740+ """根据 LeetCode 返回结果构建 AI 修复提示"""
741+ from script .leetcode .submit import SubmissionResult
742+
743+ lines = ["LeetCode 提交失败,需要修复。" , "" ]
744+
745+ if result .status == "Wrong Answer" :
746+ lines .append (f"❌ Wrong Answer (通过了 { result .passed_test_cases } /{ result .total_test_cases } 个测试用例)" )
747+ lines .append ("" )
748+ if result .failed_test_case :
749+ failed = result .failed_test_case
750+ lines .append ("失败的测试用例:" )
751+ lines .append (f"- 输入: { failed .get ('input' , 'N/A' )} " )
752+ lines .append (f"- 输出: { failed .get ('actual' , 'N/A' )} " )
753+ lines .append (f"- 期望: { failed .get ('expected' , 'N/A' )} " )
754+ lines .append ("" )
755+ lines .append ("请按以下步骤修复:" )
756+ lines .append ("" )
757+ lines .append ("**步骤 1: 添加失败的测试用例到本地**" )
758+ lines .append ("使用 `append_test_case` 工具将此测试用例添加到本地测试文件。" )
759+ lines .append ("test_name 建议使用描述性名称如 'WrongAnswerCase1' 或 'EdgeCaseEmptyArray'" )
760+ lines .append ("test_code 格式示例(注意缩进为2个空格):" )
761+ lines .append ("```" )
762+ lines .append (" // 输入: nums = [1,2,3], target = 4" )
763+ lines .append (" // 期望: [0,1]" )
764+ lines .append (" vector<int> nums = {{1, 2, 3}};" )
765+ lines .append (" int target = 4;" )
766+ lines .append (" vector<int> expected = {{0, 1}};" )
767+ lines .append (" vector<int> result = solution.twoSum(nums, target);" )
768+ lines .append (" EXPECT_EQ(expected, result);" )
769+ lines .append ("```" )
770+ lines .append ("" )
771+ lines .append ("**步骤 2: 分析并修复代码**" )
772+ lines .append ("使用 `retrieve_file_content` 查看当前代码,分析失败原因," )
773+ lines .append ("然后使用 `create_or_update_file` 修复源文件中的问题。" )
774+ lines .append ("" )
775+ lines .append ("**步骤 3: 验证修复**" )
776+ lines .append ("调用 `compile_and_test` 确保修复后的代码通过所有测试。" )
777+
778+ elif result .status == "Runtime Error" :
779+ lines .append (f"💥 Runtime Error" )
780+ if result .error_message :
781+ lines .append (f"错误信息: { result .error_message } " )
782+ lines .append ("" )
783+ lines .append ("请分析错误原因(数组越界?空指针?除以零?),然后:" )
784+ lines .append ("1. 使用 `retrieve_file_content` 查看代码" )
785+ lines .append ("2. 修复问题并使用 `create_or_update_file` 更新代码" )
786+ lines .append ("3. 调用 `compile_and_test` 验证修复" )
825787
826- if message .tool_calls :
827- self ._handle_tool_calls (message .tool_calls )
828- # 修复后需要验证编译和测试是否通过
829- log_with_time ("🔍 验证修复结果..." , ColorCode .CYAN )
830- result = self .tool_executor .execute ("compile_and_test" , {"problem_id" : self .problem_id })
831- if not result .get ("is_successful" ):
832- log_with_time ("❌ 修复未完成" , ColorCode .RED )
833- return False
834- log_with_time ("✅ 编译和测试通过" , ColorCode .GREEN )
835- return True
788+ elif result .status == "Time Limit Exceeded" :
789+ lines .append ("⏱️ Time Limit Exceeded" )
790+ lines .append ("" )
791+ lines .append ("算法时间复杂度过高,请考虑:" )
792+ lines .append ("1. 优化算法(例如使用更高效的数据结构)" )
793+ lines .append ("2. 减少冗余计算" )
794+ lines .append ("3. 使用 `retrieve_file_content` 查看当前实现并改进" )
836795
837- return False
796+ elif result .status == "Compile Error" :
797+ lines .append ("❌ Compile Error" )
798+ if result .error_message :
799+ lines .append (f"编译错误信息: { result .error_message } " )
800+ lines .append ("" )
801+ lines .append ("请检查代码语法并修复编译错误。" )
838802
839- except Exception as e :
840- log_with_time (f"修复运行时错误出错: { e } " , ColorCode .RED )
841- return False
803+ else :
804+ lines .append (f"❌ { result .status } " )
805+ if result .error_message :
806+ lines .append (f"错误信息: { result .error_message } " )
807+
808+ lines .append ("" )
809+ lines .append ("请开始修复。" )
810+
811+ return "\n " .join (lines )
842812
843813 @staticmethod
844814 def _get_system_prompt () -> str :
0 commit comments