Skip to content

fix(routing): normalize function name, fix length-truncated response …#1291

Merged
yileicn merged 2 commits intoSciSharp:masterfrom
yileicn:master
Feb 6, 2026
Merged

fix(routing): normalize function name, fix length-truncated response …#1291
yileicn merged 2 commits intoSciSharp:masterfrom
yileicn:master

Conversation

@yileicn
Copy link
Member

@yileicn yileicn commented Feb 6, 2026

fix(routing): normalize function name, fix length-truncated response handling, add DiagnosticHelper

@qodo-code-review
Copy link

Review Summary by Qodo

Normalize function names, handle length-truncated responses, and add diagnostic utilities

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add NormalizeFunctionName() extension method to handle LLM-generated function names with
  namespace/agent prefixes
• Create DiagnosticHelper utility class for stack trace debugging
• Fix length-truncated response handling across multiple chat completion providers
• Consolidate function name normalization logic across 6 provider implementations
• Improve error logging with diagnostic stack trace information
Diagram
flowchart LR
  A["LLM Response with<br/>Prefixed Function Names"] -->|NormalizeFunctionName| B["Cleaned Function Names"]
  C["Length-Truncated<br/>Responses"] -->|ChatFinishReason.Length| D["Handled with<br/>StopCompletion Flag"]
  E["Function Execution<br/>Failures"] -->|DiagnosticHelper| F["Enhanced Error Logs<br/>with Stack Trace"]
  B --> G["6 Chat Providers<br/>Updated"]
  D --> G
  F --> G
Loading

Grey Divider

File Changes

1. src/Infrastructure/BotSharp.Abstraction/Utilities/DiagnosticHelper.cs ✨ Enhancement +16/-0

Add diagnostic helper for stack trace retrieval

src/Infrastructure/BotSharp.Abstraction/Utilities/DiagnosticHelper.cs


2. src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs ✨ Enhancement +27/-0

Add function name normalization extension method

src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs


3. src/Infrastructure/BotSharp.Core/Routing/Reasoning/ReasonerHelper.cs 🐞 Bug fix +5/-3

Use new function name normalization method

src/Infrastructure/BotSharp.Core/Routing/Reasoning/ReasonerHelper.cs


View more (6)
4. src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs ✨ Enhancement +1/-1

Add diagnostic stack trace to error logging

src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs


5. src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs 🐞 Bug fix +13/-7

Normalize function names and handle length-truncated responses

src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs


6. src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs 🐞 Bug fix +13/-7

Normalize function names and handle length-truncated responses

src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs


7. src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/ChatCompletionProvider.cs 🐞 Bug fix +13/-4

Normalize function names and handle max token responses

src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/ChatCompletionProvider.cs


8. src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs 🐞 Bug fix +8/-10

Normalize function names, fix role type, handle length-truncated responses

src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs


9. src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs 🐞 Bug fix +2/-4

Normalize function names using new extension method

src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 6, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Stack trace logged in error 📘 Rule violation ⛨ Security
Description
• The new error log appends a full stack trace via DiagnosticHelper.GetCurrentStackTrace() when a
  function implementation is missing.
• Stack traces can contain sensitive internal details (method names, paths, code locations) and the
  log line is also unstructured, making it harder to audit safely.
• This increases the risk of sensitive information exposure through logs and reduces log usability
  for monitoring/auditing.
Code

src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs[R19-22]

            message.StopCompletion = true;
            message.Content = $"Can't find function implementation of {name}.";
-            _logger.LogError(message.Content);
+            _logger.LogError($"{message.Content}, stackInfo:{DiagnosticHelper.GetCurrentStackTrace()}");
            return false;
Evidence
PR Compliance ID 5 requires structured logs and prohibits sensitive data in logs. The changed code
explicitly logs a stack trace string (internal implementation detail) inside an interpolated log
message.

Rule 5: Generic: Secure Logging Practices
src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs[19-22]
src/Infrastructure/BotSharp.Abstraction/Utilities/DiagnosticHelper.cs[12-15]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The code logs a full stack trace as part of an interpolated error message. This can leak internal details into logs and is not structured logging.

## Issue Context
Secure logging requires logs to be structured and to avoid sensitive/internal details in log output.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs[19-22]
- src/Infrastructure/BotSharp.Abstraction/Utilities/DiagnosticHelper.cs[12-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Normalization can yield invalid name 🐞 Bug ✓ Correctness
Suggestion Impact:NormalizeFunctionName was updated to Trim() the input, handle both '.' and '/' separators, and avoid returning an empty/whitespace normalized token by falling back to the original functionName instead.

code diff:

# File: src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
@@ -67,25 +67,36 @@
     /// <summary>
     /// Normalizes function name by removing namespace/agent prefixes.
     /// LLM sometimes returns function names like "AgentName.FunctionName" or "Namespace.FunctionName".
-    /// This method extracts the actual function name.
+    /// This method extracts the actual function name. Returns original input if normalization would
+    /// yield empty/whitespace (e.g. "Agent." or "Agent/ ") to avoid downstream invalid function lookup.
     /// </summary>
     /// <param name="functionName">The raw function name from LLM response</param>
-    /// <returns>The normalized function name, or null if input is null/empty</returns>
+    /// <returns>The normalized function name, or original if normalized would be empty/whitespace</returns>
     public static string? NormalizeFunctionName(this string? functionName)
     {
+        functionName = functionName?.Trim();
         if (string.IsNullOrEmpty(functionName))
         {
             return functionName;
         }
 
-        if (functionName.Contains('.'))
+        foreach (var separator in new[] { '.', '/' })
         {
-            return functionName.Split('.').Last();
-        }
+            if (!functionName.Contains(separator))
+            {
+                continue;
+            }
 
-        if (functionName.Contains('/'))
-        {
-            return functionName.Split('/').Last();
+            var segments = functionName.Split(separator);
+            var normalized = segments.LastOrDefault()?.Trim();
+
+            if (string.IsNullOrWhiteSpace(normalized))
+            {
+                return functionName;
+            }
+
+            Console.WriteLine($"NormalizeFunctionName: {functionName} -> {normalized}");
+            return normalized;
         }
 
         return functionName;

Description
NormalizeFunctionName can return empty string or whitespace (e.g., inputs like "Agent." or
  "Agent/ ") because it doesn’t trim or remove empty segments.
• Multiple call sites now assign the normalized value back to FunctionName/args.Function without
  validation, increasing the chance of passing an empty/invalid function name downstream.
• Function execution is resolved by exact name equality; an empty/whitespace name will fail lookup
  and surface as “Can’t find function implementation …”, making failures harder to attribute to
  malformed LLM output.
Code

src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs[R74-89]

+    public static string? NormalizeFunctionName(this string? functionName)
+    {
+        if (string.IsNullOrEmpty(functionName))
+        {
+            return functionName;
+        }
+
+        if (functionName.Contains('.'))
+        {
+            return functionName.Split('.').Last();
+        }
+
+        if (functionName.Contains('/'))
+        {
+            return functionName.Split('/').Last();
+        }
Evidence
The normalization logic returns the last split segment without trimming or excluding empties. The
routing/execution layer matches function names using exact equality, so invalid normalized names
will not resolve to an executor.

src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs[74-92]
src/Infrastructure/BotSharp.Core/Routing/Executor/FunctionExecutorFactory.cs[8-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`NormalizeFunctionName` can normalize malformed names into empty/whitespace strings (e.g., trailing `.` or `/`, leading/trailing spaces). Those values then fail downstream exact-match lookups for executors.

## Issue Context
Function execution is resolved via `x.Name == functionName` (exact equality). Call sites now overwrite the function name with the normalized value without validating it.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs[74-92]
- src/Infrastructure/BotSharp.Core/Routing/Executor/FunctionExecutorFactory.cs[8-18]

## Suggested direction
- Update `NormalizeFunctionName` to:
 - use `string.IsNullOrWhiteSpace` for the initial guard
 - `Trim()` the input
 - split on both `.` and `/` (e.g., via `Split(new[]{&#x27;.&#x27;,&#x27;/&#x27;}, StringSplitOptions.RemoveEmptyEntries)`)
 - return the last non-empty segment (trimmed)
 - if the normalized token is empty, return `null` (or original) so callers can handle it
- Optionally add a small validation at call sites: if normalized is null/whitespace, do not overwrite and/or set a clear error explaining malformed tool name.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unstructured warning logs added 📘 Rule violation ✧ Quality
Description
• New warning logs use interpolated strings (e.g., $"Action: ...") rather than structured logging
  templates with named properties.
• This makes logs harder to parse/search/monitor and increases the chance of accidentally embedding
  sensitive values directly into log strings.
• The pattern is introduced across multiple providers for the max-output-length condition.
Code

src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs[R78-84]

+            _logger.LogWarning($"Action: {nameof(GetChatCompletions)}, Reason: {reason}, Agent: {agent.Name}, MaxOutputTokens: {options.MaxOutputTokenCount}");
+
+            responseMessage = new RoleDialogModel(AgentRole.Assistant, $"AI response exceeded max output length {options.MaxOutputTokenCount}")
            {
                CurrentAgentId = agent.Id,
-                MessageId = conversations.LastOrDefault()?.MessageId ?? string.Empty
+                MessageId = conversations.LastOrDefault()?.MessageId ?? string.Empty,
+                StopCompletion = true
Evidence
PR Compliance ID 5 requires structured logs. The added warning log lines are plain interpolated
strings (not structured message templates) and are newly introduced by this PR in several providers.

Rule 5: Generic: Secure Logging Practices
src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs[78-84]
src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs[83-85]
src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs[74-76]
src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/ChatCompletionProvider.cs[78-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New warning logs are written as interpolated strings rather than structured logs, reducing auditability and increasing the chance of leaking sensitive values.

## Issue Context
The compliance requirement asks for structured logs suitable for parsing/monitoring and to avoid sensitive data in log output.

## Fix Focus Areas
- src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs[78-84]
- src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs[83-85]
- src/Plugins/BotSharp.Plugin.DeepSeekAI/Providers/Chat/ChatCompletionProvider.cs[74-76]
- src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/ChatCompletionProvider.cs[78-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 19 to 22
message.StopCompletion = true;
message.Content = $"Can't find function implementation of {name}.";
_logger.LogError(message.Content);
_logger.LogError($"{message.Content}, stackInfo:{DiagnosticHelper.GetCurrentStackTrace()}");
return false;

Choose a reason for hiding this comment

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

Action required

1. Stack trace logged in error 📘 Rule violation ⛨ Security

• The new error log appends a full stack trace via DiagnosticHelper.GetCurrentStackTrace() when a
  function implementation is missing.
• Stack traces can contain sensitive internal details (method names, paths, code locations) and the
  log line is also unstructured, making it harder to audit safely.
• This increases the risk of sensitive information exposure through logs and reduces log usability
  for monitoring/auditing.
Agent Prompt
## Issue description
The code logs a full stack trace as part of an interpolated error message. This can leak internal details into logs and is not structured logging.

## Issue Context
Secure logging requires logs to be structured and to avoid sensitive/internal details in log output.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs[19-22]
- src/Infrastructure/BotSharp.Abstraction/Utilities/DiagnosticHelper.cs[12-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 74 to 89
public static string? NormalizeFunctionName(this string? functionName)
{
if (string.IsNullOrEmpty(functionName))
{
return functionName;
}

if (functionName.Contains('.'))
{
return functionName.Split('.').Last();
}

if (functionName.Contains('/'))
{
return functionName.Split('/').Last();
}

Choose a reason for hiding this comment

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

Action required

2. Normalization can yield invalid name 🐞 Bug ✓ Correctness

NormalizeFunctionName can return empty string or whitespace (e.g., inputs like "Agent." or
  "Agent/ ") because it doesn’t trim or remove empty segments.
• Multiple call sites now assign the normalized value back to FunctionName/args.Function without
  validation, increasing the chance of passing an empty/invalid function name downstream.
• Function execution is resolved by exact name equality; an empty/whitespace name will fail lookup
  and surface as “Can’t find function implementation …”, making failures harder to attribute to
  malformed LLM output.
Agent Prompt
## Issue description
`NormalizeFunctionName` can normalize malformed names into empty/whitespace strings (e.g., trailing `.` or `/`, leading/trailing spaces). Those values then fail downstream exact-match lookups for executors.

## Issue Context
Function execution is resolved via `x.Name == functionName` (exact equality). Call sites now overwrite the function name with the normalized value without validating it.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs[74-92]
- src/Infrastructure/BotSharp.Core/Routing/Executor/FunctionExecutorFactory.cs[8-18]

## Suggested direction
- Update `NormalizeFunctionName` to:
  - use `string.IsNullOrWhiteSpace` for the initial guard
  - `Trim()` the input
  - split on both `.` and `/` (e.g., via `Split(new[]{'.','/'}, StringSplitOptions.RemoveEmptyEntries)`)
  - return the last non-empty segment (trimmed)
  - if the normalized token is empty, return `null` (or original) so callers can handle it
- Optionally add a small validation at call sites: if normalized is null/whitespace, do not overwrite and/or set a clear error explaining malformed tool name.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@yileicn yileicn requested a review from Oceania2018 February 6, 2026 02:33
@JackJiang1234
Copy link
Contributor

reviewed

@yileicn yileicn merged commit d6a2f56 into SciSharp:master Feb 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants