Skip to content

Commit 7fda8d2

Browse files
authored
Merge pull request #1149 from iceljc/features/add-chart-data
add chart data and code endpoints
2 parents 36bbfa8 + 9b30898 commit 7fda8d2

File tree

16 files changed

+330
-3
lines changed

16 files changed

+330
-3
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using BotSharp.Abstraction.Chart.Models;
2+
3+
namespace BotSharp.Abstraction.Chart;
4+
5+
public interface IBotSharpChartService
6+
{
7+
public string Provider { get; }
8+
9+
Task<ChartDataResult?> GetConversationChartData(string conversationId, string messageId, ChartDataOptions options)
10+
=> throw new NotImplementedException();
11+
12+
Task<ChartCodeResult?> GetConversationChartCode(string conversationId, string messageId, ChartCodeOptions options)
13+
=> throw new NotImplementedException();
14+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace BotSharp.Abstraction.Chart.Models;
2+
3+
public class ChartCodeOptions
4+
{
5+
public string? AgentId { get; set; }
6+
public string? TemplateName { get; set; }
7+
public string Text { get; set; } = string.Empty;
8+
9+
/// <summary>
10+
/// Conversation state that can be used to fetch chart data
11+
/// </summary>
12+
public string? TargetStateName { get; set; }
13+
14+
public ChartLlmOptions? Llm { get; set; }
15+
public List<KeyValue<object>>? States { get; set; }
16+
17+
}
18+
19+
public class ChartLlmOptions
20+
{
21+
public string? Provider { get; set; }
22+
public string? Model { get; set; }
23+
public int? MaxOutputTokens { get; set; }
24+
public string? ReasoningEffortLevel { get; set; }
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace BotSharp.Abstraction.Chart.Models;
2+
3+
public class ChartCodeResult
4+
{
5+
public string Code { get; set; }
6+
public string Language { get; set; }
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace BotSharp.Abstraction.Chart.Models;
2+
3+
public class ChartDataOptions
4+
{
5+
/// <summary>
6+
/// Conversation state that can be used to fetch chart data
7+
/// </summary>
8+
public string? TargetStateName { get; set; }
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace BotSharp.Abstraction.Chart.Models;
2+
3+
public class ChartDataResult
4+
{
5+
public object Data { get; set; }
6+
}

src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using BotSharp.Abstraction.Chart;
12
using BotSharp.Abstraction.Files.Constants;
23
using BotSharp.Abstraction.Files.Enums;
34
using BotSharp.Abstraction.Files.Utilities;
@@ -530,6 +531,35 @@ public IActionResult DownloadMessageFile([FromRoute] string conversationId, [Fro
530531
}
531532
#endregion
532533

534+
#region Chart
535+
[AllowAnonymous]
536+
[HttpGet("/conversation/{conversationId}/message/{messageId}/user/chart/data")]
537+
public async Task<ConversationChartDataResponse?> GetConversationChartData(
538+
[FromRoute] string conversationId,
539+
[FromRoute] string messageId,
540+
[FromQuery] ConversationChartDataRequest request)
541+
{
542+
var chart = _services.GetServices<IBotSharpChartService>().FirstOrDefault(x => x.Provider == request?.ChartProvider);
543+
if (chart == null) return null;
544+
545+
var result = await chart.GetConversationChartData(conversationId, messageId, request);
546+
return ConversationChartDataResponse.From(result);
547+
}
548+
549+
[HttpPost("/conversation/{conversationId}/message/{messageId}/user/chart/code")]
550+
public async Task<ConversationChartCodeResponse?> GetConversationChartCode(
551+
[FromRoute] string conversationId,
552+
[FromRoute] string messageId,
553+
[FromBody] ConversationChartCodeRequest request)
554+
{
555+
var chart = _services.GetServices<IBotSharpChartService>().FirstOrDefault(x => x.Provider == request?.ChartProvider);
556+
if (chart == null) return null;
557+
558+
var result = await chart.GetConversationChartCode(conversationId, messageId, request);
559+
return ConversationChartCodeResponse.From(result);
560+
}
561+
#endregion
562+
533563
#region Dashboard
534564
[HttpPut("/agent/{agentId}/conversation/{conversationId}/dashboard")]
535565
public async Task<bool> PinConversationToDashboard([FromRoute] string agentId, [FromRoute] string conversationId)

src/Infrastructure/BotSharp.OpenAPI/Using.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
global using BotSharp.Abstraction.Files;
2929
global using BotSharp.Abstraction.VectorStorage.Enums;
3030
global using BotSharp.Abstraction.Knowledges.Models;
31+
global using BotSharp.Abstraction.Chart.Models;
3132
global using BotSharp.OpenAPI.ViewModels.Conversations;
3233
global using BotSharp.OpenAPI.ViewModels.Users;
3334
global using BotSharp.OpenAPI.ViewModels.Agents;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace BotSharp.OpenAPI.ViewModels.Conversations;
2+
3+
public class ConversationChartDataRequest : ChartDataOptions
4+
{
5+
/// <summary>
6+
/// Chart service provider
7+
/// </summary>
8+
public string ChartProvider { get; set; } = "Botsharp";
9+
}
10+
11+
public class ConversationChartCodeRequest : ChartCodeOptions
12+
{
13+
/// <summary>
14+
/// Chart service provider
15+
/// </summary>
16+
public string ChartProvider { get; set; } = "Botsharp";
17+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace BotSharp.OpenAPI.ViewModels.Conversations;
2+
3+
public class ConversationChartDataResponse
4+
{
5+
public object Data { get; set; }
6+
7+
public static ConversationChartDataResponse? From(ChartDataResult? result)
8+
{
9+
if (result == null)
10+
{
11+
return null;
12+
}
13+
14+
return new()
15+
{
16+
Data = result.Data
17+
};
18+
}
19+
}
20+
21+
22+
public class ConversationChartCodeResponse
23+
{
24+
public string Code { get; set; }
25+
public string Language { get; set; }
26+
27+
public static ConversationChartCodeResponse? From(ChartCodeResult? result)
28+
{
29+
if (result == null)
30+
{
31+
return null;
32+
}
33+
34+
return new()
35+
{
36+
Code = result.Code,
37+
Language = result.Language
38+
};
39+
}
40+
}

src/Plugins/BotSharp.Plugin.ChartHandler/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-chart-plot_instruction.liquid

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@ You must strictly follow the "Hard Requirements", "Render Requirements", "Code R
77

88
***** Hard Requirements *****
99
** Your output javascript code must be wrapped in one or multiple <script>...</script> blocks with everything needed inside.
10-
** You need to import ECharts.js exactly once to plot the charts. The script source is "https://cdnjs.cloudflare.com/ajax/libs/echarts/5.5.1/echarts.min.js".
10+
** You need to import ECharts.js exactly once to plot the charts. The script source is "https://cdnjs.cloudflare.com/ajax/libs/echarts/6.0.0/echarts.min.js".
1111
** You must add an ECharts Toolbox bar at the top left corner of the chart.
1212
** ALWAYS add a "Full screen" button right next to the Toolbox bar.
1313
** The "Full screen" button can toggle the chart container in and out of fullscreen using the Fullscreen API. Requirements for this button:
1414
* Always call the Fullscreen API on the chart container div itself (document.getElementById("{{ chart_element_id }}")), not on the document.
15+
* When entering fullscreen, the chart container must have widhth: 100vw and height: 100vh.
1516
* Use el.requestFullscreen() with fallbacks to el.webkitRequestFullscreen || el.msRequestFullscreen.
1617
* Exit fullscreen with document.exitFullscreen() and vendor fallbacks.
1718
* Listen for fullscreenchange, webkitfullscreenchange, and msfullscreenchange to keep the button working across repeated clicks and ESC exits.
1819
* Ensure the chart fully expands and scales to the entire screen when fullscreen is active.
1920
* fullscreenBtn must be a fully-formed object {show: true, name, title, icon: 'path://M3 3 H9 V5 H5 V9 H3 Z M15 3 H21 V9 H19 V5 H15 Z M3 15 H5 V19 H9 V21 H3 Z M19 15 H21 V21 H15 V19 H19 Z', onclick}.
2021
* When using "chart.setOption" to define the fullscreen button, DO NOT use "graphic". Include the fullscreenBtn object in toolbox.feature with name 'myFullscreen'.
22+
** Initialize the chart with explicit non-zero width (at least 800px) and non-zero height (at least 500px).
2123

2224

2325
***** Render Requirements *****
2426
** You must render the charts under the div html element with id {{ chart_element_id }}.
2527
** You must not create any new html element.
26-
** You must ensure the generated charts have visible height (at least 500px) and width (at least 800px). DO NOT generate charts with zero height or zero width.
2728
** You must not apply any styles on any html element.
2829

2930

0 commit comments

Comments
 (0)