Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/A2A.Client/A2A.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<RepositoryUrl>https://github.com/neuroglia-io/a2a</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<DebugType>embedded</DebugType>
<NoWarn>$(NoWarn);Undefined</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
57 changes: 36 additions & 21 deletions tools/A2A.ClientConsole/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using A2A;
using A2A.Client;
using A2A.Models;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console;
using Spectre.Console.Rendering;
Expand Down Expand Up @@ -246,22 +245,27 @@ async Task RunInteractionLoopAsync()
async Task ChatAsync()
{
DisplayNewPage();
var contextId = Guid.NewGuid().ToString("N");
var taskId = (string?)null;
CollectInput:
AnsiConsole.WriteLine();
var userInput = AnsiConsole.Ask<string>("[bold blue]You:[/]");
var userMessage = new Message
{
ContextId = contextId,
TaskId = taskId,
Role = Role.User,
Parts = [new TextPart { Text = userInput }]
};
var request = new SendMessageRequest
{
Message = userMessage
};

try
{
var cancellationTokenSource = new CancellationTokenSource();
var supportsStreaming = agentCard!.Capabilities?.Streaming == true;
var currentTaskId = (string?)null;
var loop = false;
if (supportsStreaming)
{
var responseText = new StringBuilder();
Expand All @@ -272,8 +276,8 @@ async Task ChatAsync()
{
if (streamResponse.Task != null)
{
currentTaskId = streamResponse.Task.Id;
AnsiConsole.MarkupLine($"\n[blue]Agent:[/] [dim]Task started: {currentTaskId}[/]");
taskId = streamResponse.Task.Id;
AnsiConsole.MarkupLine($"\n[blue]Agent:[/] [dim]Task started: {taskId}[/]");
AnsiConsole.MarkupLine("[blue]Agent:[/] [dim]Status: {0}[/]", streamResponse.Task.Status?.State ?? "unknown");
if (streamResponse.Task.Artifacts != null)
{
Expand All @@ -285,7 +289,7 @@ async Task ChatAsync()
if (part is TextPart textPart)
{
responseText.Append(textPart.Text);
AnsiConsole.Markup(textPart.Text);
AnsiConsole.Write(textPart.Text);
}
}
}
Expand All @@ -298,13 +302,32 @@ async Task ChatAsync()
if (part is TextPart textPart)
{
responseText.Append(textPart.Text);
AnsiConsole.Markup(textPart.Text);
AnsiConsole.Write(textPart.Text);
}
}
AnsiConsole.WriteLine();
}
else if (streamResponse.StatusUpdate != null)
{
AnsiConsole.MarkupLine($"\n[blue]Agent:[/] [dim]Task status: {streamResponse.StatusUpdate.Status?.State}[/]");
if (streamResponse.StatusUpdate.Status?.Message is not null)
{
foreach (var part in streamResponse.StatusUpdate.Status.Message.Parts)
{
switch (part)
{
case TextPart textPart:
AnsiConsole.Write(textPart.Text);
break;
}
}
AnsiConsole.WriteLine();
}
if (streamResponse.StatusUpdate.Status?.State == TaskState.InputRequired)
{
loop = true;
break;
}
}
else if (streamResponse.ArtifactUpdate != null)
{
Expand All @@ -314,7 +337,7 @@ async Task ChatAsync()
switch (part)
{
case TextPart textPart:
AnsiConsole.Markup(textPart.Text);
AnsiConsole.Write(textPart.Text);
break;
}
}
Expand All @@ -326,11 +349,11 @@ async Task ChatAsync()
{
if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.C)
{
if (currentTaskId != null)
if (taskId != null)
{
try
{
await client!.CancelTaskAsync(currentTaskId);
await client!.CancelTaskAsync(taskId);
AnsiConsole.MarkupLine("\n[yellow]Task cancelled.[/]");
}
catch (Exception ex)
Expand All @@ -350,15 +373,7 @@ async Task ChatAsync()
{
AnsiConsole.MarkupLine("\n[yellow]Operation cancelled.[/]");
}

if (responseText.Length > 0)
{
var agentMessage = new Message
{
Role = Role.Agent,
Parts = [new TextPart { Text = responseText.ToString() }]
};
}
if (loop) goto CollectInput;
}
else
{
Expand All @@ -378,8 +393,8 @@ async Task ChatAsync()
}
else if (response is A2A.Models.Task task)
{
currentTaskId = task.Id;
AnsiConsole.MarkupLine($"[yellow]⚙ Task created: {currentTaskId}[/]");
taskId = task.Id;
AnsiConsole.MarkupLine($"[yellow]⚙ Task created: {taskId}[/]");
AnsiConsole.MarkupLine($"[dim]Status: {task.Status?.State ?? "unknown"}[/]");
}
}
Expand Down