You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ReplaceText always performs replacements against OriginalText and then assigns to ModifiedText, which means multiple tool calls will not compose (a second replacement can overwrite/lose changes from the first one). Consider applying replacements on ModifiedText (current state) to support incremental edits as intended by the agent instructions.
[KernelFunction("replace_text")][Description("Replaces a chunk of text of the provided content with new text."+" Returns information if the text was not found or if the replacement was successful.")]publicstringReplaceText([Description("The exact text chunk to find and replace")]stringoldText,[Description("The new text to replace it with")]stringnewText){if(string.IsNullOrEmpty(OriginalText)||string.IsNullOrEmpty(oldText))return"No text to replace.";if(!OriginalText.Contains(oldText))return"[WARN] The specified text was not found in the content. No changes made.";ModifiedText=OriginalText.Replace(oldText,newText);return"Success";
The modal sets isWorking = true before sending the request, but the new flow doesn’t set isWorking = false after Mediator.Send(...) completes (both for success and error paths). This can leave the modal permanently disabled/spinning.
StateHasChanged();
var message = new DuplicateCv.Request(OriginCvId, NewCvName, TargetOfferUrl);
var response = await Mediator.Send(message);
if (response.IsError)
{
After deleting the CV, navigation uses /?offerUrl={offer} which likely interpolates the UserOffer object rather than a stable identifier (e.g., offer.OfferUrl). This can produce an invalid URL and break redirect behavior. Also consider disposing the imported JS module to avoid leaking JS object references.
privateasyncTaskDeleteCvAsync(){varconfirmation=awaitdialog.ShowAsync(title:"Are you sure you want to delete this?",message1:"This will delete the record. Once deleted can not be rolled back.",message2:"Do you want to proceed?");if(!confirmation)return;varcv=awaitdbContext.Cvs.FindAsync(cvEntity.Id);if(cvisnull)return;dbContext.Remove(cv);awaitdbContext.SaveChangesAsync();navigationManager.NavigateTo($"/?offerUrl={offer}");}privatevoidGoToCv(longduplicatedCvId)=>navigationManager.NavigateTo($"cv/edit/{duplicatedCvId}",true);privateenumCompareMode{None,WithSaved,WithOrigin,}publicboolDisableCompareToOrigin=>
compareMode is CompareMode.WithOrigin ||string.IsNullOrWhiteSpace(cvEntity?.OriginCv?.MarkdownContent);privateasyncTaskCompareToOrigin(){ArgumentException.ThrowIfNullOrWhiteSpace(cvEntity?.OriginCv?.MarkdownContent);compareMode=CompareMode.WithOrigin;originalContent=cvEntity?.OriginCv?.MarkdownContent!;awaitdiffEditor!.SetOriginalModel(cvEntity!.OriginCv!.MarkdownContent);}publicboolDisableCompareToSaved=> compareMode is CompareMode.WithSaved;privateasyncTaskCompareToSaved(){ArgumentException.ThrowIfNullOrWhiteSpace(cvEntity?.MarkdownContent);compareMode=CompareMode.WithSaved;originalContent=cvEntity?.MarkdownContent!;awaitdiffEditor!.SetOriginalModel(cvEntity!.MarkdownContent);}privateboolPreventNavigation=> isWorking || dbContext.Entry(cvEntity).State == EntityState.Modified;privateasyncTaskOnBeforeInternalNavigation(LocationChangingContextctx){if(!PreventNavigation)return;varconfirm=awaitjs.InvokeAsync<bool>("confirm","Are you sure you want to leave this page?");if(!confirm)ctx.PreventNavigation();}publicasyncValueTaskDisposeAsync(){await_cts.CancelAsync();_cts.Dispose();if(downloadModuleis not null)awaitdownloadModule.DisposeAsync();}
Resetting isWorking was removed after sending the request, which can leave the modal stuck in a “working” state forever. Wrap the send in try/finally (or set isWorking = false immediately after) to guarantee UI state is restored even on exceptions.
isWorking = true;
StateHasChanged();
var message = new DuplicateCv.Request(OriginCvId, NewCvName, TargetOfferUrl);
-var response = await Mediator.Send(message);+ErrorOr<DuplicateCv.Response> response;++try+{+ response = await Mediator.Send(message);+}+finally+{+ isWorking = false;+ StateHasChanged();+}
if (response.IsError)
{
toasts.PushMessage(response.FirstError.Description, ToastType.Warning);
Suggestion importance[1-10]: 8
__
Why: In DuplicateCvModal.razor, isWorking is set to true and never reset, so the modal can remain stuck in a busy/disabled state. Wrapping Mediator.Send(...) with try/finally (or resetting immediately after) is a correctness/UX fix and prevents permanent lock-up even on exceptions.
Medium
Apply edits cumulatively
ReplaceText currently searches and replaces against OriginalText, so multiple tool calls will overwrite prior edits and lose changes. Apply replacements to ModifiedText (and check existence there) so successive edits accumulate correctly.
-if (string.IsNullOrEmpty(OriginalText) || string.IsNullOrEmpty(oldText))+if (string.IsNullOrEmpty(ModifiedText) || string.IsNullOrEmpty(oldText))
return "No text to replace.";
-if (!OriginalText.Contains(oldText))+if (!ModifiedText.Contains(oldText))
return "[WARN] The specified text was not found in the content. No changes made.";
-ModifiedText = OriginalText.Replace(oldText, newText);+ModifiedText = ModifiedText.Replace(oldText, newText);
return "Success";
Suggestion importance[1-10]: 8
__
Why: ReplaceTextPlugin.ReplaceText currently replaces against OriginalText, so multiple replace_text tool calls will overwrite previous changes instead of accumulating edits. Switching the search/replace base to ModifiedText makes the tool behave correctly for iterative modifications.
Medium
Prevent infinite model loops
This loop can run indefinitely if the model never includes DoneSignal, causing a hang until external cancellation. Add an explicit iteration limit (and/or check ct.IsCancellationRequested) and fail gracefully when exceeded.
var lastResponse = "";
-do+const int maxIterations = 5;++for (var i = 0; i < maxIterations; i++)+{
await foreach (var response in agent.InvokeAsync(chatHistory, cancellationToken: ct))
lastResponse = response.Message.Content ?? "";
-while (!lastResponse.Contains(DoneSignal));+ if (lastResponse.Contains(DoneSignal))+ break;+}++if (!lastResponse.Contains(DoneSignal))+ return new Response(false, null, chatHistory.Select(ChatItem.From).ToList());+
Suggestion importance[1-10]: 6
__
Why: The do/while loop waits indefinitely for DoneSignal, which can hang if the model never emits it (until external cancellation). Adding a maximum iteration limit (and failing gracefully) improves robustness without changing the intended flow.
Low
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.