-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Support configure, login and review commands - Reorganize classes - Simplify dependency tree
- Loading branch information
Showing
72 changed files
with
894 additions
and
630 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ciandt/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System.Collections.Immutable; | ||
using System.Text.Json.Serialization; | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges.v1; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Infrastructure; | ||
|
||
[JsonSourceGenerationOptions( | ||
GenerationMode = JsonSourceGenerationMode.Default, | ||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, | ||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, | ||
PropertyNameCaseInsensitive = true, | ||
RespectNullableAnnotations = true)] | ||
[JsonSerializable(typeof(ImmutableList<ReviewerFeedbackResponse>))] | ||
public partial class AgentJsonContext : JsonSerializerContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.Login; | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges; | ||
using Jab; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Infrastructure; | ||
|
||
[ServiceProviderModule] | ||
|
||
// Infrastructure | ||
[Singleton(typeof(AgentJsonContext), Factory = nameof(GetJsonContext))] | ||
|
||
// Operations | ||
[Singleton(typeof(ILoginUseCase), typeof(LoginUseCase))] | ||
[Singleton(typeof(LoginCommand))] | ||
[Singleton(typeof(ReviewChangesCommand))] | ||
public interface IAgentModule | ||
{ | ||
static AgentJsonContext GetJsonContext() => AgentJsonContext.Default; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using Ciandt.FlowTools.FlowPair.Common; | ||
using ConsoleAppFramework; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Operations.Login; | ||
|
||
public class LoginCommand( | ||
ILoginUseCase loginUseCase) | ||
{ | ||
/// <summary> | ||
/// Sign in to the Flow. | ||
/// </summary> | ||
[Command("login")] | ||
public int Execute() | ||
{ | ||
return loginUseCase.Execute(isBackground: false) | ||
.UnwrapErrOr(0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using AutomaticInterface; | ||
using Ciandt.FlowTools.FlowPair.Common; | ||
using Ciandt.FlowTools.FlowPair.Flow; | ||
using Ciandt.FlowTools.FlowPair.Flow.Contracts; | ||
using Ciandt.FlowTools.FlowPair.Flow.Infrastructure; | ||
using Ciandt.FlowTools.FlowPair.Flow.Operations.GenerateToken; | ||
using Ciandt.FlowTools.FlowPair.Settings.Contracts.v1; | ||
using Ciandt.FlowTools.FlowPair.Settings.Services; | ||
using Ciandt.FlowTools.FlowPair.Support.Persistence; | ||
using Ciandt.FlowTools.FlowPair.UserSessions.Contracts.v1; | ||
using Ciandt.FlowTools.FlowPair.UserSessions.Services; | ||
using Spectre.Console; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Operations.Login; | ||
|
||
public partial interface ILoginUseCase; | ||
|
||
[GenerateAutomaticInterface] | ||
public sealed class LoginUseCase( | ||
TimeProvider timeProvider, | ||
IAnsiConsole console, | ||
FlowHttpClient httpClient, | ||
IAppSettingsRepository appSettingsRepository, | ||
IUserSessionRepository userSessionRepository, | ||
IFlowGenerateTokenHandler generateTokenHandler) | ||
: ILoginUseCase | ||
{ | ||
public Result<UserSession, int> Execute(bool isBackground) | ||
{ | ||
var result = from config in appSettingsRepository.Read().MapErr(HandleConfigurationError) | ||
from session in userSessionRepository.Read() | ||
.Do(SetupHttpAuthentication) | ||
.UnwrapOrElse(UserSession.Empty) | ||
.Ensure(s => s.IsExpired(timeProvider), 0) | ||
from auth in RequestToken(config, session, verbose: isBackground).MapErr(HandleFlowError) | ||
.Do(s => userSessionRepository.Save(s)) | ||
select auth; | ||
|
||
if (!isBackground) | ||
{ | ||
result.Do(s => console.WriteLine($"Signed in with expiration at {s.ExpiresAt:g}")); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private int HandleConfigurationError(GetJsonFileValueError error) | ||
{ | ||
var errorMessage = error.Match<FormattableString>( | ||
NotFound: _ => $"[red]Error:[/] Configuration not found.", | ||
Invalid: x => $"[red]Error:[/] {x.Exception.Message}", | ||
Null: _ => $"[red]Error:[/] Configuration is null.", | ||
UnknownVersion: x => $"[red]Error:[/] The configuration version '{x.Version}' is not supported."); | ||
|
||
console.MarkupLineInterpolated(errorMessage); | ||
return 1; | ||
} | ||
|
||
private void SetupHttpAuthentication(UserSession session) | ||
{ | ||
if (session.IsExpired(timeProvider)) | ||
return; | ||
|
||
httpClient.BearerToken = session.AccessToken; | ||
} | ||
|
||
private Result<UserSession, FlowError> RequestToken( | ||
AppConfiguration configuration, | ||
UserSession userSession, | ||
bool verbose) | ||
{ | ||
if (verbose) | ||
{ | ||
console.Write("Signing in to Flow..."); | ||
} | ||
|
||
var result = generateTokenHandler.Execute(configuration, userSession); | ||
if (verbose) | ||
{ | ||
result | ||
.Do(_ => console.WriteLine(" OK")) | ||
.DoErr(_ => console.WriteLine(" FAIL")); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private int HandleFlowError(FlowError error) | ||
{ | ||
console.MarkupLineInterpolated($"[red]Error:[/] {error.FullMessage}"); | ||
return 2; | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/FlowPair/Agent/Operations/ReviewChanges/ContentDeserializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System.Collections.Immutable; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization.Metadata; | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges.v1; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges; | ||
|
||
public static class ContentDeserializer | ||
{ | ||
public static ImmutableList<ReviewerFeedbackResponse> TryDeserializeFeedback( | ||
ReadOnlySpan<char> content, | ||
JsonTypeInfo<ImmutableList<ReviewerFeedbackResponse>> typeInfo) | ||
{ | ||
if (content.IsWhiteSpace()) | ||
return []; | ||
|
||
while (!content.IsEmpty) | ||
{ | ||
var start = content.IndexOf('['); | ||
if (start < 0) | ||
return []; | ||
|
||
var end = content.IndexOf(']'); | ||
if (end < start) | ||
return []; | ||
|
||
try | ||
{ | ||
return JsonSerializer.Deserialize(content[start..(end + 1)], typeInfo) ?? []; | ||
} | ||
catch (JsonException) | ||
{ | ||
content = content[(end + 1)..]; | ||
} | ||
} | ||
|
||
return []; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ent/ReviewChanges/FeedbackHtmlTemplate.tt → ...ons/ReviewChanges/FeedbackHtmlTemplate.tt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...wPair/Agent/ReviewChanges/Instructions.cs → .../Operations/ReviewChanges/Instructions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
src/FlowPair/Agent/Operations/ReviewChanges/ReviewChangesCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using System.Collections.Immutable; | ||
using System.IO.Abstractions; | ||
using System.Text; | ||
using Ciandt.FlowTools.FlowPair.Agent.Infrastructure; | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.Login; | ||
using Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges.v1; | ||
using Ciandt.FlowTools.FlowPair.ChangeTracking; | ||
using Ciandt.FlowTools.FlowPair.Common; | ||
using Ciandt.FlowTools.FlowPair.Flow.Operations.ProxyCompleteChat; | ||
using Ciandt.FlowTools.FlowPair.Flow.Operations.ProxyCompleteChat.v1; | ||
using Ciandt.FlowTools.FlowPair.Support.Persistence; | ||
using Ciandt.FlowTools.FlowPair.Support.Presentation; | ||
using ConsoleAppFramework; | ||
using Spectre.Console; | ||
|
||
namespace Ciandt.FlowTools.FlowPair.Agent.Operations.ReviewChanges; | ||
|
||
public class ReviewChangesCommand( | ||
IAnsiConsole console, | ||
IFileSystem fileSystem, | ||
AgentJsonContext jsonContext, | ||
IGitDiffExtractor gitDiffExtractor, | ||
ILoginUseCase loginUseCase, | ||
IProxyCompleteChatHandler completeChatHandler) | ||
{ | ||
/// <summary> | ||
/// Review changed files using Flow. | ||
/// </summary> | ||
[Command("review")] | ||
public int Execute() | ||
{ | ||
return (from diff in gitDiffExtractor.Extract().OkOr(0) | ||
from session in loginUseCase.Execute(isBackground: true) | ||
.UnwrapErrOr(0) | ||
.Ensure(n => n == 0, 1) | ||
from feedback in BuildFeedback(diff) | ||
select 0) | ||
.UnwrapEither(); | ||
} | ||
|
||
private Result<Unit, int> BuildFeedback(ImmutableList<FileChange> changes) | ||
{ | ||
var feedback = changes | ||
.GroupBy(c => Instructions.FindInstructionsForFile(Instructions.Default, c.Path)) | ||
.Where(g => g.Key.IsSome) | ||
.Select(g => new { Instructions = g.Key.Unwrap(), Diff = g.AggregateToStringLines(c => c.Diff) }) | ||
.SelectMany(x => GetFeedback(AllowedModel.Claude35Sonnet, x.Diff, x.Instructions)) | ||
.Where(f => !string.IsNullOrWhiteSpace(f.Feedback)) | ||
.OrderByDescending(x => x.RiskScore).ThenBy(x => x.Path, StringComparer.OrdinalIgnoreCase) | ||
.ToImmutableList(); | ||
|
||
console.WriteLine($"Created {feedback.Count} comments"); | ||
|
||
if (feedback.Count > 0) | ||
{ | ||
var tempPath = ApplicationData.GetTempPath(fileSystem); | ||
tempPath.Create(); | ||
|
||
var feedbackFilePath = tempPath.NewFile($"{DateTime.UtcNow:yyyyMMddHHmmss}-feedback.html"); | ||
|
||
var htmlContent = new FeedbackHtmlTemplate(feedback).TransformText(); | ||
feedbackFilePath.WriteAllText(htmlContent, Encoding.UTF8); | ||
|
||
FileLauncher.OpenFile(feedbackFilePath.FullName); | ||
} | ||
|
||
return Unit(); | ||
} | ||
|
||
private ImmutableList<ReviewerFeedbackResponse> GetFeedback( | ||
AllowedModel model, | ||
string diff, | ||
Instructions instructions) | ||
{ | ||
var result = completeChatHandler.ChatCompletion( | ||
model, | ||
[new Message(Role.System, instructions.Message), new Message(Role.User, diff)]); | ||
|
||
if (!result.IsOk) | ||
{ | ||
console.MarkupLineInterpolated($"[bold red]Error:[/] {result.UnwrapErr().ToString()}"); | ||
return []; | ||
} | ||
|
||
var feedback = ContentDeserializer.TryDeserializeFeedback( | ||
result.Unwrap().Content, | ||
jsonContext.ImmutableListReviewerFeedbackResponse); | ||
return feedback; | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...iewChanges/v1/ReviewerFeedbackResponse.cs → ...iewChanges/v1/ReviewerFeedbackResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.