Skip to content

Conversation

@iceljc
Copy link
Collaborator

@iceljc iceljc commented Nov 17, 2025

PR Type

Enhancement, Bug fix


Description

  • Add new crontab endpoint to manually trigger scheduled tasks

  • Refactor instruction execution logic into separate RunLlm method

  • Fix typos and improve code organization in crontab service

  • Clean up unused imports and reorganize namespace structure


Diagram Walkthrough

flowchart LR
  A["CrontabController"] -- "POST /crontab/{name}" --> B["RunCrontab"]
  B -- "calls" --> C["ICrontabService"]
  C -- "executes" --> D["ScheduledTimeArrived"]
  E["InstructService.Execute"] -- "delegates" --> F["RunLlm"]
  F -- "handles" --> G["LLM Completion"]
Loading

File Walkthrough

Relevant files
Bug fix
CrontabService.cs
Fix typos in crontab service variable names                           

src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs

  • Fixed typo: fixedCrantabItems renamed to fixedCrontabItems
  • Fixed typo: cronsources renamed to cronSources for consistency
  • Improved variable naming conventions throughout the method
+5/-5     
Enhancement
InstructService.Execute.cs
Refactor instruction execution into separate RunLlm method

src/Infrastructure/BotSharp.Core/Instructs/Services/InstructService.Execute.cs

  • Extracted LLM completion logic into new RunLlm private method
  • Simplified Execute method by delegating LLM work to RunLlm
  • Improved code response handling with null check
  • Reorganized imports in alphabetical order
  • Removed unused IConversationStateService variable from Execute method
+127/-105
CrontabController.cs
Add new crontab controller with run endpoint                         

src/Infrastructure/BotSharp.OpenAPI/Controllers/Crontab/CrontabController.cs

  • Created new CrontabController with POST endpoint /crontab/{name}
  • Implements manual crontab execution by name
  • Includes error handling and logging for crontab execution
  • Returns boolean indicating success or failure
+45/-0   
Miscellaneous
SpeechToTextRequest.cs
Remove empty SpeechToTextRequest class                                     

src/Plugins/BotSharp.Plugin.OpenAI/Models/SpeechToTextRequest.cs

  • Removed empty placeholder class file
+0/-5     
RealTimeCompletionProvider.cs
Remove unused imports from RealTimeCompletionProvider       

src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs

  • Removed unused imports: BotSharp.Abstraction.Realtime.Sessions and
    BotSharp.Plugin.OpenAI.Models.Realtime
  • Cleaned up unnecessary dependencies
+0/-2     
Configuration changes
TextCompletionRequest.cs
Update namespace for TextCompletionRequest                             

src/Plugins/BotSharp.Plugin.OpenAI/Models/Text/TextCompletionRequest.cs

  • Updated namespace from BotSharp.Plugin.OpenAI.Models to
    BotSharp.Plugin.OpenAI.Models.Text
  • Moved file to Text subdirectory for better organization
+1/-1     
TextCompletionResponse.cs
Update namespace for TextCompletionResponse                           

src/Plugins/BotSharp.Plugin.OpenAI/Models/Text/TextCompletionResponse.cs

  • Updated namespace from BotSharp.Plugin.OpenAI.Models to
    BotSharp.Plugin.OpenAI.Models.Text
  • Moved file to Text subdirectory for better organization
+1/-1     
Using.cs
Update global using statements for new namespaces               

src/Plugins/BotSharp.Plugin.OpenAI/Using.cs

  • Updated global using statements to reflect new namespace structure
  • Changed BotSharp.Plugin.OpenAI.Models to
    BotSharp.Plugin.OpenAI.Models.Text
  • Added explicit import for BotSharp.Plugin.OpenAI.Models.Realtime
  • Reorganized imports with improved spacing for readability
+4/-1     

@qodo-merge-pro
Copy link

qodo-merge-pro bot commented Nov 17, 2025

PR Compliance Guide 🔍

(Compliance updated until commit d445e0b)

Below is a summary of compliance checks for this PR:

Security Compliance
Missing authorization checks

Description: The POST endpoint /crontab/{name} allows any authenticated user to trigger arbitrary
scheduled tasks by title without additional authorization, input validation, or rate
limiting, enabling potential abuse or privilege escalation if task names are guessable or
sensitive jobs exist.
CrontabController.cs [20-44]

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {


 ... (clipped 4 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Insufficient Audit: The new crontab execution endpoint logs start/complete/errors but does not include user
identity or structured audit details required to reconstruct who triggered the action.

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {


 ... (clipped 4 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Generic Errors: The endpoint returns boolean without conveying actionable failure context to callers and
does not validate input 'name' beyond a title match, which may hinder robust
error handling.

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {


 ... (clipped 5 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured Logs: Logging uses free-form messages without structured fields (e.g., user, crontab id), which
may reduce auditability and could risk accidental inclusion of sensitive data in messages.

Referred Code
    _logger.LogWarning($"Cannnot find crontab {name}");
    return false;
}

try
{
    _logger.LogWarning($"Start running crontab {name}");
    await cron.ScheduledTimeArrived(found);
    _logger.LogWarning($"Complete running crontab {name}");
    return true;
}
catch (Exception ex)
{
    _logger.LogError(ex, $"Error when running crontab {name}");

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Input Validation: The route parameter 'name' is used directly to select and run a crontab by title
without validation or authorization checks specific to the task being triggered.

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

Previous compliance checks

Compliance check up to commit d445e0b
Security Compliance
Unrestricted job triggering

Description: The new POST /crontab/{name} endpoint allows any authorized caller to trigger arbitrary
scheduled jobs by title without scope checks, rate limits, or CSRF protection for
state-changing action, enabling abuse (e.g., repeated execution of heavy jobs or
unintended task invocation by guessing names).
CrontabController.cs [20-44]

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {


 ... (clipped 4 lines)
Unvalidated job sources

Description: Fixed crontab items from all ICrontabSource implementations are blindly appended without
validation; if a malicious or misconfigured source is registered, its task becomes
triggerable via the new endpoint by title, expanding the attack surface to unvetted jobs.
CrontabService.cs [49-62]

Referred Code
// Add fixed crontab items from cronsources
var fixedCrontabItems = crontable.Items.ToList();
var cronSources = _services.GetServices<ICrontabSource>();
foreach (var source in cronSources)
{
    if (source.IsRealTime)
    {
        continue;
    }
    var item = source.GetCrontabItem();
    fixedCrontabItems.Add(item);
}

return fixedCrontabItems;
Information disclosure in logs

Description: Execution status and internal job names are logged with LogWarning/LogError including
user-supplied {name}, which could leak operational details and facilitate
enumeration/bruteforce of job titles through log analysis.
CrontabController.cs [34-41]

Referred Code
    _logger.LogWarning($"Start running crontab {name}");
    await cron.ScheduledTimeArrived(found);
    _logger.LogWarning($"Complete running crontab {name}");
    return true;
}
catch (Exception ex)
{
    _logger.LogError(ex, $"Error when running crontab {name}");
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit context: The new crontab execution endpoint logs messages but does not include user identity or
sufficient action context to meet comprehensive audit trail requirements.

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {
        _logger.LogWarning($"Cannnot find crontab {name}");
        return false;
    }

    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {


 ... (clipped 4 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Broad catch block: The endpoint catches all exceptions and returns false without exposing actionable error
context to callers or validating input (e.g., empty or whitespace name).

Referred Code
    try
    {
        _logger.LogWarning($"Start running crontab {name}");
        await cron.ScheduledTimeArrived(found);
        _logger.LogWarning($"Complete running crontab {name}");
        return true;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Error when running crontab {name}");
        return false;
    }
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Missing input validation: The RunCrontab endpoint accepts a path parameter 'name' but does not validate or
normalize it (e.g., empty, whitespace, length, allowed characters), which could lead to
misuse.

Referred Code
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable();
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
    if (found == null)
    {

Learn more about managing compliance generic rules or creating your own custom rules

@qodo-merge-pro
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Return code execution failure messages

When code execution fails, return the error message to the user instead of
silently falling back to the LLM. This provides immediate feedback and improves
debuggability.

src/Infrastructure/BotSharp.Core/Instructs/Services/InstructService.Execute.cs [169-179]

-if (codeResponse == null || !codeResponse.Success)
+if (codeResponse == null)
 {
     return instructResult;
+}
+
+// If code execution failed, return the error message to the user.
+// Otherwise, the failure is silent and the system will proceed with the LLM fallback.
+if (!codeResponse.Success)
+{
+    _logger.LogError($"Code execution failed: {codeResponse.Result}");
 }
 
 instructResult = new InstructResult
 {
     MessageId = message.MessageId,
     Template = context.CodeScript?.Name,
     Text = codeResponse.Result
 };
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that a code execution failure is silently ignored, and proposes returning the error to the user, which significantly improves error handling and user experience.

Medium
High-level
Inefficiently fetching all crontab jobs

The manual crontab trigger endpoint fetches all jobs into memory before
filtering, which is inefficient. A dedicated method should be added to retrieve
a single job by name directly from the data source to improve scalability.

Examples:

src/Infrastructure/BotSharp.OpenAPI/Controllers/Crontab/CrontabController.cs [24-25]
        var crons = await cron.GetCrontable();
        var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));

Solution Walkthrough:

Before:

// In CrontabController.cs
public async Task<bool> RunCrontab(string name)
{
    var cron = _services.GetRequiredService<ICrontabService>();
    var crons = await cron.GetCrontable(); // Fetches all jobs
    var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name)); // Filters in-memory

    if (found == null)
    {
        return false;
    }

    await cron.ScheduledTimeArrived(found);
    return true;
}

After:

// In ICrontabService (new method)
Task<CrontabItem> GetCrontabItemByName(string name);

// In CrontabController.cs
public async Task<bool> RunCrontab(string name)
{
    var cronService = _services.GetRequiredService<ICrontabService>();
    // Fetches only the required job
    var found = await cronService.GetCrontabItemByName(name);

    if (found == null)
    {
        return false;
    }

    await cronService.ScheduledTimeArrived(found);
    return true;
}
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a scalability issue in the new RunCrontab endpoint where all jobs are fetched into memory instead of filtering at the data source.

Medium
General
Filter crontab jobs at database

Improve performance by filtering crontab jobs at the database level instead of
fetching all jobs and filtering them in memory. This may require modifying
ICrontabService to accept a filter.

src/Infrastructure/BotSharp.OpenAPI/Controllers/Crontab/CrontabController.cs [23-25]

 var cron = _services.GetRequiredService<ICrontabService>();
-var crons = await cron.GetCrontable();
-var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
+var filter = new CrontabItemFilter { Title = name };
+var found = await cron.GetCrontabItem(filter);
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies a potential performance issue by fetching all crontab jobs and filtering in memory, proposing a more scalable database-level filtering approach.

Low
  • More

@iceljc iceljc merged commit 17cd768 into SciSharp:master Nov 17, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant