Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,32 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
string? apiViewUrl = IsApiViewUrl(customizationRequest) ? customizationRequest : null;

var languageService = await ResolveLanguageServiceAsync(packagePath, apiViewUrl, ct);
PackageInfo? packageInfo = null;

try
{
packageInfo = await languageService.GetPackageInfo(packagePath, ct);
}
catch (OperationCanceledException) when (ct.IsCancellationRequested)
{
throw;
}
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to resolve package info for {PackagePath}", packagePath);
}
Comment thread
samvaity marked this conversation as resolved.

CustomizedCodeUpdateResponse CreateResponse(CustomizedCodeUpdateResponse response)
{
response.PackageName ??= packageInfo?.PackageName;
response.Language = packageInfo?.Language ?? languageService.Language;
response.PackageType = packageInfo?.SdkType ?? SdkType.Unknown;
Comment on lines +206 to +210
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in commit 1ba4648. The remainder of RunUpdateAsync (after languageService/packageInfo are resolved and CreateResponse is defined) is now wrapped in an outer try/catch that:

  • Rethrows OperationCanceledException to honor cancellation
  • Returns CreateResponse(...) with enriched package/language metadata for any unexpected errors from downstream operations (regen, build, second classification pass, patching, etc.)

Also fixed the GetPackageInfo catch block (the first reviewer comment) to include catch (OperationCanceledException) when (ct.IsCancellationRequested) { throw; } before the broad catch so cancellation isn't swallowed there either.

response.TypeSpecProject ??= packageInfo?.SpecProjectPath ?? tspProjectPath;
return response;
}

try
{
List<FeedbackItem> feedbackItems = [];
FeedbackClassificationResponse response;
try
Expand All @@ -205,38 +230,38 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
catch (CopilotCliUnavailableException ex)
{
logger.LogError(ex, "GitHub Copilot CLI is not available.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = ex.Message,
Message = ex.Message,
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.UnexpectedError,
BuildResult = ex.Message
};
});
}
catch (ArgumentException ex)
{
logger.LogError(ex, "Invalid input for feedback classification.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = ex.Message,
Message = ex.Message,
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.InvalidInput,
BuildResult = ex.Message
};
});
}
catch (Exception ex)
{
logger.LogError(ex, "Feedback classification failed unexpectedly.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = $"Feedback classification failed: {ex.Message}",
Message = $"Feedback classification failed: {ex.Message}",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.UnexpectedError,
BuildResult = $"Feedback classification failed: {ex.Message}"
};
});
}
var feedbackDictionary = feedbackItems.ToDictionary(i => i.Id, i => i);

Expand All @@ -249,14 +274,14 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa

if (response.Classifications == null || response.Classifications.Count == 0)
{
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
Comment thread
samvaity marked this conversation as resolved.
ResponseError = "Feedback could not be classified.",
Message = "Feedback could not be classified.",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.InvalidInput,
BuildResult = "Feedback could not be classified."
};
});
}

var tspFixFailed = 0;
Expand Down Expand Up @@ -325,23 +350,23 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
// Nothing was classified as tsp applicable and at least some feedback requires manual intervention
if (tspApplicable == 0 && codeCustomizations == 0 && manualChanges > 0)
{
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
Message = "The requested changes require manual intervention and cannot be applied via TypeSpec customizations.",
NextSteps = manualInterventions,
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.ManualInterventionRequired
};
});
}

// Everything was classified as success
if (tspApplicable == 0 && codeCustomizations == 0 && noChanges > 0)
{
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = true,
Message = "No changes needed — the requested customizations are already in place."
};
});
}

// ── Regen + Build if TSP fixes were applied ──
Expand Down Expand Up @@ -371,7 +396,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
if (buildSucceeded && codeCustomizations == 0)
{
logger.LogInformation("Build passed after TypeSpec customizations.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = manualInterventions.Count == 0,
Message = manualInterventions.Count == 0
Expand All @@ -380,7 +405,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
TypeSpecChangesSummary = changesMade,
NextSteps = manualInterventions,
ErrorCode = manualInterventions.Count > 0 ? CustomizedCodeUpdateResponse.KnownErrorCodes.ManualInterventionRequired : null,
};
});
}

// Enrich remaining items with build error context for the second classifier pass
Expand Down Expand Up @@ -437,7 +462,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
if (buildSucceeded && codeCustomizations == 0)
{
logger.LogInformation("Build passed after TypeSpec customizations.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = manualInterventions.Count == 0,
Message = manualInterventions.Count == 0
Expand All @@ -446,29 +471,29 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
TypeSpecChangesSummary = changesMade,
NextSteps = manualInterventions,
ErrorCode = manualInterventions.Count > 0 ? CustomizedCodeUpdateResponse.KnownErrorCodes.ManualInterventionRequired : null,
};
});
}

// Step 2: If the build failed or CODE_CUSTOMIZATION items still need patching, start customized code update process

if (!languageService.IsCustomizedCodeUpdateSupported)
{
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = "Language service does not support customized code updates.",
Message = "Language service does not support customized code updates.",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.NoLanguageService,
BuildResult = "No language service available for this package type."
};
});
}

// Step 3: Check for customization files to repair
var customizationRoot = languageService.HasCustomizations(packagePath, ct);
if (customizationRoot == null)
{
logger.LogInformation("Build failed but no customization files found.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = string.IsNullOrWhiteSpace(buildError)
Expand All @@ -477,7 +502,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
Message = "Build failed but no customization files found to repair.",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.BuildNoCustomizationsFailed,
BuildResult = buildError
};
});
}

// Step 4: Apply patches based on build errors
Expand All @@ -498,7 +523,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
if (patches.Count == 0)
{
logger.LogInformation("No patches applied.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = string.IsNullOrWhiteSpace(buildError)
Expand All @@ -507,7 +532,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
Message = "No patches could be applied - automated repair found nothing to fix.",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.PatchesFailed,
BuildResult = buildError
};
});
}

// Step 5: Regenerate if Java (only Java needs regen after patching customization files)
Expand All @@ -518,7 +543,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
if (!regenResult.IsSuccessful)
{
logger.LogWarning("Regeneration failed: {Error}", regenResult.ResponseError);
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = $"Regeneration failed after patches: {regenResult.ResponseError}",
Expand All @@ -527,7 +552,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
BuildResult = regenResult.ResponseError,
TypeSpecChangesSummary = changesMade,
AppliedPatches = patches
};
});
}
}

Expand All @@ -538,7 +563,7 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
if (finalBuildSuccess)
{
logger.LogInformation("Build passed after code customization patches.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = manualInterventions.Count == 0,
Message = manualInterventions.Count == 0
Expand All @@ -548,12 +573,12 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
AppliedPatches = patches,
NextSteps = manualInterventions,
ErrorCode = manualInterventions.Count > 0 ? CustomizedCodeUpdateResponse.KnownErrorCodes.ManualInterventionRequired : null,
};
});
}

// Build still failing after patches
logger.LogInformation("Build still failing after code customization patches.");
return new CustomizedCodeUpdateResponse
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = string.IsNullOrWhiteSpace(finalBuildError)
Expand All @@ -565,7 +590,24 @@ private async Task<CustomizedCodeUpdateResponse> RunUpdateAsync(string packagePa
TypeSpecChangesSummary = changesMade,
AppliedPatches = patches,
NextSteps = manualInterventions,
};
});
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "Unexpected error during customized code update.");
return CreateResponse(new CustomizedCodeUpdateResponse
{
Success = false,
ResponseError = $"Unexpected error: {ex.Message}",
Message = $"Unexpected error: {ex.Message}",
ErrorCode = CustomizedCodeUpdateResponse.KnownErrorCodes.UnexpectedError,
BuildResult = ex.Message
});
}
}

/// <summary>
Expand Down