Skip to content

Commit 17cd768

Browse files
authored
Merge pull request #1220 from iceljc/master
add run crontab endpoint
2 parents babd9c6 + d445e0b commit 17cd768

File tree

8 files changed

+183
-120
lines changed

8 files changed

+183
-120
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,19 @@ public async Task<List<CrontabItem>> GetCrontable()
4747
var crontable = await repo.GetCrontabItems(CrontabItemFilter.Empty());
4848

4949
// Add fixed crontab items from cronsources
50-
var fixedCrantabItems = crontable.Items.ToList();
51-
var cronsources = _services.GetServices<ICrontabSource>();
52-
foreach (var source in cronsources)
50+
var fixedCrontabItems = crontable.Items.ToList();
51+
var cronSources = _services.GetServices<ICrontabSource>();
52+
foreach (var source in cronSources)
5353
{
5454
if (source.IsRealTime)
5555
{
5656
continue;
5757
}
5858
var item = source.GetCrontabItem();
59-
fixedCrantabItems.Add(item);
59+
fixedCrontabItems.Add(item);
6060
}
6161

62-
return fixedCrantabItems;
62+
return fixedCrontabItems;
6363
}
6464

6565
public async Task<List<AgentTask>> GetTasks()

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

Lines changed: 127 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using BotSharp.Abstraction.Coding;
2-
using BotSharp.Abstraction.Coding.Enums;
32
using BotSharp.Abstraction.Coding.Contexts;
3+
using BotSharp.Abstraction.Coding.Enums;
44
using BotSharp.Abstraction.Files.Options;
55
using BotSharp.Abstraction.Files.Proccessors;
66
using BotSharp.Abstraction.Instructs;
@@ -23,7 +23,6 @@ public async Task<InstructResult> Execute(
2323
FileInstructOptions? fileOptions = null)
2424
{
2525
var agentService = _services.GetRequiredService<IAgentService>();
26-
var state = _services.GetRequiredService<IConversationStateService>();
2726
var agent = await agentService.LoadAgent(agentId);
2827

2928
var response = new InstructResult
@@ -32,7 +31,6 @@ public async Task<InstructResult> Execute(
3231
Template = templateName
3332
};
3433

35-
3634
if (agent == null)
3735
{
3836
response.Text = $"Agent (id: {agentId}) does not exist!";
@@ -46,112 +44,14 @@ public async Task<InstructResult> Execute(
4644
return response;
4745
}
4846

49-
5047
// Run code template
5148
var codeResponse = await RunCode(agent, message, templateName, codeOptions);
52-
if (!string.IsNullOrWhiteSpace(codeResponse?.Text))
49+
if (codeResponse != null)
5350
{
5451
return codeResponse;
5552
}
5653

57-
58-
// Before completion hooks
59-
var hooks = _services.GetHooks<IInstructHook>(agentId);
60-
foreach (var hook in hooks)
61-
{
62-
await hook.BeforeCompletion(agent, message);
63-
64-
// Interrupted by hook
65-
if (message.StopCompletion)
66-
{
67-
return new InstructResult
68-
{
69-
MessageId = message.MessageId,
70-
Text = message.Content
71-
};
72-
}
73-
}
74-
75-
76-
var provider = string.Empty;
77-
var model = string.Empty;
78-
var result = string.Empty;
79-
80-
// Render prompt
81-
var prompt = string.IsNullOrEmpty(templateName) ?
82-
agentService.RenderInstruction(agent) :
83-
agentService.RenderTemplate(agent, templateName);
84-
85-
var completer = CompletionProvider.GetCompletion(_services,
86-
agentConfig: agent.LlmConfig);
87-
88-
if (completer is ITextCompletion textCompleter)
89-
{
90-
instruction = null;
91-
provider = textCompleter.Provider;
92-
model = textCompleter.Model;
93-
94-
result = await GetTextCompletion(textCompleter, agent, prompt, message.MessageId);
95-
response.Text = result;
96-
}
97-
else if (completer is IChatCompletion chatCompleter)
98-
{
99-
provider = chatCompleter.Provider;
100-
model = chatCompleter.Model;
101-
102-
103-
if (instruction == "#TEMPLATE#")
104-
{
105-
instruction = prompt;
106-
prompt = message.Content;
107-
}
108-
109-
IFileProcessor? fileProcessor = null;
110-
if (!files.IsNullOrEmpty() && fileOptions != null)
111-
{
112-
fileProcessor = _services.GetServices<IFileProcessor>()
113-
.FirstOrDefault(x => x.Provider.IsEqualTo(fileOptions.Processor));
114-
}
115-
116-
if (fileProcessor != null)
117-
{
118-
var fileResponse = await fileProcessor.HandleFilesAsync(agent, prompt, files, new FileHandleOptions
119-
{
120-
Provider = provider,
121-
Model = model,
122-
Instruction = instruction,
123-
UserMessage = message.Content,
124-
TemplateName = templateName,
125-
InvokeFrom = $"{nameof(InstructService)}.{nameof(Execute)}",
126-
Data = state.GetStates().ToDictionary(x => x.Key, x => (object)x.Value)
127-
});
128-
result = fileResponse.Result.IfNullOrEmptyAs(string.Empty);
129-
}
130-
else
131-
{
132-
result = await GetChatCompletion(chatCompleter, agent, instruction, prompt, message.MessageId, files);
133-
}
134-
response.Text = result;
135-
}
136-
137-
response.LogId = Guid.NewGuid().ToString();
138-
// After completion hooks
139-
foreach (var hook in hooks)
140-
{
141-
await hook.AfterCompletion(agent, response);
142-
await hook.OnResponseGenerated(new InstructResponseModel
143-
{
144-
LogId = response.LogId,
145-
AgentId = agentId,
146-
Provider = provider,
147-
Model = model,
148-
TemplateName = templateName,
149-
UserMessage = prompt,
150-
SystemInstruction = instruction,
151-
CompletionText = response.Text
152-
});
153-
}
154-
54+
response = await RunLlm(agent, message, instruction, templateName, files, fileOptions);
15555
return response;
15656
}
15757

@@ -166,7 +66,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
16666
private async Task<InstructResult?> RunCode(
16767
Agent agent,
16868
RoleDialogModel message,
169-
string templateName,
69+
string? templateName,
17070
CodeInstructOptions? codeOptions)
17171
{
17272
InstructResult? instructResult = null;
@@ -266,11 +166,16 @@ await hook.OnResponseGenerated(new InstructResponseModel
266166
UseProcess = useProcess
267167
}, cancellationToken: cts.Token);
268168

169+
if (codeResponse == null || !codeResponse.Success)
170+
{
171+
return instructResult;
172+
}
173+
269174
instructResult = new InstructResult
270175
{
271176
MessageId = message.MessageId,
272177
Template = context.CodeScript?.Name,
273-
Text = codeResponse?.Result ?? string.Empty
178+
Text = codeResponse.Result
274179
};
275180

276181
var codeExecution = new CodeExecutionResponseModel
@@ -292,6 +197,123 @@ await hook.OnResponseGenerated(new InstructResponseModel
292197
return instructResult;
293198
}
294199

200+
201+
private async Task<InstructResult> RunLlm(
202+
Agent agent,
203+
RoleDialogModel message,
204+
string? instruction,
205+
string? templateName,
206+
IEnumerable<InstructFileModel>? files = null,
207+
FileInstructOptions? fileOptions = null)
208+
{
209+
var agentService = _services.GetRequiredService<IAgentService>();
210+
var state = _services.GetRequiredService<IConversationStateService>();
211+
212+
var response = new InstructResult
213+
{
214+
MessageId = message.MessageId,
215+
Template = templateName
216+
};
217+
218+
// Before completion hooks
219+
var hooks = _services.GetHooks<IInstructHook>(agent.Id);
220+
foreach (var hook in hooks)
221+
{
222+
await hook.BeforeCompletion(agent, message);
223+
224+
// Interrupted by hook
225+
if (message.StopCompletion)
226+
{
227+
return new InstructResult
228+
{
229+
MessageId = message.MessageId,
230+
Text = message.Content
231+
};
232+
}
233+
}
234+
235+
var provider = string.Empty;
236+
var model = string.Empty;
237+
var result = string.Empty;
238+
239+
// Render prompt
240+
var prompt = string.IsNullOrEmpty(templateName) ?
241+
agentService.RenderInstruction(agent) :
242+
agentService.RenderTemplate(agent, templateName);
243+
244+
var completer = CompletionProvider.GetCompletion(_services,
245+
agentConfig: agent.LlmConfig);
246+
247+
if (completer is ITextCompletion textCompleter)
248+
{
249+
instruction = null;
250+
provider = textCompleter.Provider;
251+
model = textCompleter.Model;
252+
253+
result = await GetTextCompletion(textCompleter, agent, prompt, message.MessageId);
254+
response.Text = result;
255+
}
256+
else if (completer is IChatCompletion chatCompleter)
257+
{
258+
provider = chatCompleter.Provider;
259+
model = chatCompleter.Model;
260+
261+
if (instruction == "#TEMPLATE#")
262+
{
263+
instruction = prompt;
264+
prompt = message.Content;
265+
}
266+
267+
IFileProcessor? fileProcessor = null;
268+
if (!files.IsNullOrEmpty() && fileOptions != null)
269+
{
270+
fileProcessor = _services.GetServices<IFileProcessor>()
271+
.FirstOrDefault(x => x.Provider.IsEqualTo(fileOptions.Processor));
272+
}
273+
274+
if (fileProcessor != null)
275+
{
276+
var fileResponse = await fileProcessor.HandleFilesAsync(agent, prompt, files, new FileHandleOptions
277+
{
278+
Provider = provider,
279+
Model = model,
280+
Instruction = instruction,
281+
UserMessage = message.Content,
282+
TemplateName = templateName,
283+
InvokeFrom = $"{nameof(InstructService)}.{nameof(Execute)}",
284+
Data = state.GetStates().ToDictionary(x => x.Key, x => (object)x.Value)
285+
});
286+
result = fileResponse.Result.IfNullOrEmptyAs(string.Empty);
287+
}
288+
else
289+
{
290+
result = await GetChatCompletion(chatCompleter, agent, instruction, prompt, message.MessageId, files);
291+
}
292+
response.Text = result;
293+
}
294+
295+
response.LogId = Guid.NewGuid().ToString();
296+
// After completion hooks
297+
foreach (var hook in hooks)
298+
{
299+
await hook.AfterCompletion(agent, response);
300+
await hook.OnResponseGenerated(new InstructResponseModel
301+
{
302+
LogId = response.LogId,
303+
AgentId = agent.Id,
304+
Provider = provider,
305+
Model = model,
306+
TemplateName = templateName,
307+
UserMessage = prompt,
308+
SystemInstruction = instruction,
309+
CompletionText = response.Text
310+
});
311+
}
312+
313+
return response;
314+
}
315+
316+
295317
private async Task<string> GetTextCompletion(
296318
ITextCompletion textCompleter,
297319
Agent agent,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using BotSharp.Abstraction.Crontab;
2+
3+
namespace BotSharp.OpenAPI.Controllers;
4+
5+
[Authorize]
6+
[ApiController]
7+
public class CrontabController : ControllerBase
8+
{
9+
private readonly IServiceProvider _services;
10+
private readonly ILogger<CrontabController> _logger;
11+
12+
public CrontabController(
13+
IServiceProvider services,
14+
ILogger<CrontabController> logger)
15+
{
16+
_services = services;
17+
_logger = logger;
18+
}
19+
20+
[HttpPost("/crontab/{name}")]
21+
public async Task<bool> RunCrontab(string name)
22+
{
23+
var cron = _services.GetRequiredService<ICrontabService>();
24+
var crons = await cron.GetCrontable();
25+
var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
26+
if (found == null)
27+
{
28+
_logger.LogWarning($"Cannnot find crontab {name}");
29+
return false;
30+
}
31+
32+
try
33+
{
34+
_logger.LogWarning($"Start running crontab {name}");
35+
await cron.ScheduledTimeArrived(found);
36+
_logger.LogWarning($"Complete running crontab {name}");
37+
return true;
38+
}
39+
catch (Exception ex)
40+
{
41+
_logger.LogError(ex, $"Error when running crontab {name}");
42+
return false;
43+
}
44+
}
45+
}

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

Lines changed: 0 additions & 5 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace BotSharp.Plugin.OpenAI.Models;
1+
namespace BotSharp.Plugin.OpenAI.Models.Text;
22

33
public class TextCompletionRequest
44
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace BotSharp.Plugin.OpenAI.Models;
1+
namespace BotSharp.Plugin.OpenAI.Models.Text;
22

33
public class TextCompletionResponse
44
{

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using BotSharp.Abstraction.Hooks;
22
using BotSharp.Abstraction.Realtime.Options;
3-
using BotSharp.Abstraction.Realtime.Sessions;
43
using BotSharp.Abstraction.Realtime.Settings;
5-
using BotSharp.Plugin.OpenAI.Models.Realtime;
64
using OpenAI.Chat;
75

86
namespace BotSharp.Plugin.OpenAI.Providers.Realtime;

0 commit comments

Comments
 (0)