@@ -7,6 +7,7 @@ use tokio::process::Command;
77
88use crate :: safeoutputs:: { ExecutionContext , ExecutionResult , Executor , ToolResult , Validate } ;
99use crate :: sanitize:: { Sanitize , sanitize as sanitize_text} ;
10+ use crate :: tool_result;
1011use anyhow:: { Context , ensure} ;
1112
1213/// Maximum allowed patch file size (5 MB)
@@ -256,41 +257,56 @@ impl Validate for CreatePrParams {
256257 }
257258}
258259
259- /// Result of creating a pull request - stored as safe output
260- #[ derive( Debug , serde:: Serialize , serde:: Deserialize , schemars:: JsonSchema ) ]
261- pub struct CreatePrResult {
262- /// Tool identifier
263- pub name : String ,
264- /// Title for the pull request
265- pub title : String ,
266- /// Description/body of the pull request (markdown)
267- pub description : String ,
268- /// Source branch name (generated or provided)
269- pub source_branch : String ,
270- /// Path to the patch file in the safe outputs directory
271- pub patch_file : String ,
272- /// Repository alias ("self" or alias from checkout list)
273- pub repository : String ,
274- /// Agent-provided labels (validated against allowed-labels at execution time)
260+ /// Internal params struct mirroring CreatePrResult fields for the tool_result! macro.
261+ /// The actual MCP parameters come from CreatePrParams; this struct enables the macro's
262+ /// TryFrom generation while CreatePrResult is constructed via CreatePrResult::new().
263+ #[ derive( Deserialize , JsonSchema ) ]
264+ struct CreatePrResultFields {
265+ title : String ,
266+ description : String ,
267+ source_branch : String ,
268+ patch_file : String ,
269+ repository : String ,
275270 #[ serde( default ) ]
276- pub agent_labels : Vec < String > ,
277- /// Base commit SHA recorded at patch generation time (merge-base of HEAD and
278- /// the upstream branch). When present, Stage 2 uses this as the parent commit
279- /// for the ADO Push API, ensuring the patch applies cleanly even if the target
280- /// branch has advanced since the agent ran. Falls back to resolving the live
281- /// target branch HEAD via the ADO refs API when absent (backward compatibility).
282- ///
283- /// Note: this is the merge-base, not the target branch HEAD. The PR diff in ADO
284- /// compares file states and displays correctly regardless; however, the branch
285- /// history shows a parent older than current main. This is normal for topic
286- /// branches and is resolved when the PR is merged.
271+ agent_labels : Vec < String > ,
287272 #[ serde( skip_serializing_if = "Option::is_none" ) ]
288- pub base_commit : Option < String > ,
273+ base_commit : Option < String > ,
289274}
290275
291- impl crate :: safeoutputs:: ToolResult for CreatePrResult {
292- const NAME : & ' static str = "create-pull-request" ;
293- const REQUIRES_WRITE : bool = true ;
276+ impl Validate for CreatePrResultFields { }
277+
278+ tool_result ! {
279+ name = "create-pull-request" ,
280+ write = true ,
281+ params = CreatePrResultFields ,
282+ /// Result of creating a pull request - stored as safe output
283+ pub struct CreatePrResult {
284+ /// Title for the pull request
285+ title: String ,
286+ /// Description/body of the pull request (markdown)
287+ description: String ,
288+ /// Source branch name (generated or provided)
289+ source_branch: String ,
290+ /// Path to the patch file in the safe outputs directory
291+ patch_file: String ,
292+ /// Repository alias ("self" or alias from checkout list)
293+ repository: String ,
294+ /// Agent-provided labels (validated against allowed-labels at execution time)
295+ #[ serde( default ) ]
296+ agent_labels: Vec <String >,
297+ /// Base commit SHA recorded at patch generation time (merge-base of HEAD and
298+ /// the upstream branch). When present, Stage 2 uses this as the parent commit
299+ /// for the ADO Push API, ensuring the patch applies cleanly even if the target
300+ /// branch has advanced since the agent ran. Falls back to resolving the live
301+ /// target branch HEAD via the ADO refs API when absent (backward compatibility).
302+ ///
303+ /// Note: this is the merge-base, not the target branch HEAD. The PR diff in ADO
304+ /// compares file states and displays correctly regardless; however, the branch
305+ /// history shows a parent older than current main. This is normal for topic
306+ /// branches and is resolved when the PR is merged.
307+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
308+ base_commit: Option <String >,
309+ }
294310}
295311
296312impl Sanitize for CreatePrResult {
0 commit comments