Skip to content

Commit

Permalink
Merge branch 'main' into rysweet-grpc-service
Browse files Browse the repository at this point in the history
  • Loading branch information
rysweet authored Feb 7, 2025
2 parents fbbcfdc + 4c1c12d commit 9b47878
Show file tree
Hide file tree
Showing 36 changed files with 911 additions and 501 deletions.
95 changes: 38 additions & 57 deletions .github/workflows/dotnet-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ jobs:
- name: workflows has changes
run: echo "workflows has changes"
if: steps.filter.outputs.workflows == 'true'

build:
name: Dotnet Build
name: Dotnet Build & Test
needs: paths-filter
if: needs.paths-filter.outputs.hasChanges == 'true'
defaults:
Expand All @@ -64,35 +65,12 @@ jobs:
- uses: actions/checkout@v4
with:
lfs: true
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install jupyter and ipykernel
run: |
python -m pip install --upgrade pip
python -m pip install jupyter
python -m pip install ipykernel
- name: list available kernels
run: |
python -m jupyter kernelspec list
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
version: "0.5.18"
- run: uv sync --locked --all-extras
working-directory: ./python
- name: Prepare python venv
run: |
source ${{ github.workspace }}/python/.venv/bin/activate
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: |
# dotnet nuget add source --name dotnet-tool https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json --configfile NuGet.config
dotnet restore -bl
run: dotnet restore -bl
- name: Format check
run: |
echo "Format check"
Expand All @@ -104,40 +82,43 @@ jobs:
dotnet build --no-restore --configuration Release -bl /p:SignAssembly=true
- name: Unit Test V1
run: dotnet test --no-build -bl --configuration Release --filter "Category=UnitV1"
- name: Unit Test V2
run: dotnet test --no-build -bl --configuration Release --filter "Category=UnitV2"

grpc-unit-tests:
name: Dotnet Grpc unit tests
needs: paths-filter
if: needs.paths-filter.outputs.hasChanges == 'true'
defaults:
run:
working-directory: dotnet
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Unit Test V2 (With Coverage)
run: dotnet test --no-build -bl --configuration Release --filter "Category=UnitV2" --collect:"XPlat Code Coverage"
- name: Install Dev Certs for GRPC
if: matrix.os == 'ubuntu-latest'
run: dotnet dev-certs https --trust
- name: GRPC Tests (With Coverage)
if: matrix.os == 'ubuntu-latest'
run: dotnet test --no-build -bl --configuration Release --filter "Category=GRPC" --collect:"XPlat Code Coverage"
- name: Generate & Merge Coverage Report
if: matrix.os == 'ubuntu-latest'
run: |
# Install reportgenerator
dotnet tool install -g dotnet-reportgenerator-globaltool || dotnet tool update -g dotnet-reportgenerator-globaltool
# Ensure output directory exists
mkdir -p ${{ github.workspace }}/dotnet/coverage-report
# Merge all coverage reports and generate HTML + XML
reportgenerator \
-reports:${{ github.workspace }}/dotnet/**/TestResults/**/coverage.cobertura.xml \
-targetdir:${{ github.workspace }}/dotnet/coverage-report \
-reporttypes:"Cobertura;Html"
ls -R ${{ github.workspace }}/dotnet/coverage-report
- name: Upload Merged Coverage Report
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
lfs: true
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v4
name: CodeCoverageReport
path: ${{ github.workspace }}/dotnet/coverage-report/
retention-days: 7
- name: Upload Coverage to Codecov
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5
with:
dotnet-version: '8.0.x'
- name: Install dev certs
run: dotnet --version && dotnet dev-certs https --trust
- name: Restore dependencies
run: |
# dotnet nuget add source --name dotnet-tool https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json --configfile NuGet.config
dotnet restore -bl
- name: Build
run: dotnet build --no-restore --configuration Release -bl /p:SignAssembly=true
- name: GRPC tests
run: dotnet test --no-build -bl --configuration Release --filter "Category=GRPC"
files: ${{ github.workspace }}/dotnet/coverage-report/*.xml
flags: unittests
name: dotnet-codecov
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

integration-test:
strategy:
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Integration

on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to run tests'
required: true
type: string

jobs:
test:
runs-on: ubuntu-latest
environment: integration
strategy:
matrix:
package:
[
"./packages/autogen-core",
"./packages/autogen-ext",
"./packages/autogen-agentchat",
]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch }}
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
version: "0.5.18"
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Run uv sync
run: |
uv sync --locked --all-extras
echo "PKG_NAME=$(basename '${{ matrix.package }}')" >> $GITHUB_ENV
working-directory: ./python
- name: Run task
run: |
source ${{ github.workspace }}/python/.venv/bin/activate
poe --directory ${{ matrix.package }} test
working-directory: ./python

- name: Move coverage file
run: |
mv ${{ matrix.package }}/coverage.xml coverage_${{ env.PKG_NAME }}.xml
working-directory: ./python

- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-${{ env.PKG_NAME }}
path: ./python/coverage_${{ env.PKG_NAME }}.xml
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
[![LinkedIn](https://img.shields.io/badge/LinkedIn-Company?style=flat&logo=linkedin&logoColor=white)](https://www.linkedin.com/company/105812540)
[![Discord](https://img.shields.io/badge/discord-chat-green?logo=discord)](https://aka.ms/autogen-discord)
[![Documentation](https://img.shields.io/badge/Documentation-AutoGen-blue?logo=read-the-docs)](https://microsoft.github.io/autogen/)
[![Blog](https://img.shields.io/badge/Blog-AutoGen-blue?logo=blogger)](https://devblogs.microsoft.com/autogen/)

</div>

<div align="center" style="background-color: rgba(255, 235, 59, 0.5); padding: 10px; border-radius: 5px; margin: 20px 0;">
<strong>Important:</strong> This is the official project. We are not affiliated with any fork or startup. See our <a href="https://x.com/pyautogen/status/1857264760951296210">statement</a>.
</div>

# AutoGen

**AutoGen** is a framework for creating multi-agent AI applications that can act autonomously or work alongside humans.
Expand Down Expand Up @@ -130,7 +135,7 @@ With AutoGen you get to join and contribute to a thriving ecosystem. We host wee

Interested in contributing? See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to get started. We welcome contributions of all kinds, including bug fixes, new features, and documentation improvements. Join our community and help us make AutoGen better!

Have questions? Check out our [Frequently Asked Questions (FAQ)](./FAQ.md) for answers to common queries. If you don't find what you're looking for, feel free to ask in our [GitHub Discussions](https://github.com/microsoft/autogen/discussions) or join our [Discord server](https://aka.ms/autogen-discord) for real-time support.
Have questions? Check out our [Frequently Asked Questions (FAQ)](./FAQ.md) for answers to common queries. If you don't find what you're looking for, feel free to ask in our [GitHub Discussions](https://github.com/microsoft/autogen/discussions) or join our [Discord server](https://aka.ms/autogen-discord) for real-time support. You can also read our [blog](https://devblogs.microsoft.com/autogen/) for updates.

## Legal Notices

Expand Down
6 changes: 4 additions & 2 deletions dotnet/src/Microsoft.AutoGen/Contracts/AgentProxy.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// AgentProxy.cs

using System.Text.Json;

namespace Microsoft.AutoGen.Contracts;

/// <summary>
Expand Down Expand Up @@ -55,7 +57,7 @@ private T ExecuteAndUnwrap<T>(Func<IAgentRuntime, ValueTask<T>> delegate_)
/// </summary>
/// <param name="state">A dictionary representing the state of the agent. Must be JSON serializable.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public ValueTask LoadStateAsync(IDictionary<string, object> state)
public ValueTask LoadStateAsync(IDictionary<string, JsonElement> state)
{
return this.runtime.LoadAgentStateAsync(this.Id, state);
}
Expand All @@ -64,7 +66,7 @@ public ValueTask LoadStateAsync(IDictionary<string, object> state)
/// Saves the state of the agent. The result must be JSON serializable.
/// </summary>
/// <returns>A task representing the asynchronous operation, returning a dictionary containing the saved state.</returns>
public ValueTask<IDictionary<string, object>> SaveStateAsync()
public ValueTask<IDictionary<string, JsonElement>> SaveStateAsync()
{
return this.runtime.SaveAgentStateAsync(this.Id);
}
Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/Microsoft.AutoGen/Contracts/IAgentRuntime.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// IAgentRuntime.cs

using StateDict = System.Collections.Generic.IDictionary<string, object>;
using StateDict = System.Collections.Generic.IDictionary<string, System.Text.Json.JsonElement>;

namespace Microsoft.AutoGen.Contracts;

Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/Microsoft.AutoGen/Contracts/ISaveState.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ISaveState.cs

using StateDict = System.Collections.Generic.IDictionary<string, object>;
using StateDict = System.Collections.Generic.IDictionary<string, System.Text.Json.JsonElement>;

namespace Microsoft.AutoGen.Contracts;

Expand Down
39 changes: 22 additions & 17 deletions dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// GrpcAgentRuntime.cs

using System.Collections.Concurrent;
using System.Text.Json;
using Grpc.Core;
using Microsoft.AutoGen.Contracts;
using Microsoft.AutoGen.Protobuf;
Expand Down Expand Up @@ -321,13 +322,13 @@ public async ValueTask PublishMessageAsync(object message, TopicId topic, Contra
public ValueTask<Contracts.AgentId> GetAgentAsync(string agent, string key = "default", bool lazy = true)
=> this.GetAgentAsync(new Contracts.AgentId(agent, key), lazy);

public async ValueTask<IDictionary<string, object>> SaveAgentStateAsync(Contracts.AgentId agentId)
public async ValueTask<IDictionary<string, JsonElement>> SaveAgentStateAsync(Contracts.AgentId agentId)
{
IHostableAgent agent = await this._agentsContainer.EnsureAgentAsync(agentId);
return await agent.SaveStateAsync();
}

public async ValueTask LoadAgentStateAsync(Contracts.AgentId agentId, IDictionary<string, object> state)
public async ValueTask LoadAgentStateAsync(Contracts.AgentId agentId, IDictionary<string, JsonElement> state)
{
IHostableAgent agent = await this._agentsContainer.EnsureAgentAsync(agentId);
await agent.LoadStateAsync(state);
Expand Down Expand Up @@ -377,37 +378,41 @@ public ValueTask<AgentProxy> TryGetAgentProxyAsync(Contracts.AgentId agentId)
return ValueTask.FromResult(new AgentProxy(agentId, this));
}

public async ValueTask<IDictionary<string, object>> SaveStateAsync()
{
Dictionary<string, object> state = new();
foreach (var agent in this._agentsContainer.LiveAgents)
{
state[agent.Id.ToString()] = await agent.SaveStateAsync();
}

return state;
}

public async ValueTask LoadStateAsync(IDictionary<string, object> state)
public async ValueTask LoadStateAsync(IDictionary<string, JsonElement> state)
{
HashSet<AgentType> registeredTypes = this._agentsContainer.RegisteredAgentTypes;

foreach (var agentIdStr in state.Keys)
{
Contracts.AgentId agentId = Contracts.AgentId.FromStr(agentIdStr);
if (state[agentIdStr] is not IDictionary<string, object> agentStateDict)

if (state[agentIdStr].ValueKind != JsonValueKind.Object)
{
throw new Exception($"Agent state for {agentId} is not a {typeof(IDictionary<string, object>)}: {state[agentIdStr].GetType()}");
throw new Exception($"Agent state for {agentId} is not a valid JSON object.");
}

var agentState = JsonSerializer.Deserialize<IDictionary<string, JsonElement>>(state[agentIdStr].GetRawText())
?? throw new Exception($"Failed to deserialize state for {agentId}.");

if (registeredTypes.Contains(agentId.Type))
{
IHostableAgent agent = await this._agentsContainer.EnsureAgentAsync(agentId);
await agent.LoadStateAsync(agentStateDict);
await agent.LoadStateAsync(agentState);
}
}
}

public async ValueTask<IDictionary<string, JsonElement>> SaveStateAsync()
{
Dictionary<string, JsonElement> state = new();
foreach (var agent in this._agentsContainer.LiveAgents)
{
var agentState = await agent.SaveStateAsync();
state[agent.Id.ToString()] = JsonSerializer.SerializeToElement(agentState);
}
return state;
}

public async ValueTask OnMessageAsync(Message message, CancellationToken cancellation = default)
{
switch (message.MessageCase)
Expand Down
7 changes: 4 additions & 3 deletions dotnet/src/Microsoft.AutoGen/Core/BaseAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
using Microsoft.AutoGen.Contracts;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -92,11 +93,11 @@ private Dictionary<Type, HandlerInvoker> ReflectInvokers()
return null;
}

public virtual ValueTask<IDictionary<string, object>> SaveStateAsync()
public virtual ValueTask<IDictionary<string, JsonElement>> SaveStateAsync()
{
return ValueTask.FromResult<IDictionary<string, object>>(new Dictionary<string, object>());
return ValueTask.FromResult<IDictionary<string, JsonElement>>(new Dictionary<string, JsonElement>());
}
public virtual ValueTask LoadStateAsync(IDictionary<string, object> state)
public virtual ValueTask LoadStateAsync(IDictionary<string, JsonElement> state)
{
return ValueTask.CompletedTask;
}
Expand Down
Loading

0 comments on commit 9b47878

Please sign in to comment.