Ryan Sweet 458d273fc4
Refactoring the services and implementing an in-memory runtime for .NET (#4005)
closes #3950 closes #3702

What this is doing:

I am refactoring the services on the .NET runtime and attempting to clarify the naming and organization.
I added this doc to help capture the naming and concepts.
AgentRuntime / Worker should work similar to the python version and enables running the whole agent system in one process. For remote the system uses the versions of the services in the grpc folder.
lots of other bug fixes/threading cleanup - passing cancellation token throughout
Services update clarifies the naming and roles:

Worker: Hosts the Agents and is a client to the Gateway
Gateway:
-- RPC gateway for the other services APIs
-- Provides an RPC bridge between the workers and the Event Bus
Registry: keeps track of the agents in the system and which events they can handle
AgentState: persistent state for agents
2024-11-12 11:04:59 -08:00

93 lines
3.8 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved.
// Hubber.cs
using System.Text.Json;
using DevTeam;
using DevTeam.Backend;
using DevTeam.Shared;
using Microsoft.AutoGen.Abstractions;
using Microsoft.AutoGen.Agents;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Memory;
namespace Microsoft.AI.DevTeam;
public class Hubber(IAgentRuntime context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, IManageGithub ghService)
: SKAiAgent<object>(context, memory, kernel, typeRegistry),
IHandle<NewAsk>,
IHandle<ReadmeGenerated>,
IHandle<DevPlanGenerated>,
IHandle<DevPlanCreated>,
IHandle<ReadmeStored>,
IHandle<CodeGenerated>
{
public async Task Handle(NewAsk item)
{
var pmIssue = await CreateIssue(item.Org, item.Repo, item.Ask, "PM.Readme", item.IssueNumber);
var devLeadIssue = await CreateIssue(item.Org, item.Repo, item.Ask, "DevLead.Plan", item.IssueNumber);
await PostComment(item.Org, item.Repo, item.IssueNumber, $" - #{pmIssue} - tracks PM.Readme");
await PostComment(item.Org, item.Repo, item.IssueNumber, $" - #{devLeadIssue} - tracks DevLead.Plan");
await CreateBranch(item.Org, item.Repo, $"sk-{item.IssueNumber}");
}
public async Task Handle(ReadmeGenerated item)
{
var contents = string.IsNullOrEmpty(item.Readme) ? "Sorry, I got tired, can you try again please? " : item.Readme;
await PostComment(item.Org, item.Repo, item.IssueNumber, contents);
}
public async Task Handle(DevPlanGenerated item)
{
var contents = string.IsNullOrEmpty(item.Plan) ? "Sorry, I got tired, can you try again please? " : item.Plan;
await PostComment(item.Org, item.Repo, item.IssueNumber, contents);
}
public async Task Handle(CodeGenerated item)
{
var contents = string.IsNullOrEmpty(item.Code) ? "Sorry, I got tired, can you try again please? " : item.Code;
await PostComment(item.Org, item.Repo, item.IssueNumber, contents);
}
public async Task Handle(DevPlanCreated item)
{
var plan = JsonSerializer.Deserialize<DevLeadPlan>(item.Plan);
var prompts = plan!.Steps.SelectMany(s => s.Subtasks!.Select(st => st.Prompt));
foreach (var prompt in prompts)
{
var functionName = "Developer.Implement";
var issue = await CreateIssue(item.Org, item.Repo, prompt!, functionName, item.IssueNumber);
var commentBody = $" - #{issue} - tracks {functionName}";
await PostComment(item.Org, item.Repo, item.IssueNumber, commentBody);
}
}
public async Task Handle(ReadmeStored item)
{
var branch = $"sk-{item.ParentNumber}";
await CommitToBranch(item.Org, item.Repo, item.ParentNumber, item.IssueNumber, "output", branch);
await CreatePullRequest(item.Org, item.Repo, item.ParentNumber, branch);
}
public async Task<int> CreateIssue(string org, string repo, string input, string function, long parentNumber)
{
return await ghService.CreateIssue(org, repo, input, function, parentNumber);
}
public async Task PostComment(string org, string repo, long issueNumber, string comment)
{
await ghService.PostComment(org, repo, issueNumber, comment);
}
public async Task CreateBranch(string org, string repo, string branch)
{
await ghService.CreateBranch(org, repo, branch);
}
public async Task CreatePullRequest(string org, string repo, long issueNumber, string branch)
{
await ghService.CreatePR(org, repo, issueNumber, branch);
}
public async Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch)
{
await ghService.CommitToBranch(org, repo, parentNumber, issueNumber, rootDir, branch);
}
}