Skip to content

Commit

Permalink
Refactor PromptClientInput to support parsed result and errors
Browse files Browse the repository at this point in the history
Updated PromptClientInput to handle parsed input results and return error messages instead of raw strings. Introduced ParsedInputResult<TResult> class to encapsulate parsing results and errors, enhancing client validation and feedback mechanism.
  • Loading branch information
Ayymoss committed Aug 4, 2024
1 parent aaa2574 commit 58ac495
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 12 deletions.
16 changes: 16 additions & 0 deletions SharedLibraryCore/Helpers/ParsedInputResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;

namespace SharedLibraryCore.Helpers;

public class ParsedInputResult<TResult>
{
public TResult? Result { get; set; }

Check warning on line 7 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 7 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 7 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 7 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 7 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public string? RawInput { get; set; }

Check warning on line 8 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 8 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 8 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 8 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 8 in SharedLibraryCore/Helpers/ParsedInputResult.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public List<string> ErrorMessages { get; set; } = [];

public ParsedInputResult<TResult> WithError(string errorMessage)
{
ErrorMessages.Add(errorMessage);
return this;
}
}
29 changes: 17 additions & 12 deletions SharedLibraryCore/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1375,28 +1375,32 @@ public static void ExecuteAfterDelay(int delayMs, Func<CancellationToken, Task>
public static void ExecuteAfterDelay(this Func<CancellationToken, Task> action, int delayMs,
CancellationToken token = default) => ExecuteAfterDelay(delayMs, action, token);

public static async Task<string> PromptClientInput(this EFClient client, string[] prompt, Func<string, Task<bool>> validator,
CancellationToken token = default)
public static async Task<ParsedInputResult<TResult>> PromptClientInput<TResult>(this EFClient client, string[] prompts,
Func<string, Task<ParsedInputResult<TResult>>> parser, string tokenExpiredMessage, CancellationToken token = default)
{
var clientResponse = new ManualResetEventSlim(false);
string response = null;
ParsedInputResult<TResult>? response = null;

Check warning on line 1382 in SharedLibraryCore/Utilities.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1382 in SharedLibraryCore/Utilities.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1382 in SharedLibraryCore/Utilities.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1382 in SharedLibraryCore/Utilities.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1382 in SharedLibraryCore/Utilities.cs

View workflow job for this annotation

GitHub Actions / build_pack

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

try
{
IGameEventSubscriptions.ClientMessaged += OnResponse;
await client.TellAsync(prompt, token);
await client.TellAsync(prompts, token);

using var tokenSource = new CancellationTokenSource(DefaultCommandTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token, token);

clientResponse.Wait(linkedTokenSource.Token);
try
{
clientResponse.Wait(linkedTokenSource.Token);
}
catch (OperationCanceledException)
{
await client.TellAsync([tokenExpiredMessage], token);
return new ParsedInputResult<TResult> { ErrorMessages = [tokenExpiredMessage] };
}

return response;
}
catch (OperationCanceledException)
{
return null;
}
finally
{
IGameEventSubscriptions.ClientMessaged -= OnResponse;
Expand All @@ -1410,16 +1414,17 @@ async Task OnResponse(ClientMessageEvent messageEvent, CancellationToken cancell
return;
}

response = messageEvent.Message;
response = await parser(messageEvent.Message);
response.RawInput = messageEvent.Message;

if (await validator(response))
if (response.ErrorMessages.Count is 0)
{
// ReSharper disable once AccessToDisposedClosure
clientResponse.Set();
}
else
{
await client.TellAsync(prompt, cancellationToken);
await client.TellAsync(response.ErrorMessages.Concat(prompts), cancellationToken);
}
}
}
Expand Down

0 comments on commit 58ac495

Please sign in to comment.