feat(a2a): scaffold the A2A server library and its tests

This commit is contained in:
EugeneTes
2026-10-07 12:18:18 +00:00
parent 99528d003f
commit 39c9c2467f
7 changed files with 108 additions and 0 deletions

View File

@@ -15,10 +15,12 @@
<Project Path="samples/Volcanic.AgenticCore.Sample.Headless/Volcanic.AgenticCore.Sample.Headless.csproj" />
</Folder>
<Folder Name="/src/">
<Project Path="src/Volcanic.AgenticCore.A2A.Server/Volcanic.AgenticCore.A2A.Server.csproj" />
<Project Path="src/Volcanic.AgenticCore.Abstractions/Volcanic.AgenticCore.Abstractions.csproj" />
<Project Path="src/Volcanic.AgenticCore/Volcanic.AgenticCore.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/Volcanic.AgenticCore.A2A.Server.Tests/Volcanic.AgenticCore.A2A.Server.Tests.csproj" />
<Project Path="tests/Volcanic.AgenticCore.Extensions.Tests/Volcanic.AgenticCore.Extensions.Tests.csproj" />
<Project Path="tests/Volcanic.AgenticCore.Extensions.Tests.FakeMcpServer/Volcanic.AgenticCore.Extensions.Tests.FakeMcpServer.csproj" />
<Project Path="tests/Volcanic.AgenticCore.HardeningProbe/Volcanic.AgenticCore.HardeningProbe.csproj" />

View File

@@ -0,0 +1,43 @@
using System.Text.Json;
namespace Volcanic.AgenticCore.A2A.Server;
/// <summary>The <c>A2A</c> configuration section (env <c>A2A__…</c>).</summary>
public sealed class A2AHostOptions
{
public const string SectionName = "A2A";
/// <summary>Mount the endpoints. Off means the Telegram host starts no HTTP listener.</summary>
public bool Enabled { get; set; }
/// <summary>External base URL, used in the card's interfaces and for push webhook URLs. Unset: built from the request.</summary>
public string? PublicUrl { get; set; }
public int MaxHops { get; set; } = 3;
public TimeSpan SessionIdleTimeout { get; set; } = TimeSpan.FromMinutes(30);
public long MaxFileBytes { get; set; } = 10 * 1024 * 1024;
/// <summary>Allow caller webhooks on http and on loopback/private ranges (tests, tailnet).</summary>
public bool AllowPrivatePushUrls { get; set; }
public A2ACardOptions Card { get; set; } = new();
/// <summary><c>provider/model</c> for server sessions; null uses the core default.</summary>
public string? Model { get; set; }
/// <summary>Time zone of a caller's session; null uses the core default.</summary>
public Func<Callers.A2ACaller, TimeZoneInfo?>? TimeZoneFor { get; set; }
/// <summary>
/// Receives pushes for our own client's watches: (watchId, token, body) → handled. False answers 404.
/// Null: the receiver endpoint answers 404 to everything.
/// </summary>
public Func<string, string?, JsonElement, CancellationToken, Task<bool>>? OnPush { get; set; }
}
public sealed class A2ACardOptions
{
public string Name { get; set; } = "Volcanic assistant";
public string Description { get; set; } =
"A Volcanic agent. Authenticate with an API key (X-API-Key header) to see what this assistant does.";
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>A2A (Agent2Agent) server for Volcanic agent sessions, on the official A2A .NET SDK.</Description>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<ProjectReference Include="../Volcanic.AgenticCore/Volcanic.AgenticCore.csproj" />
<PackageReference Include="A2A.AspNetCore" Version="1.0.0-preview2" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Volcanic.AgenticCore.A2A.Server.Tests" />
<InternalsVisibleTo Include="Volcanic.AgenticCore.Telegram" />
<InternalsVisibleTo Include="Volcanic.AgenticCore.Telegram.Tests" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1 @@
global using Xunit;

View File

@@ -0,0 +1,16 @@
namespace Volcanic.AgenticCore.A2A.Server.Tests;
public class OptionsTests
{
[Fact]
public void Defaults_MatchSpec()
{
var o = new A2AHostOptions();
Assert.False(o.Enabled);
Assert.Equal(3, o.MaxHops);
Assert.Equal(TimeSpan.FromMinutes(30), o.SessionIdleTimeout);
Assert.Equal(10 * 1024 * 1024, o.MaxFileBytes);
Assert.False(o.AllowPrivatePushUrls);
Assert.Equal("Volcanic assistant", o.Card.Name);
}
}

View File

@@ -0,0 +1,13 @@
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging.Abstractions;
using Volcanic.AgenticCore.Features.Processes;
namespace Volcanic.AgenticCore.A2A.Server.Tests.Support;
/// <summary>Consumes the process-wide hardening call with the flag off, so the test runner stays debuggable.</summary>
internal static class NoHostHardening
{
[ModuleInitializer]
internal static void Disable() =>
HostProcessHardening.Apply(new ProcessEnvironmentOptions { HardenHostProcess = false }, NullLogger.Instance);
}

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/Volcanic.AgenticCore.A2A.Server/Volcanic.AgenticCore.A2A.Server.csproj" />
</ItemGroup>
</Project>