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
11 changes: 10 additions & 1 deletion dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ protected sealed override ValueTask<AgentSession> CreateSessionCoreAsync(Cancell
/// <param name="contextId">The context id to continue.</param>
/// <returns>A value task representing the asynchronous operation. The task result contains a new <see cref="AgentSession"/> instance.</returns>
public ValueTask<AgentSession> CreateSessionAsync(string contextId)
=> new(new A2AAgentSession() { ContextId = contextId });
=> new(new A2AAgentSession() { ContextId = Throw.IfNullOrWhitespace(contextId) });

/// <summary>
/// Get a new <see cref="AgentSession"/> instance using an existing context id and task id, to resume that conversation from a specific task.
/// </summary>
/// <param name="contextId">The context id to continue.</param>
/// <param name="taskId">The task id to resume from.</param>
/// <returns>A value task representing the asynchronous operation. The task result contains a new <see cref="AgentSession"/> instance.</returns>
public ValueTask<AgentSession> CreateSessionAsync(string contextId, string taskId)
=> new(new A2AAgentSession() { ContextId = Throw.IfNullOrWhitespace(contextId), TaskId = Throw.IfNullOrWhitespace(taskId) });

/// <inheritdoc/>
protected override ValueTask<JsonElement> SerializeSessionCoreAsync(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
Expand Down
94 changes: 94 additions & 0 deletions dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,100 @@ public void GetService_RequestingAIAgentMetadata_ReturnsConsistentMetadata()
Assert.Equal("a2a", metadata.ProviderName);
}

/// <summary>
/// Verify that CreateSessionAsync with contextId creates a session with the correct context ID.
/// </summary>
[Fact]
public async Task CreateSessionAsync_WithContextId_CreatesSessionWithContextIdAsync()
{
// Arrange
const string ContextId = "test-context-123";

// Act
var session = await this._agent.CreateSessionAsync(ContextId);

// Assert
Assert.NotNull(session);
Assert.IsType<A2AAgentSession>(session);
var typedSession = (A2AAgentSession)session;
Assert.Equal(ContextId, typedSession.ContextId);
Assert.Null(typedSession.TaskId);
}

/// <summary>
/// Verify that CreateSessionAsync with contextId and taskId creates a session with both IDs set correctly.
/// </summary>
[Fact]
public async Task CreateSessionAsync_WithContextIdAndTaskId_CreatesSessionWithBothIdsAsync()
{
// Arrange
const string ContextId = "test-context-456";
const string TaskId = "test-task-789";

// Act
var session = await this._agent.CreateSessionAsync(ContextId, TaskId);

// Assert
Assert.NotNull(session);
Assert.IsType<A2AAgentSession>(session);
var typedSession = (A2AAgentSession)session;
Assert.Equal(ContextId, typedSession.ContextId);
Assert.Equal(TaskId, typedSession.TaskId);
}

/// <summary>
/// Verify that CreateSessionAsync throws when contextId is null, empty, or whitespace.
/// </summary>
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
[InlineData("\t")]
[InlineData("\r\n")]
public async Task CreateSessionAsync_WithInvalidContextId_ThrowsArgumentExceptionAsync(string? contextId)
{
// Act & Assert
await Assert.ThrowsAnyAsync<ArgumentException>(async () =>
await this._agent.CreateSessionAsync(contextId!));
}

/// <summary>
/// Verify that CreateSessionAsync with both parameters throws when contextId is null, empty, or whitespace.
/// </summary>
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
[InlineData("\t")]
[InlineData("\r\n")]
public async Task CreateSessionAsync_WithInvalidContextIdAndValidTaskId_ThrowsArgumentExceptionAsync(string? contextId)
{
// Arrange
const string TaskId = "valid-task-id";

// Act & Assert
await Assert.ThrowsAnyAsync<ArgumentException>(async () =>
await this._agent.CreateSessionAsync(contextId!, TaskId));
}

/// <summary>
/// Verify that CreateSessionAsync with both parameters throws when taskId is null, empty, or whitespace.
/// </summary>
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
[InlineData("\t")]
[InlineData("\r\n")]
public async Task CreateSessionAsync_WithValidContextIdAndInvalidTaskId_ThrowsArgumentExceptionAsync(string? taskId)
{
// Arrange
const string ContextId = "valid-context-id";

// Act & Assert
await Assert.ThrowsAnyAsync<ArgumentException>(async () =>
await this._agent.CreateSessionAsync(ContextId, taskId!));
}
#endregion

public void Dispose()
Expand Down
Loading