@@ -34,4 +34,85 @@ class UnitTestCodingComponent(BaseComponent[CodeUnitTestRequest, CodeUnitTestOut
34
34
def invoke (
35
35
self , request : CodeUnitTestRequest , llm_client : LlmClient = injected
36
36
) -> CodeUnitTestOutput | None :
37
- pass
37
+ with BaseTools (self .context , repo_client_type = RepoClientType .CODECOV_UNIT_TEST ) as tools :
38
+ agent = LlmAgent (
39
+ tools = tools .get_tools (),
40
+ config = AgentConfig (interactive = False ),
41
+ )
42
+
43
+ codecov_client_params = request .codecov_client_params
44
+
45
+ code_coverage_data = CodecovClient .fetch_coverage (
46
+ repo_name = codecov_client_params ["repo_name" ],
47
+ pullid = codecov_client_params ["pullid" ],
48
+ owner_username = codecov_client_params ["owner_username" ],
49
+ )
50
+
51
+ test_result_data = CodecovClient .fetch_test_results_for_commit (
52
+ repo_name = codecov_client_params ["repo_name" ],
53
+ owner_username = codecov_client_params ["owner_username" ],
54
+ latest_commit_sha = codecov_client_params ["head_sha" ],
55
+ )
56
+
57
+ existing_test_design_response = llm_client .generate_text (
58
+ model = AnthropicProvider .model ("claude-3-7-sonnet@20250219" ),
59
+ prompt = CodingUnitTestPrompts .format_find_unit_test_pattern_step_msg (
60
+ diff_str = request .diff
61
+ ),
62
+ )
63
+
64
+ llm_client .generate_text (
65
+ model = AnthropicProvider .model ("claude-3-7-sonnet@20250219" ),
66
+ prompt = CodingUnitTestPrompts .format_plan_step_msg (
67
+ diff_str = request .diff ,
68
+ has_coverage_info = code_coverage_data ,
69
+ has_test_result_info = test_result_data ,
70
+ ),
71
+ )
72
+
73
+ final_response = agent .run (
74
+ run_config = RunConfig (
75
+ prompt = CodingUnitTestPrompts .format_unit_test_msg (
76
+ diff_str = request .diff , test_design_hint = existing_test_design_response
77
+ ),
78
+ system_prompt = CodingUnitTestPrompts .format_system_msg (),
79
+ model = AnthropicProvider .model ("claude-3-7-sonnet@20250219" ),
80
+ run_name = "Generate Unit Tests" ,
81
+ ),
82
+ )
83
+
84
+ if not final_response :
85
+ return None
86
+ plan_steps_content = extract_text_inside_tags (final_response , "plan_steps" )
87
+
88
+ if len (plan_steps_content ) == 0 :
89
+ raise ValueError ("Failed to extract plan_steps from the planning step of LLM" )
90
+
91
+ coding_output = PlanStepsPromptXml .from_xml (
92
+ f"<plan_steps>{ escape_multi_xml (plan_steps_content , ['diff' , 'description' , 'commit_message' ])} </plan_steps>"
93
+ ).to_model ()
94
+
95
+ if not coding_output .tasks :
96
+ raise ValueError ("No tasks found in coding output" )
97
+ file_changes : list [FileChange ] = []
98
+ for task in coding_output .tasks :
99
+ repo_client = self .context .get_repo_client (
100
+ task .repo_name , type = RepoClientType .CODECOV_UNIT_TEST
101
+ )
102
+ if task .type == "file_change" :
103
+ file_content , _ = repo_client .get_file_content (task .file_path )
104
+ if not file_content :
105
+ logger .warning (f"Failed to get content for { task .file_path } " )
106
+ continue
107
+
108
+ changes , _ = task_to_file_change (task , file_content )
109
+ file_changes += changes
110
+ elif task .type == "file_delete" :
111
+ change = task_to_file_delete (task )
112
+ file_changes .append (change )
113
+ elif task .type == "file_create" :
114
+ change = task_to_file_create (task )
115
+ file_changes .append (change )
116
+ else :
117
+ logger .warning (f"Unsupported task type: { task .type } " )
118
+ return CodeUnitTestOutput (diffs = file_changes )
0 commit comments