mirror of https://github.com/microsoft/autogen.git
Merge 39d79b0064
into 51b361dfcf
This commit is contained in:
commit
f3499e212a
|
@ -86,8 +86,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AutoGen.Extension
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AutoGen.Runtime", "src\Microsoft.AutoGen\Runtime\Microsoft.AutoGen.Runtime.csproj", "{A905E29A-7110-497F-ADC5-2CE2A148FEA0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AutoGen.ServiceDefaults", "src\Microsoft.AutoGen\ServiceDefaults\Microsoft.AutoGen.ServiceDefaults.csproj", "{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AgentChat", "AgentChat", "{668726B9-77BC-45CF-B576-0F0773BF1615}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoGen.Anthropic.Samples", "samples\AutoGen.Anthropic.Samples\AutoGen.Anthropic.Samples.csproj", "{84020C4A-933A-4693-9889-1B99304A7D76}"
|
||||
|
@ -134,6 +132,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{686480
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloAgentState", "samples\Hello\HelloAgentState\HelloAgentState.csproj", "{64EF61E7-00A6-4E5E-9808-62E10993A0E5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MarketingTeam", "MarketingTeam", "{ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.AgentHost", "samples\marketing-team\Marketing.AgentHost\Marketing.AgentHost.csproj", "{6C796ACE-9599-4D55-AA0D-F1615B2D8C42}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.Agents", "samples\marketing-team\Marketing.Agents\Marketing.Agents.csproj", "{7EF1F26A-85BF-4C6F-8891-331C44B5802B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.AppHost", "samples\marketing-team\Marketing.AppHost\Marketing.AppHost.csproj", "{31DC6301-E354-46AA-BA0A-BED38AED8D36}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.Backend", "samples\marketing-team\Marketing.Backend\Marketing.Backend.csproj", "{60132BCE-0E8B-4E13-AEB0-919BC795E068}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.ServiceDefaults", "samples\marketing-team\Marketing.ServiceDefaults\Marketing.ServiceDefaults.csproj", "{F7C5E0CD-6FDA-4118-B419-74377C9CFD27}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.Shared", "samples\marketing-team\Marketing.Shared\Marketing.Shared.csproj", "{06CD34BB-93BF-467D-891A-91C44F0CD423}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevTeam.ServiceDefaults", "samples\dev-team\DevTeam.ServiceDefaults\DevTeam.ServiceDefaults.csproj", "{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -268,10 +282,6 @@ Global
|
|||
{A905E29A-7110-497F-ADC5-2CE2A148FEA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A905E29A-7110-497F-ADC5-2CE2A148FEA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A905E29A-7110-497F-ADC5-2CE2A148FEA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{84020C4A-933A-4693-9889-1B99304A7D76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{84020C4A-933A-4693-9889-1B99304A7D76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{84020C4A-933A-4693-9889-1B99304A7D76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -348,6 +358,34 @@ Global
|
|||
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{64EF61E7-00A6-4E5E-9808-62E10993A0E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C796ACE-9599-4D55-AA0D-F1615B2D8C42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C796ACE-9599-4D55-AA0D-F1615B2D8C42}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C796ACE-9599-4D55-AA0D-F1615B2D8C42}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C796ACE-9599-4D55-AA0D-F1615B2D8C42}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7EF1F26A-85BF-4C6F-8891-331C44B5802B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EF1F26A-85BF-4C6F-8891-331C44B5802B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EF1F26A-85BF-4C6F-8891-331C44B5802B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EF1F26A-85BF-4C6F-8891-331C44B5802B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{31DC6301-E354-46AA-BA0A-BED38AED8D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{31DC6301-E354-46AA-BA0A-BED38AED8D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{31DC6301-E354-46AA-BA0A-BED38AED8D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{31DC6301-E354-46AA-BA0A-BED38AED8D36}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{60132BCE-0E8B-4E13-AEB0-919BC795E068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60132BCE-0E8B-4E13-AEB0-919BC795E068}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60132BCE-0E8B-4E13-AEB0-919BC795E068}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60132BCE-0E8B-4E13-AEB0-919BC795E068}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F7C5E0CD-6FDA-4118-B419-74377C9CFD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F7C5E0CD-6FDA-4118-B419-74377C9CFD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F7C5E0CD-6FDA-4118-B419-74377C9CFD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F7C5E0CD-6FDA-4118-B419-74377C9CFD27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{06CD34BB-93BF-467D-891A-91C44F0CD423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{06CD34BB-93BF-467D-891A-91C44F0CD423}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{06CD34BB-93BF-467D-891A-91C44F0CD423}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{06CD34BB-93BF-467D-891A-91C44F0CD423}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -386,7 +424,6 @@ Global
|
|||
{E0C991D9-0DB8-471C-ADC9-5FB16E2A0106} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{952827D4-8D4C-4327-AE4D-E8D25811EF35} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{A905E29A-7110-497F-ADC5-2CE2A148FEA0} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{D7E9D90B-5595-4E72-A90A-6DE20D9AB7AE} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{668726B9-77BC-45CF-B576-0F0773BF1615} = {686480D7-8FEC-4ED3-9C5D-CEBE1057A7ED}
|
||||
{84020C4A-933A-4693-9889-1B99304A7D76} = {668726B9-77BC-45CF-B576-0F0773BF1615}
|
||||
{5777515F-4053-42F9-AF2B-95D8D0F5384A} = {668726B9-77BC-45CF-B576-0F0773BF1615}
|
||||
|
@ -409,6 +446,14 @@ Global
|
|||
{97550E87-48C6-4EBF-85E1-413ABAE9DBFD} = {18BF8DD7-0585-48BF-8F97-AD333080CE06}
|
||||
{CF4C92BD-28AE-4B8F-B173-601004AEC9BF} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64}
|
||||
{64EF61E7-00A6-4E5E-9808-62E10993A0E5} = {7EB336C2-7C0A-4BC8-80C6-A3173AB8DC45}
|
||||
{ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470} = {686480D7-8FEC-4ED3-9C5D-CEBE1057A7ED}
|
||||
{6C796ACE-9599-4D55-AA0D-F1615B2D8C42} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{7EF1F26A-85BF-4C6F-8891-331C44B5802B} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{31DC6301-E354-46AA-BA0A-BED38AED8D36} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{60132BCE-0E8B-4E13-AEB0-919BC795E068} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{F7C5E0CD-6FDA-4118-B419-74377C9CFD27} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{06CD34BB-93BF-467D-891A-91C44F0CD423} = {ACC20E50-0E9A-47AE-B6B3-9F1AFE74E470}
|
||||
{FA454D8D-F4CD-4B8F-97EB-AB2BE18AD3AD} = {05B9C173-6441-4DCA-9AC4-E897EF75F331}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {93384647-528D-46C8-922C-8DB36A382F0B}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<PackageVersion Include="Aspire.Hosting.Orleans" Version="8.2.1" />
|
||||
<PackageVersion Include="Aspire.Hosting.Qdrant" Version="8.2.1" />
|
||||
<PackageVersion Include="Aspire.Hosting.Redis" Version="8.2.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.Python" Version="8.2.0" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version=" 2.1.0-beta.1" />
|
||||
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.1" />
|
||||
<PackageVersion Include="Azure.Data.Tables" Version="12.9.1" />
|
||||
|
@ -38,7 +39,7 @@
|
|||
<PackageVersion Include="Grpc.Core" Version="2.46.6" />
|
||||
<PackageVersion Include="Grpc.Net.ClientFactory" Version="2.66.0" />
|
||||
<PackageVersion Include="Grpc.Tools" Version="2.67.0" />
|
||||
<PackageVersion Include="Grpc.Net.Client" Version="2.65.0" />
|
||||
<PackageVersion Include="Grpc.Net.Client" Version="2.66.0" />
|
||||
<PackageVersion Include="Google.Protobuf" Version="3.28.2" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.App" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8" />
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/Runtime/Microsoft.AutoGen.Runtime.csproj" />
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/ServiceDefaults/Microsoft.AutoGen.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\DevTeam.ServiceDefaults\DevTeam.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\DevTeam.Shared\DevTeam.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
<ItemGroup>
|
||||
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/Agents/Microsoft.AutoGen.Agents.csproj" />
|
||||
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/ServiceDefaults/Microsoft.AutoGen.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\DevTeam.Shared\DevTeam.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\SemanticKernel\Microsoft.AutoGen.Extensions.SemanticKernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"profiles": {
|
||||
"DevTeam.AppHost": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:17034;http://localhost:15043",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21249",
|
||||
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22030"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/ServiceDefaults/Microsoft.AutoGen.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\DevTeam.Shared\DevTeam.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\SemanticKernel\Microsoft.AutoGen.Extensions.SemanticKernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
|
||||
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Extensions.cs
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
|
||||
// This project should be referenced by each service project in your solution.
|
||||
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
|
||||
public static class Extensions
|
||||
{
|
||||
public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.ConfigureOpenTelemetry();
|
||||
|
||||
builder.AddDefaultHealthChecks();
|
||||
|
||||
builder.Services.AddServiceDiscovery();
|
||||
|
||||
builder.Services.ConfigureHttpClientDefaults(http =>
|
||||
{
|
||||
// Turn on resilience by default
|
||||
http.AddStandardResilienceHandler();
|
||||
|
||||
// Turn on service discovery by default
|
||||
http.AddServiceDiscovery();
|
||||
});
|
||||
|
||||
// Uncomment the following to restrict the allowed schemes for service discovery.
|
||||
// builder.Services.Configure<ServiceDiscoveryOptions>(options =>
|
||||
// {
|
||||
// options.AllowedSchemes = ["https"];
|
||||
// });
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Logging.AddOpenTelemetry(logging =>
|
||||
{
|
||||
logging.IncludeFormattedMessage = true;
|
||||
logging.IncludeScopes = true;
|
||||
});
|
||||
|
||||
builder.Services.AddOpenTelemetry()
|
||||
.WithMetrics(metrics =>
|
||||
{
|
||||
metrics.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddRuntimeInstrumentation()
|
||||
.AddMeter("Microsoft.Orleans");
|
||||
})
|
||||
.WithTracing(tracing =>
|
||||
{
|
||||
tracing.AddAspNetCoreInstrumentation()
|
||||
//.AddGrpcClientInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddSource("Microsoft.Orleans.Application")
|
||||
.AddSource("AutoGen.Agent");
|
||||
});
|
||||
|
||||
builder.AddOpenTelemetryExporters();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
|
||||
{
|
||||
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
|
||||
|
||||
if (useOtlpExporter)
|
||||
{
|
||||
builder.Services.AddOpenTelemetry().UseOtlpExporter();
|
||||
}
|
||||
|
||||
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
|
||||
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
|
||||
//{
|
||||
// builder.Services.AddOpenTelemetry()
|
||||
// .UseAzureMonitor();
|
||||
//}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddHealthChecks()
|
||||
// Add a default liveness check to ensure app is responsive
|
||||
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static WebApplication MapDefaultEndpoints(this WebApplication app)
|
||||
{
|
||||
// Adding health checks endpoints to applications in non-development environments has security implications.
|
||||
// See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
// All health checks must pass for app to be considered ready to accept traffic after starting
|
||||
app.MapHealthChecks("/health");
|
||||
|
||||
// Only health checks tagged with the "live" tag must pass for app to be considered alive
|
||||
app.MapHealthChecks("/alive", new HealthCheckOptions
|
||||
{
|
||||
Predicate = r => r.Tags.Contains("live")
|
||||
});
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/Agents/Microsoft.AutoGen.Agents.csproj" />
|
||||
<ProjectReference Include="..\DevTeam.ServiceDefaults\DevTeam.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/.infra/
|
||||
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/Microsoft.AutoGen/Runtime/Microsoft.AutoGen.Runtime.csproj" />
|
||||
<ProjectReference Include="..\Marketing.Shared\Marketing.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
@Marketing.AgentHost_HostAddress = http://localhost:5136
|
||||
|
||||
GET {{Marketing.AgentHost_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Program.cs
|
||||
|
||||
using Microsoft.AutoGen.Runtime;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddServiceDefaults();
|
||||
builder.AddAgentService();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapDefaultEndpoints();
|
||||
app.MapAgentService();
|
||||
|
||||
app.Run();
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:59666",
|
||||
"sslPort": 44374
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5136",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7069;http://localhost:5136",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Auditor.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AutoGen.Abstractions;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
[TopicSubscription("default")]
|
||||
public class Auditor(IAgentContext context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, ILogger<Auditor> logger)
|
||||
: SKAiAgent<AuditorState>(context, memory, kernel, typeRegistry),
|
||||
IHandle<AuditText>
|
||||
{
|
||||
public async Task Handle(AuditText item)
|
||||
{
|
||||
logger.LogInformation($"[{nameof(Auditor)}] Event {nameof(AuditText)}. Text: {{Text}}", item.Text);
|
||||
|
||||
var context = new KernelArguments { ["input"] = AppendChatHistory(item.Text) };
|
||||
var auditorAnswer = await CallFunction(AuditorPrompts.AuditText, context);
|
||||
if (auditorAnswer.Contains("NOTFORME", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SendAuditorAlertEvent(auditorAnswer, item.UserId);
|
||||
}
|
||||
|
||||
private async Task SendAuditorAlertEvent(string auditorAlertMessage, string userId)
|
||||
{
|
||||
var auditorAlert = new AuditorAlert
|
||||
{
|
||||
AuditorAlertMessage = auditorAlertMessage,
|
||||
UserId = userId
|
||||
}.ToCloudEvent(this.AgentId.Key);
|
||||
|
||||
await PublishEvent(auditorAlert);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// AuditorPrompts.cs
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
public static class AuditorPrompts
|
||||
{
|
||||
public const string AuditText = """
|
||||
You are an Auditor in a Marketing team
|
||||
Audit the text bello and make sure we do not give discounts larger than 10%
|
||||
If the text talks about a larger than 10% discount, reply with a message to the user saying that the discount is too large, and by company policy we are not allowed.
|
||||
If the message says who wrote it, add that information in the response as well
|
||||
In any other case, reply with NOTFORME
|
||||
---
|
||||
Input: {{$input}}
|
||||
---
|
||||
""";
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// CommunityManager.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AutoGen.Abstractions;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
[TopicSubscription("default")]
|
||||
public class CommunityManager(IAgentContext context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, ILogger<CommunityManager> logger)
|
||||
: SKAiAgent<CommunityManagerState>(context, memory, kernel, typeRegistry),
|
||||
IHandle<UserConnected>,
|
||||
IHandle<UserChatInput>,
|
||||
IHandle<ArticleCreated>
|
||||
{
|
||||
public async Task Handle(ArticleCreated item)
|
||||
{
|
||||
logger.LogInformation($"Article created: {item.Article}");
|
||||
_state.Data.Article = item.Article;
|
||||
await HandleGeneration(item.UserId, item.UserMessage);
|
||||
}
|
||||
|
||||
public async Task Handle(UserChatInput item)
|
||||
{
|
||||
logger.LogInformation($"UserChatInput: {item.UserMessage}");
|
||||
if (_state.Data.Article == null) { return; }
|
||||
await HandleGeneration(item.UserId, item.UserMessage);
|
||||
}
|
||||
|
||||
private async Task HandleGeneration(string userId, string userMessage)
|
||||
{
|
||||
var input = _state.Data.Article + "| USER REQUEST: " + userMessage;
|
||||
var context = new KernelArguments { ["input"] = AppendChatHistory(input) };
|
||||
var socialMediaPost = await CallFunction(CommunityManagerPrompts.WritePost, context);
|
||||
if (socialMediaPost.Contains("NOTFORME", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_state.Data.WrittenSocialMediaPost = socialMediaPost;
|
||||
|
||||
await SendDesignedCreatedEvent(socialMediaPost, userId);
|
||||
}
|
||||
|
||||
public async Task Handle(UserConnected item)
|
||||
{
|
||||
//The user reconnected, let's send the last message if we have one
|
||||
var lastMessage = _state.History.LastOrDefault()?.Message;
|
||||
if (string.IsNullOrWhiteSpace(lastMessage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SendDesignedCreatedEvent(lastMessage, item.UserId);
|
||||
}
|
||||
|
||||
private async Task SendDesignedCreatedEvent(string socialMediaPost, string userId)
|
||||
{
|
||||
var socialMediaPostCreatedEvent = new SocialMediaPostCreated
|
||||
{
|
||||
SocialMediaPost = socialMediaPost,
|
||||
UserId = userId
|
||||
}.ToCloudEvent(this.AgentId.Key);
|
||||
|
||||
await PublishEvent(socialMediaPostCreatedEvent);
|
||||
}
|
||||
|
||||
// This is just an example on how you can synchronously call an specific agent
|
||||
public Task<string> GetArticle()
|
||||
{
|
||||
return Task.FromResult(_state.Data.WrittenSocialMediaPost);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// CommunityManagerPrompts.cs
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
public static class CommunityManagerPrompts
|
||||
{
|
||||
public const string WritePost = """
|
||||
You are a Marketing community manager writer.
|
||||
If the request from the user is to write a post to promote a new product, or if it is specifically talking to you (community manager)
|
||||
then you should write a post based on the user request
|
||||
Your writings are going to be posted on Tweeter. So be informal, friendly and add some hashtags and emojis.
|
||||
Remember, the tweet cannot be longer than 280 characters.
|
||||
If the request was not intedend for you. reply with <NOTFORME>"
|
||||
---
|
||||
Input: {{$input}}
|
||||
---
|
||||
""";
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// GraphicDesigner.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AutoGen.Abstractions;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel.TextToImage;
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
[TopicSubscription("default")]
|
||||
public class GraphicDesigner(IAgentContext context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, ILogger<GraphicDesigner> logger)
|
||||
: SKAiAgent<GraphicDesignerState>(context, memory, kernel, typeRegistry),
|
||||
IHandle<UserConnected>,
|
||||
IHandle<ArticleCreated>
|
||||
{
|
||||
public async Task Handle(UserConnected item)
|
||||
{
|
||||
var lastMessage = _state.History.LastOrDefault()?.Message;
|
||||
if (string.IsNullOrWhiteSpace(lastMessage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SendDesignedCreatedEvent(lastMessage, item.UserId);
|
||||
}
|
||||
|
||||
public async Task Handle(ArticleCreated item)
|
||||
{
|
||||
//For demo purposes, we do not recreate images if they already exist
|
||||
if (!string.IsNullOrEmpty(_state.Data.ImageUrl))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogInformation($"[{nameof(GraphicDesigner)}] Event {nameof(ArticleCreated)}.");
|
||||
var dallEService = _kernel.GetRequiredService<ITextToImageService>();
|
||||
var imageUri = await dallEService.GenerateImageAsync(item.Article, 1024, 1024);
|
||||
|
||||
_state.Data.ImageUrl = imageUri;
|
||||
|
||||
await SendDesignedCreatedEvent(imageUri, item.UserId);
|
||||
}
|
||||
|
||||
private async Task SendDesignedCreatedEvent(string imageUri, string userId)
|
||||
{
|
||||
var graphicDesignEvent = new GraphicDesignCreated
|
||||
{
|
||||
ImageUri = imageUri,
|
||||
UserId = userId
|
||||
}.ToCloudEvent(this.AgentId.Key);
|
||||
|
||||
await PublishEvent(graphicDesignEvent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// GraphicDesignerPrompts.cs
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
public static class GraphicDesignerPrompts
|
||||
{
|
||||
public const string GenerateImage = """
|
||||
You are a Marketing community manager graphic designer.
|
||||
Bellow is a campaign that you need to create a image for.
|
||||
Create an image of maximum 500x500 pixels that could be use in social medias as a marketing image.
|
||||
Only answer if the user is asking for an image to be created or if the user is asking for a new campaign
|
||||
Input: {{$input}}
|
||||
""";
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="Google.Protobuf" />
|
||||
<PackageReference Include="Grpc.Net.Client" />
|
||||
<PackageReference Include="Grpc.Tools" PrivateAssets="All" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marketing.ServiceDefaults\Marketing.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\Marketing.Shared\Marketing.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
@Marketing.Agents_HostAddress = http://localhost:5019
|
||||
|
||||
GET {{Marketing.Agents_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Program.cs
|
||||
|
||||
using Marketing.Agents;
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddServiceDefaults();
|
||||
|
||||
builder.ConfigureSemanticKernel();
|
||||
|
||||
builder.AddAgentWorker(builder.Configuration["AGENT_HOST"]!)
|
||||
.AddAgent<Writer>("writer")
|
||||
.AddAgent<GraphicDesigner>("graphic-designer")
|
||||
.AddAgent<Auditor>("auditor")
|
||||
.AddAgent<CommunityManager>("community-manager");
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapDefaultEndpoints();
|
||||
|
||||
app.Run();
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:2285",
|
||||
"sslPort": 44301
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5019",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7150;http://localhost:5019",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Writer.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.AutoGen.Abstractions;
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
[TopicSubscription("default")]
|
||||
public class Writer(IAgentContext context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, ILogger<Writer> logger)
|
||||
: SKAiAgent<WriterState>(context, memory, kernel, typeRegistry),
|
||||
IHandle<UserConnected>,
|
||||
IHandle<UserChatInput>,
|
||||
IHandle<AuditorAlert>
|
||||
{
|
||||
public async Task Handle(UserConnected item)
|
||||
{
|
||||
logger.LogInformation($"User Connected: {item.UserId}");
|
||||
string? lastMessage = _state.History.LastOrDefault()?.Message;
|
||||
if (string.IsNullOrWhiteSpace(lastMessage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SendArticleCreatedEvent(lastMessage, item.UserId);
|
||||
}
|
||||
|
||||
public async Task Handle(UserChatInput item)
|
||||
{
|
||||
logger.LogInformation($"UserChatInput: {item.UserMessage}");
|
||||
var context = new KernelArguments { ["input"] = AppendChatHistory(item.UserMessage) };
|
||||
var newArticle = await CallFunction(WriterPrompts.Write, context);
|
||||
|
||||
if (newArticle.Contains("NOTFORME", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// TODO: Implement
|
||||
// var agentState = _state.Data.ToAgentState(this.AgentId, "Etag");
|
||||
// await Store("WrittenArticle", newArticle);
|
||||
await SendArticleCreatedEvent(newArticle, item.UserId);
|
||||
}
|
||||
|
||||
public async Task Handle(AuditorAlert item)
|
||||
{
|
||||
logger.LogInformation($"Auditor feedback: {item.AuditorAlertMessage}");
|
||||
var context = new KernelArguments { ["input"] = AppendChatHistory(item.AuditorAlertMessage) };
|
||||
var newArticle = await CallFunction(WriterPrompts.Adjust, context);
|
||||
|
||||
if (newArticle.Contains("NOTFORME", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
await SendArticleCreatedEvent(newArticle, item.UserId);
|
||||
}
|
||||
private async Task SendArticleCreatedEvent(string article, string userId)
|
||||
{
|
||||
var articleCreatedEvent = new ArticleCreated
|
||||
{
|
||||
Article = article,
|
||||
UserId = userId
|
||||
}.ToCloudEvent(this.AgentId.Key);
|
||||
|
||||
var auditTextEvent = new AuditText
|
||||
{
|
||||
Text = "Article written by the Writer: " + article,
|
||||
UserId = userId
|
||||
}.ToCloudEvent(this.AgentId.Key);
|
||||
|
||||
await PublishEvent(articleCreatedEvent);
|
||||
await PublishEvent(auditTextEvent);
|
||||
}
|
||||
|
||||
//protected override Task<RpcResponse> HandleRequest(RpcRequest request) => request.Method switch
|
||||
//{
|
||||
// "GetArticle" => Task.FromResult(new RpcResponse
|
||||
// {
|
||||
// Payload = new Payload
|
||||
// {
|
||||
// DataContentType = "text/plain",
|
||||
// Data = ByteString.CopyFromUtf8(_state.Data.WrittenArticle),
|
||||
// DataType = "text"
|
||||
// }
|
||||
// }),
|
||||
// _ => Task.FromResult(new RpcResponse { Error = $"Unknown method, '{request.Method}'." }),
|
||||
//};
|
||||
|
||||
public Task<string> GetArticle()
|
||||
{
|
||||
return Task.FromResult(_state.Data.WrittenArticle);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// WriterPrompts.cs
|
||||
|
||||
namespace Marketing.Agents;
|
||||
|
||||
public static class WriterPrompts
|
||||
{
|
||||
public const string Write = """
|
||||
This is a multi agent app. You are a Marketing Campaign writer Agent.
|
||||
If the request is not for you, answer with <NOTFORME>.
|
||||
If the request is about writing or modifying an existing campaign, then you should write a campaign based on the user request.
|
||||
Write up to three paragraphs to promote the product the user is asking for.
|
||||
Bellow are a series of inputs from the user that you can use.
|
||||
If the input talks about twitter or images, dismiss it and return <NOTFORME>
|
||||
Input: {{$input}}
|
||||
""";
|
||||
|
||||
public const string Adjust = """
|
||||
This is a multi agent app. You are a Marketing Campaign writer Agent.
|
||||
If the request is not for you, answer with <NOTFORME>.
|
||||
If the request is about writing or modifying an existing campaign, then you should write a campaign based on the user request.
|
||||
The campaign is not compliant with the company policy, and you need to adjust it. This is the message from the automatic auditor agent regarding what is wrong with the original campaign
|
||||
---
|
||||
Input: {{$input}}
|
||||
---
|
||||
Return only the new campaign text but adjusted to the auditor request
|
||||
""";
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>f0492827-f837-4305-9a7c-29e61abd4788</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" />
|
||||
<PackageReference Include="Aspire.Hosting.Azure.ApplicationInsights" />
|
||||
<PackageReference Include="Aspire.Hosting.Azure.CognitiveServices" />
|
||||
<PackageReference Include="Aspire.Hosting.NodeJs" />
|
||||
<PackageReference Include="Aspire.Hosting.Orleans" />
|
||||
<PackageReference Include="Aspire.Hosting.Qdrant" />
|
||||
<PackageReference Include="Aspire.Hosting.Redis" />
|
||||
<PackageReference Include="Aspire.Hosting.Python" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marketing.Agents\Marketing.Agents.csproj" />
|
||||
<ProjectReference Include="..\Marketing.AgentHost\Marketing.AgentHost.csproj" />
|
||||
<ProjectReference Include="..\Marketing.Backend\Marketing.Backend.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Program.cs
|
||||
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddAzureProvisioning();
|
||||
|
||||
var orleans = builder.AddOrleans("orleans")
|
||||
.WithDevelopmentClustering();
|
||||
|
||||
var agentHost = builder.AddProject<Projects.Marketing_AgentHost>("agenthost")
|
||||
.WithReference(orleans);
|
||||
var agentHostHttps = agentHost.GetEndpoint("https");
|
||||
|
||||
var backend = builder.AddProject<Projects.Marketing_Backend>("backend")
|
||||
.WithEnvironment("AGENT_HOST", $"{agentHostHttps.Property(EndpointProperty.Url)}")
|
||||
.WithEnvironment("OpenAI__Key", builder.Configuration["OpenAI:Key"])
|
||||
.WithEnvironment("OpenAI__Endpoint", builder.Configuration["OpenAI:Endpoint"]);
|
||||
|
||||
builder.AddProject<Projects.Marketing_Agents>("marketing-agents")
|
||||
.WithEnvironment("AGENT_HOST", $"{agentHostHttps.Property(EndpointProperty.Url)}")
|
||||
.WithEnvironment("OpenAI__Key", builder.Configuration["OpenAI:Key"])
|
||||
.WithEnvironment("OpenAI__Endpoint", builder.Configuration["OpenAI:Endpoint"]);
|
||||
|
||||
//var ep = agentHost.GetEndpoint("http");
|
||||
|
||||
//builder.AddPythonProject("python-worker", "../../../../../python/", "./packages/autogen-core/samples/marketing-team/worker.py")
|
||||
// .WithEnvironment("AGENT_HOST", $"{agentHostHttps.Property(EndpointProperty.Host)}:{agentHostHttps.Property(EndpointProperty.Port)}");
|
||||
|
||||
builder.AddNpmApp("frontend", "../Marketing.Frontend", "dev")
|
||||
.WithReference(backend)
|
||||
.WithEnvironment("NEXT_PUBLIC_BACKEND_URI", backend.GetEndpoint("http"))
|
||||
.WithHttpEndpoint(env: "PORT")
|
||||
.WithExternalHttpEndpoints()
|
||||
.PublishAsDockerFile();
|
||||
|
||||
builder.Build().Run();
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:17034;http://localhost:15043",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21249",
|
||||
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22030"
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:15043",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19105",
|
||||
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20096"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Aspire.Hosting.Dcp": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SignalRAgent.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Marketing.Backend.Hubs;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.AutoGen.Abstractions;
|
||||
|
||||
namespace Marketing.Backend.Agents;
|
||||
|
||||
[TopicSubscription("default")]
|
||||
public class SignalRAgent(IAgentContext context, Kernel kernel, ISemanticTextMemory memory, [FromKeyedServices("EventTypes")] EventTypes typeRegistry, ISignalRService signalRClient)
|
||||
: SKAiAgent<Empty>(context, memory, kernel, typeRegistry),
|
||||
IHandle<ArticleCreated>,
|
||||
IHandle<GraphicDesignCreated>,
|
||||
IHandle<SocialMediaPostCreated>,
|
||||
IHandle<AuditorAlert>
|
||||
{
|
||||
public async Task Handle(SocialMediaPostCreated item)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
await signalRClient.SendMessageToSpecificClient(item.UserId, item.SocialMediaPost, Hubs.AgentTypes.CommunityManager);
|
||||
}
|
||||
|
||||
public async Task Handle(ArticleCreated item)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
await signalRClient.SendMessageToSpecificClient(item.UserId, item.Article, Hubs.AgentTypes.Chat);
|
||||
}
|
||||
|
||||
public async Task Handle(GraphicDesignCreated item)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
await signalRClient.SendMessageToSpecificClient(item.UserId, item.ImageUri, Hubs.AgentTypes.GraphicDesigner);
|
||||
}
|
||||
|
||||
public async Task Handle(AuditorAlert item)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
await signalRClient.SendMessageToSpecificClient(item.UserId, item.AuditorAlertMessage, Hubs.AgentTypes.Auditor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// ArticlesController.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.AutoGen.Runtime;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace Marketing.Backend.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class Articles(AgentWorker client) : ControllerBase
|
||||
{
|
||||
private readonly AgentWorker _client = client;
|
||||
|
||||
//// GET api/<Post>/5
|
||||
//[HttpGet("{id}")]
|
||||
//public async Task<string> Get(string id)
|
||||
//{
|
||||
// var response = await _client.(new AgentId("writer", id), "GetArticle", []);
|
||||
// return response.Payload.Data.ToStringUtf8();
|
||||
//}
|
||||
|
||||
// PUT api/<Post>/5
|
||||
[HttpPut("{UserId}")]
|
||||
public async Task<string> Put(string userId, [FromBody] string userMessage)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(userId);
|
||||
var evt = new UserChatInput
|
||||
{
|
||||
UserId = userId,
|
||||
UserMessage = userMessage,
|
||||
};
|
||||
await _client.PublishEventAsync(evt.ToCloudEvent(userId));
|
||||
|
||||
return $"Task {userId} accepted";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// AgentTypes.cs
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public enum AgentTypes
|
||||
{
|
||||
Chat,
|
||||
CommunityManager,
|
||||
GraphicDesigner,
|
||||
Auditor,
|
||||
Accountant,
|
||||
Librarian
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// ArticleHub.cs
|
||||
|
||||
using Marketing.Shared;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
using Microsoft.AutoGen.Runtime;
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public class ArticleHub(AgentWorker client) : Hub<IArticleHub>
|
||||
{
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
SignalRConnectionsDB.ConnectionIdByUser.TryRemove(Context.ConnectionId, out _);
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is called when a new message from the client arrives.
|
||||
/// </summary>
|
||||
/// <param name="frontEndMessage"></param>
|
||||
/// <returns></returns>
|
||||
public async Task ProcessMessage(FrontEndMessage frontEndMessage)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(frontEndMessage);
|
||||
ArgumentNullException.ThrowIfNull(client);
|
||||
|
||||
var evt = new UserChatInput { UserId = frontEndMessage.UserId, UserMessage = frontEndMessage.Message };
|
||||
|
||||
await client.PublishEventAsync(evt.ToCloudEvent(frontEndMessage.UserId));
|
||||
}
|
||||
|
||||
public async Task ConnectToAgent(string userId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(userId);
|
||||
ArgumentNullException.ThrowIfNull(client);
|
||||
|
||||
var frontEndMessage = new FrontEndMessage()
|
||||
{
|
||||
UserId = userId,
|
||||
Message = "Connected to agents",
|
||||
Agent = AgentTypes.Chat.ToString()
|
||||
};
|
||||
|
||||
SignalRConnectionsDB.ConnectionIdByUser.AddOrUpdate(userId, Context.ConnectionId, (key, oldValue) => Context.ConnectionId);
|
||||
|
||||
// Notify the agents that a new user got connected.
|
||||
var data = new Dictionary<string, string>
|
||||
{
|
||||
["UserId"] = frontEndMessage.UserId,
|
||||
["userMessage"] = frontEndMessage.Message,
|
||||
};
|
||||
var evt = new UserConnected { UserId = userId };
|
||||
await client.PublishEventAsync(evt.ToCloudEvent(userId));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// FrontEndMessage.cs
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public class FrontEndMessage
|
||||
{
|
||||
public required string UserId { get; set; }
|
||||
public required string Message { get; set; }
|
||||
public required string Agent { get; set; }
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// IArticleHub.cs
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public interface IArticleHub
|
||||
{
|
||||
public Task ConnectToAgent(string UserId);
|
||||
|
||||
public Task ChatMessage(FrontEndMessage frontEndMessage);
|
||||
|
||||
public Task SendMessageToSpecificClient(string userId, string message);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// ISignalRService.cs
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public interface ISignalRService
|
||||
{
|
||||
Task SendMessageToSpecificClient(string userId, string message, AgentTypes agentType);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SignalRConnectionsDB.cs
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public static class SignalRConnectionsDB
|
||||
{
|
||||
public static ConcurrentDictionary<string, string> ConnectionIdByUser { get; } = new ConcurrentDictionary<string, string>();
|
||||
public static ConcurrentDictionary<string, string> AllConnections { get; } = new ConcurrentDictionary<string, string>();
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SignalRService.cs
|
||||
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Marketing.Backend.Hubs;
|
||||
|
||||
public class SignalRService(IHubContext<ArticleHub> hubContext) : ISignalRService
|
||||
{
|
||||
public async Task SendMessageToSpecificClient(string userId, string message, AgentTypes agentType)
|
||||
{
|
||||
var connectionId = SignalRConnectionsDB.ConnectionIdByUser[userId];
|
||||
var frontEndMessage = new FrontEndMessage()
|
||||
{
|
||||
UserId = userId,
|
||||
Message = message,
|
||||
Agent = agentType.ToString()
|
||||
};
|
||||
await hubContext.Clients.Client(connectionId).SendAsync("ReceiveMessage", frontEndMessage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Octokit.Webhooks.AspNetCore" />
|
||||
<PackageReference Include="Octokit" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Qdrant" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Memory" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" />
|
||||
<PackageReference Include="Microsoft.Extensions.Azure" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
|
||||
<PackageReference Include="Azure.ResourceManager.ContainerInstance" />
|
||||
<PackageReference Include="Azure.Storage.Files.Shares" />
|
||||
<PackageReference Include="Azure.Data.Tables" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Extensions\CloudEvents\Microsoft.AutoGen.Extensions.CloudEvents.csproj" />
|
||||
<ProjectReference Include="..\Marketing.Shared\Marketing.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
@Marketing.Backend_HostAddress = http://localhost:5019
|
||||
|
||||
GET {{Marketing.Backend_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Program.cs
|
||||
|
||||
using Marketing.Backend.Agents;
|
||||
using Marketing.Shared;
|
||||
using Marketing.Backend.Hubs;
|
||||
using Microsoft.AutoGen.Agents;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddServiceDefaults();
|
||||
builder.ConfigureSemanticKernel();
|
||||
|
||||
builder.Services.AddHttpClient();
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddSignalR();
|
||||
builder.AddAgentWorker(builder.Configuration["AGENT_HOST"]!)
|
||||
.AddAgent<SignalRAgent>("signalr-hub");
|
||||
builder.Services.AddSingleton<AgentWorker>();
|
||||
builder.Services.AddSingleton<ISignalRService, SignalRService>();
|
||||
|
||||
// Allow any CORS origin if in DEV
|
||||
const string AllowDebugOriginPolicy = "AllowDebugOrigin";
|
||||
if (builder.Environment.IsDevelopment())
|
||||
{
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(AllowDebugOriginPolicy, builder =>
|
||||
{
|
||||
builder
|
||||
.WithOrigins("*") // client url
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapDefaultEndpoints();
|
||||
app.UseRouting();
|
||||
app.UseCors(AllowDebugOriginPolicy);
|
||||
app.MapControllers();
|
||||
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||
});
|
||||
|
||||
app.MapHub<ArticleHub>("/articlehub");
|
||||
app.Run();
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:51446",
|
||||
"sslPort": 44363
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5020",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7224;http://localhost:5020",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# Front end needs the environment variables at build time
|
||||
!.env
|
|
@ -0,0 +1 @@
|
|||
NEXT_PUBLIC_BACKEND_URI=<AZURE_BACKEND_URI>
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
.env
|
||||
|
||||
/.infra/
|
||||
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
|
@ -0,0 +1,2 @@
|
|||
legacy-peer-deps=true
|
||||
strict-peer-dependencies=false
|
|
@ -0,0 +1,31 @@
|
|||
FROM refinedev/node:18 AS base
|
||||
|
||||
FROM base AS deps
|
||||
RUN apk add --no-cache libc6-compat
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
FROM base AS builder
|
||||
ENV NEXT_TELEMETRY_DEBUG=1
|
||||
COPY --from=deps /app/refine/node_modules ./node_modules
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM base AS runner
|
||||
ENV NODE_ENV=production
|
||||
COPY --from=builder /app/refine/public ./public
|
||||
RUN mkdir .next
|
||||
RUN chown refine:nodejs .next
|
||||
COPY --from=builder --chown=refine:nodejs /app/refine/.next/standalone ./
|
||||
COPY --from=builder --chown=refine:nodejs /app/refine/.next/static ./.next/static
|
||||
|
||||
USER refine
|
||||
EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
CMD ["node", "server.js"]
|
|
@ -0,0 +1,11 @@
|
|||
## TODO: describe the frontend app
|
||||
|
||||
## How I started
|
||||
```
|
||||
npm -i
|
||||
```
|
||||
|
||||
## How to run it
|
||||
```shell
|
||||
npm run dev
|
||||
```
|
|
@ -0,0 +1,23 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: 'standalone',
|
||||
images: {
|
||||
domains: ['dalleprodsec.blob.core.windows.net', 'oaidalleapiprodscus.blob.core.windows.net'],
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'dalleprodsec.blob.core.windows.net',
|
||||
port: '**',
|
||||
pathname: '**',
|
||||
},
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'oaidalleapiprodscus.blob.core.windows.net',
|
||||
port: '**',
|
||||
pathname: '**',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "Learning",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
|
||||
"build": "refine build",
|
||||
"start": "refine start",
|
||||
"lint": "eslint '**/*.{js,jsx,ts,tsx}'",
|
||||
"refine": "refine"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.8.2",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@fontsource/roboto": "^4.5.8",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@mui/icons-material": "^5.8.3",
|
||||
"@mui/lab": "^5.0.0-alpha.85",
|
||||
"@mui/material": "^5.8.6",
|
||||
"@mui/x-data-grid": "^6.6.0",
|
||||
"@refinedev/cli": "^2.16.21",
|
||||
"@refinedev/core": "^4.47.1",
|
||||
"@refinedev/devtools": "^1.1.32",
|
||||
"@refinedev/kbar": "^1.3.6",
|
||||
"@refinedev/mui": "^5.14.4",
|
||||
"@refinedev/nextjs-router": "^6.0.0",
|
||||
"@refinedev/react-hook-form": "^4.8.14",
|
||||
"@refinedev/simple-rest": "^5.0.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"next": "^14.2.5",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-flippy": "^1.1.0",
|
||||
"uuidv4": "^6.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@typescript-eslint/parser": "5.48.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.1.0",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"refine": {
|
||||
"projectId": "Z0Y3hf-6BZFyJ-VWX5Qq"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 376 KiB |
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f6c1e8aa044af0cf16af9840f4b8c34dbefc37994febfd286cd9704d5584989a
|
||||
size 2787
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3e3bd4af4498ca6dcd037e2c9a165dad307dde631380a3408fc13039ba33617b
|
||||
size 5195
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:79970b593cf2a95c7e2aac828272982a19c7f149bead9b8d8256cfdc46b12860
|
||||
size 66564
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e9c6f416afca867f3501df6ee02d32bf245c02d46688155232ba0faa6ecec585
|
||||
size 15771
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c0d515e8f60f037366e52e8f1d82e28a676808a9c30c20b2dc93b9b0554bffa7
|
||||
size 84596
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2447ccc6fecf13857e32a06659f75637d39d560dc3e0b9673ff855a8bd6ac4ba
|
||||
size 28777
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7253f301aa0fd63fad4935c51eba121f766a630a9f47b25d24cd7b281e3ca943
|
||||
size 14950
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a4c797fb932b0334d675d56e8c3bcfb967a3a3aa9da88affa7daf302992021f9
|
||||
size 2490
|
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
|
@ -0,0 +1,57 @@
|
|||
import { DevtoolsProvider } from "@providers/devtools";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
|
||||
import { RefineSnackbarProvider, notificationProvider } from "@refinedev/mui";
|
||||
import routerProvider from "@refinedev/nextjs-router";
|
||||
import { Metadata } from "next";
|
||||
import { cookies } from "next/headers";
|
||||
import React, { Suspense } from "react";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "AgNext Marketing Sample",
|
||||
description: "AgNext Marketing Sample",
|
||||
icons: {
|
||||
icon: "/favicon.ico",
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Suspense>
|
||||
<RefineKbarProvider>
|
||||
<RefineSnackbarProvider>
|
||||
<DevtoolsProvider>
|
||||
<Refine
|
||||
routerProvider={routerProvider}
|
||||
notificationProvider={notificationProvider}
|
||||
resources={[
|
||||
{
|
||||
name: "marketing-app",
|
||||
list: "/marketing",
|
||||
}
|
||||
]}
|
||||
options={{
|
||||
syncWithLocation: true,
|
||||
warnWhenUnsavedChanges: true,
|
||||
useNewQueryKeys: true,
|
||||
projectId: "Z0Y3hf-6BZFyJ-VWX5Qq",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<RefineKbar />
|
||||
</Refine>
|
||||
</DevtoolsProvider>
|
||||
</RefineSnackbarProvider>
|
||||
</RefineKbarProvider>
|
||||
</Suspense>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Public from '@mui/icons-material/Public';
|
||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||
import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
|
||||
import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import LightbulbIcon from '@mui/icons-material/Lightbulb';
|
||||
import { Button, Container, Grid, TextField } from '@mui/material';
|
||||
|
||||
const data = [
|
||||
{ icon: <HandshakeTwoToneIcon />, label: 'Bank vs Mrs Peters - Settled - chf 1.5M - 1 year' },
|
||||
{ icon: <WorkspacePremiumTwoToneIcon />, label: 'Bank vs Mr Pertussi - Won - chf0 - 4 years' },
|
||||
{ icon: <Public />, label: 'Bank vs Governnent - Public Case - chf 3.7M - 10 years' },
|
||||
];
|
||||
|
||||
type Sender = 'user' | 'CommunityManager' | 'GraphicDesigner' | 'Writer' | 'Auditor';
|
||||
|
||||
const senderColors: Record<Sender, string> = {
|
||||
'user': '#d1e7dd',
|
||||
'CommunityManager': '#d4e2d4',
|
||||
'GraphicDesigner': '#f0e8e8',
|
||||
'Writer': '#add8e6',
|
||||
'Auditor': '#ff7f7f',
|
||||
};
|
||||
|
||||
|
||||
const FireNav = styled(List)<{ component?: React.ElementType }>({
|
||||
'& .MuiListItemButton-root': {
|
||||
paddingLeft: 24,
|
||||
paddingRight: 24,
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
minWidth: 0,
|
||||
marginRight: 16,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
|
||||
type Message = {
|
||||
sender: string;
|
||||
text: any;
|
||||
};
|
||||
|
||||
type ChatProps = {
|
||||
messages: Message[];
|
||||
setMessages: (messages: Message[]) => void;
|
||||
sendMessage: (message: string, agent: string) => void;
|
||||
};
|
||||
|
||||
export default function Chat({ messages, setMessages, sendMessage }: ChatProps) {
|
||||
const [open, setOpen] = React.useState(true);
|
||||
const [message, setMessage] = React.useState<string>('');
|
||||
|
||||
const handleSend = (message:string) => {
|
||||
setMessages([...messages, { sender: 'user', text: message }]);
|
||||
sendMessage(message, "chat");
|
||||
};
|
||||
|
||||
return (
|
||||
<FireNav component="nav" disablePadding>
|
||||
<ListItemButton
|
||||
alignItems="flex-start"
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
px: 3,
|
||||
pt: 2.5,
|
||||
pb: open ? 0 : 2.5,
|
||||
'&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ my: 0, opacity: 1, class: "menuicon" }}>
|
||||
<LightbulbIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Chat"
|
||||
primaryTypographyProps={{
|
||||
fontSize: 15,
|
||||
fontWeight: 'medium',
|
||||
lineHeight: '20px',
|
||||
mb: '2px',
|
||||
}}
|
||||
secondary="What would you like the campaing to be about?"
|
||||
secondaryTypographyProps={{
|
||||
noWrap: true,
|
||||
fontSize: 12,
|
||||
lineHeight: '16px',
|
||||
color: open ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)',
|
||||
}}
|
||||
sx={{ my: 0 }}
|
||||
/>
|
||||
<KeyboardArrowDown
|
||||
id="arrowdownicon"
|
||||
sx={{
|
||||
mr: -1,
|
||||
opacity: 0,
|
||||
transform: open ? 'rotate(-180deg)' : 'rotate(0)',
|
||||
transition: '0.2s',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
{open && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 50px)' }}>
|
||||
<Container maxWidth={false} style={{ overflowY: 'auto', flex: '1 0 auto', maxHeight: 'calc(100vh - 150px)'}}>
|
||||
<div style={{ margin: '0 auto', fontFamily: "sans-serif" }}>
|
||||
{messages.map((message, index) => (
|
||||
<div key={index} style={{
|
||||
margin: '10px',
|
||||
padding: '10px',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: senderColors[message.sender as Sender] || '#d4e2d4',
|
||||
alignSelf: message.sender === 'user' ? 'flex-end' : 'flex-start',
|
||||
maxWidth: '80%',
|
||||
wordWrap: 'break-word'
|
||||
}}>
|
||||
<strong>{message.sender}:</strong> {message.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
<Container maxWidth={false} style={{ height: '150px' }}>
|
||||
<Grid container spacing={1} alignItems="flex-end">
|
||||
<Grid item xs={11}>
|
||||
<TextField
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
fullWidth
|
||||
inputProps={{ style: { height: 'auto' } }}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
handleSend((e.target as HTMLInputElement).value);
|
||||
setMessage('');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={1}>
|
||||
<Button style={{ height: '100%' }} onClick={() => {
|
||||
handleSend(message);
|
||||
setMessage('');
|
||||
}}>
|
||||
Send
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</div>
|
||||
)}
|
||||
</FireNav>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import AppShortcut from '@mui/icons-material/AttachMoney';
|
||||
import LoopIcon from '@mui/icons-material/Loop';
|
||||
import { Card, CardContent, Typography } from '@mui/material';
|
||||
import Image from 'next/image';
|
||||
|
||||
const FireNav = styled(List)<{ component?: React.ElementType }>({
|
||||
'& .MuiListItemButton-root': {
|
||||
paddingLeft: 24,
|
||||
paddingRight: 24,
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
minWidth: 0,
|
||||
marginRight: 16,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
|
||||
type CommunityManagerProps = {
|
||||
article: string;
|
||||
open: boolean;
|
||||
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
imgUrl: string;
|
||||
};
|
||||
|
||||
export default function CommunityManager({ article, open, setOpen, imgUrl }: CommunityManagerProps) {
|
||||
console.log(`[CommunityManager] Rendering. Url: '${imgUrl}'`);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<FireNav component="nav" disablePadding>
|
||||
<Box
|
||||
sx={{
|
||||
//bgcolor: open ? 'rgba(71, 98, 130, 0.2)' : null,
|
||||
//pb: open ? 2 : 0,
|
||||
}}
|
||||
>
|
||||
<ListItemButton
|
||||
alignItems="flex-start"
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
px: 3,
|
||||
pt: 2.5,
|
||||
pb: open ? 0 : 2.5,
|
||||
'&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ my: 0, opacity: 1, class: "menuicon" }}>
|
||||
<AppShortcut />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Social Media posts"
|
||||
primaryTypographyProps={{
|
||||
fontSize: 15,
|
||||
fontWeight: 'medium',
|
||||
lineHeight: '20px',
|
||||
mb: '2px',
|
||||
}}
|
||||
secondary="Posts in social media"
|
||||
secondaryTypographyProps={{
|
||||
noWrap: true,
|
||||
fontSize: 12,
|
||||
lineHeight: '16px',
|
||||
color: open ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)',
|
||||
}}
|
||||
sx={{ my: 0 }}
|
||||
/>
|
||||
<KeyboardArrowDown
|
||||
id="arrowdownicon"
|
||||
sx={{
|
||||
mr: -1,
|
||||
opacity: 0,
|
||||
transform: open ? 'rotate(-180deg)' : 'rotate(0)',
|
||||
transition: '0.2s',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
{open && (
|
||||
article === '' || article === null ? (
|
||||
<Box>
|
||||
<LoopIcon
|
||||
sx={{
|
||||
animation: "spin 2s linear infinite",
|
||||
"@keyframes spin": {
|
||||
"0%": {
|
||||
transform: "rotate(360deg)",
|
||||
},
|
||||
"100%": {
|
||||
transform: "rotate(0deg)",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h5" component="div">
|
||||
Social media posts on X
|
||||
</Typography>
|
||||
<p>{article}</p>
|
||||
{imgUrl && (
|
||||
<div style={{ width: '100%', height: '500px', position: 'relative' }}>
|
||||
<Image
|
||||
layout='fill'
|
||||
objectFit='cover'
|
||||
src={imgUrl}
|
||||
alt="Graphic designer is working on an image ..."
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
)}
|
||||
</Box>
|
||||
</FireNav>
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||
import Public from '@mui/icons-material/Public';
|
||||
import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
|
||||
import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
|
||||
import GavelIcon from '@mui/icons-material/Gavel';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { green, pink } from '@mui/material/colors';
|
||||
import AttachMoneyIcon from '@mui/icons-material/AttachMoney';
|
||||
|
||||
const data = [
|
||||
{ icon: <HandshakeTwoToneIcon sx={{ color: green[500] }} />, label: 'IPA discount form 9-9 - eur 15k' },
|
||||
{ icon: <GavelIcon sx={{ color: green[500] }} />, label: '2x1 brewery birthday - eur 250k' },
|
||||
{ icon: <HandshakeTwoToneIcon sx={{ color: green[500] }} />, label: 'Summer day 1 - CHF 180k' },
|
||||
{ icon: <HandshakeTwoToneIcon sx={{ color: pink[500] }} />, label: 'Worldcup promo 1.5M' },
|
||||
];
|
||||
|
||||
const FireNav = styled(List)<{ component?: React.ElementType }>({
|
||||
'& .MuiListItemButton-root': {
|
||||
paddingLeft: 24,
|
||||
paddingRight: 24,
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
minWidth: 0,
|
||||
marginRight: 16,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default function CostList() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
console.log(`[Marketing] Rendering.`);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<FireNav component="nav" disablePadding>
|
||||
<Box
|
||||
sx={{
|
||||
//bgcolor: open ? 'rgba(71, 98, 130, 0.2)' : null,
|
||||
//pb: open ? 2 : 0,
|
||||
}}
|
||||
>
|
||||
<ListItemButton
|
||||
alignItems="flex-start"
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
px: 3,
|
||||
pt: 2.5,
|
||||
pb: open ? 0 : 2.5,
|
||||
'&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ my: 0, opacity: 1, class: "menuicon"}}>
|
||||
<AttachMoneyIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Economy of similar cases"
|
||||
primaryTypographyProps={{
|
||||
fontSize: 15,
|
||||
fontWeight: 'medium',
|
||||
lineHeight: '20px',
|
||||
mb: '2px',
|
||||
}}
|
||||
secondary="Cost of similar cases in the past"
|
||||
secondaryTypographyProps={{
|
||||
noWrap: true,
|
||||
fontSize: 12,
|
||||
lineHeight: '16px',
|
||||
color: open ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)',
|
||||
}}
|
||||
sx={{ my: 0 }}
|
||||
/>
|
||||
<KeyboardArrowDown
|
||||
id="arrowdownicon"
|
||||
sx={{
|
||||
mr: -1,
|
||||
opacity: 0,
|
||||
transform: open ? 'rotate(-180deg)' : 'rotate(0)',
|
||||
transition: '0.2s',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
{open &&
|
||||
data.map((item) => (
|
||||
<ListItemButton
|
||||
key={item.label}
|
||||
sx={{ py: 0, minHeight: 32, color: 'rgba(255,255,255,.8)' }}
|
||||
>
|
||||
<ListItemIcon sx={{ color: 'inherit' }}>
|
||||
{item.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={item.label}
|
||||
primaryTypographyProps={{ fontSize: 14, fontWeight: 'medium' }}
|
||||
/>
|
||||
</ListItemButton>
|
||||
))}
|
||||
</Box>
|
||||
</FireNav>
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||
import Public from '@mui/icons-material/Public';
|
||||
import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
|
||||
import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import ExpandLess from '@mui/icons-material/ExpandLess';
|
||||
import ExpandMore from '@mui/icons-material/ExpandMore';
|
||||
import Collapse from '@mui/material/Collapse';
|
||||
import FilePresentIcon from '@mui/icons-material/FilePresent';
|
||||
|
||||
const data = [
|
||||
{ icon: <HandshakeTwoToneIcon />, label: 'Internal guidance for marketing campaigns' },
|
||||
{ icon: <WorkspacePremiumTwoToneIcon />, label: 'Belgium law on marketing of alcohol' },
|
||||
{ icon: <Public />, label: 'something else' },
|
||||
];
|
||||
|
||||
const FireNav = styled(List)<{ component?: React.ElementType }>({
|
||||
'& .MuiListItemButton-root': {
|
||||
paddingLeft: 24,
|
||||
paddingRight: 24,
|
||||
},
|
||||
'& .MuiListItemIcon-root': {
|
||||
minWidth: 0,
|
||||
marginRight: 16,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default function RelevantDocumentList() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
console.log(`[Marketing] Rendering.`);
|
||||
|
||||
const [courtCasesOpen, setCourtCasesOpen] = React.useState(true);
|
||||
const courtCasesOpenHandleClick = () => {
|
||||
setCourtCasesOpen(!courtCasesOpen);
|
||||
};
|
||||
|
||||
const [lawOpen, setLawOpen] = React.useState(true);
|
||||
const LawOpenHandleClick = () => {
|
||||
setLawOpen(!lawOpen);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<FireNav component="nav" disablePadding>
|
||||
<Box
|
||||
sx={{
|
||||
bgcolor: open ? 'rgba(71, 98, 130, 0.2)' : null,
|
||||
pb: open ? 2 : 0,
|
||||
}}
|
||||
>
|
||||
<ListItemButton
|
||||
alignItems="flex-start"
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
px: 3,
|
||||
pt: 2.5,
|
||||
pb: open ? 0 : 2.5,
|
||||
'&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ my: 0, opacity: 1, class: "menuicon" }}>
|
||||
<FilePresentIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Relevant files"
|
||||
primaryTypographyProps={{
|
||||
fontSize: 15,
|
||||
fontWeight: 'medium',
|
||||
lineHeight: '20px',
|
||||
mb: '2px',
|
||||
}}
|
||||
secondary="Files that might be relevant to your case."
|
||||
secondaryTypographyProps={{
|
||||
noWrap: true,
|
||||
fontSize: 12,
|
||||
lineHeight: '16px',
|
||||
color: open ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)',
|
||||
}}
|
||||
sx={{ my: 0 }}
|
||||
/>
|
||||
<KeyboardArrowDown
|
||||
id="arrowdownicon"
|
||||
sx={{
|
||||
mr: -1,
|
||||
opacity: 0,
|
||||
transform: open ? 'rotate(-180deg)' : 'rotate(0)',
|
||||
transition: '0.2s',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
{open && (
|
||||
<Box>
|
||||
<List
|
||||
sx={{ bgcolor: 'background.paper', textAlign: 'left' }}
|
||||
component="nav"
|
||||
aria-labelledby="nested-list-subheader"
|
||||
>
|
||||
{/* Court cases */}
|
||||
<List>
|
||||
<ListItemButton onClick={courtCasesOpenHandleClick}>
|
||||
<ListItemIcon>
|
||||
<FolderIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Internal docs" />
|
||||
{courtCasesOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItemButton>
|
||||
<Collapse in={courtCasesOpen} timeout="auto" unmountOnExit>
|
||||
<List component="div" disablePadding>
|
||||
<ListItemButton>
|
||||
<ListItemIcon sx={{ pl: 4 }}>
|
||||
<img src="/static/icons/docs.png" height={20} width={20} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Marketing campaings general guidelines" />
|
||||
</ListItemButton>
|
||||
<ListItemButton>
|
||||
<ListItemIcon sx={{ pl: 4 }}>
|
||||
<img src="/static/icons/pdf.png" height={20} width={20} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Marketing regulations in Belgium" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Collapse>
|
||||
</List>
|
||||
{/* Laws */}
|
||||
<List>
|
||||
<ListItemButton onClick={LawOpenHandleClick}>
|
||||
<ListItemIcon>
|
||||
<FolderIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Public " />
|
||||
{lawOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItemButton>
|
||||
<Collapse in={lawOpen} timeout="auto" unmountOnExit>
|
||||
<List component="div" disablePadding>
|
||||
<ListItemButton>
|
||||
<ListItemIcon sx={{ pl: 4 }}>
|
||||
<img src="/static/icons/edge.png" height={20} width={20} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Worldwide discount" />
|
||||
</ListItemButton>
|
||||
<ListItemButton>
|
||||
<ListItemIcon sx={{ pl: 4 }}>
|
||||
<img src="/static/icons/edge.png" height={20} width={20} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Color week - T-Shitrs 2022" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</Collapse>
|
||||
</List>
|
||||
</List>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</FireNav>
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
"use client";
|
||||
|
||||
import '@fontsource/roboto/300.css';
|
||||
import '@fontsource/roboto/400.css';
|
||||
import '@fontsource/roboto/500.css';
|
||||
import '@fontsource/roboto/700.css';
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { styled, ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Divider from '@mui/material/Divider';
|
||||
|
||||
import StakeholderList from './stakeholders/stakeholders';
|
||||
import CostList from './costs/cost';
|
||||
import RelevantDocumentList from './docs/docs';
|
||||
import Chat from './chat/chat';
|
||||
import CommunityManager from './community-manager/community-manager';
|
||||
import { Container, Grid } from '@mui/material';
|
||||
import { HubConnectionBuilder, HubConnection, LogLevel } from '@microsoft/signalr';
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
type SignalRMessage = {
|
||||
userId: string;
|
||||
message: string;
|
||||
agent: string;
|
||||
};
|
||||
|
||||
export default function Marketing() {
|
||||
const Item = styled(Paper)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
|
||||
...theme.typography.body2,
|
||||
padding: theme.spacing(0),
|
||||
textAlign: 'center',
|
||||
color: theme.palette.text.secondary,
|
||||
}));
|
||||
|
||||
// Add this style
|
||||
const Background = styled('div')({
|
||||
backgroundImage: `url(/static/background1.webp)`,
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: 'cover',
|
||||
height: '100vh',
|
||||
});
|
||||
|
||||
const [userId, setUserId] = React.useState<string>(uuidv4());
|
||||
const [connection, setConnection] = React.useState<HubConnection>();
|
||||
const [messages, setMessages] = React.useState<{ sender: string; text: any; }[]>([]);
|
||||
|
||||
//Community manager state
|
||||
|
||||
const [ article, setArticle ] = useState<string>('');
|
||||
const [ imgUrl, setImgUrl ] = useState<string>('');
|
||||
const [ communityManagerOpen, setCommunityManagerOpen ] = useState<boolean>(false);
|
||||
|
||||
const createSignalRConnection = async (userId: string) => {
|
||||
try {
|
||||
console.log(`[MainPage] Reading environment variables [${process.env.NEXT_PUBLIC_BACKEND_URI}]`);
|
||||
var uri = process.env.NEXT_PUBLIC_BACKEND_URI
|
||||
? process.env.NEXT_PUBLIC_BACKEND_URI
|
||||
: 'http://localhost:5244';
|
||||
|
||||
uri = new URL('articlehub', uri).href;
|
||||
console.log(`[MainPage] Connecting to [${uri}]`);
|
||||
// initi the connection
|
||||
const connection = new HubConnectionBuilder()
|
||||
.withUrl(uri, {withCredentials: false})
|
||||
.configureLogging(LogLevel.Information)
|
||||
.build();
|
||||
|
||||
//setup handler
|
||||
connection.on('ReceiveMessage', (message: SignalRMessage) => {
|
||||
console.log(`[MainPage][${message.userId}] Received message from ${message.agent}: ${message.message}`);
|
||||
if (message.agent === 'Chat') {
|
||||
const newMessage = { sender: 'Writer', text: message.message };
|
||||
setMessages(prevMessages => [...prevMessages, newMessage]);
|
||||
}
|
||||
if (message.agent === 'Auditor') {
|
||||
const newMessage = { sender: 'Auditor', text: message.message };
|
||||
setMessages(prevMessages => [...prevMessages, newMessage]);
|
||||
}
|
||||
if (message.agent === 'CommunityManager') {
|
||||
setArticle(message.message);
|
||||
const newMessage = { sender: message.agent, text: 'Community Manager: ' + message.message };
|
||||
setMessages(prevMessages => [...prevMessages, newMessage]);
|
||||
}
|
||||
if (message.agent === 'GraphicDesigner') {
|
||||
setImgUrl(message.message);
|
||||
const newMessage = { sender: message.agent, text: 'Graphic Designer: Check the image I created!'};
|
||||
setMessages(prevMessages => [...prevMessages, newMessage]);
|
||||
}
|
||||
});
|
||||
|
||||
connection.onclose(async () => {
|
||||
console.log(`[MainPage] Connection closed.`);
|
||||
|
||||
try {
|
||||
await connection.start();
|
||||
console.log(`Connection ID: ${connection.connectionId}`);
|
||||
await connection.invoke('ConnectToAgent', userId);
|
||||
console.log(`[MainPage] Connection re-established.`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
|
||||
await connection.start();
|
||||
console.log(`Connection ID: ${connection.connectionId}`);
|
||||
await connection.invoke('ConnectToAgent', userId);
|
||||
|
||||
setConnection(connection);
|
||||
console.log(`[MainPage] Connection established.`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const setMessagesInUI = async (messages: { sender: string; text: any; }[]) => {
|
||||
await setMessages(messages);
|
||||
}
|
||||
|
||||
const sendMessage = async (message: string, agent: string) => {
|
||||
if (connection) {
|
||||
const frontEndMessage:SignalRMessage = {
|
||||
userId: userId,
|
||||
message: message,
|
||||
agent: agent
|
||||
};
|
||||
console.log(`[MainPage][${{agent}}] Sending message: ${message}`);
|
||||
await connection.invoke('ProcessMessage', frontEndMessage);
|
||||
console.log(`[MainPage][${{agent}}] message sent`);
|
||||
} else {
|
||||
console.error(`[MainPage] Connection not established.`);
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
createSignalRConnection(userId);
|
||||
}, []);
|
||||
|
||||
const defaultTheme = createTheme({
|
||||
typography: {
|
||||
fontFamily: 'Helvetica, Arial, sans-serif',
|
||||
},
|
||||
});
|
||||
|
||||
const rightPannelTheme = createTheme({
|
||||
typography: {
|
||||
fontFamily: 'Helvetica, Arial, sans-serif',
|
||||
},
|
||||
components: {
|
||||
MuiListItemButton: {
|
||||
defaultProps: {
|
||||
disableTouchRipple: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
// primary: { main: 'rgb(102, 157, 246)' },
|
||||
// background: { paper: 'rgb(5, 30, 52)' },
|
||||
primary: { main: '#006BD6' },
|
||||
background: { paper: 'grey' },
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`[Marketing] Rendering.`);
|
||||
return (
|
||||
<ThemeProvider theme={defaultTheme}>
|
||||
<Background>
|
||||
<Container maxWidth="xl" disableGutters >
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={6}>
|
||||
<Paper elevation={0} style={{ border: '1px solid #000' }}>
|
||||
<Chat messages={messages} setMessages={setMessagesInUI} sendMessage={sendMessage}/>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Stack spacing={0}>
|
||||
<ThemeProvider theme={rightPannelTheme}>
|
||||
<Item>
|
||||
<Paper elevation={0}>
|
||||
<StakeholderList />
|
||||
</Paper>
|
||||
<Divider />
|
||||
</Item>
|
||||
<Item>
|
||||
<Paper elevation={0}>
|
||||
<CostList />
|
||||
</Paper>
|
||||
<Divider />
|
||||
</Item>
|
||||
<Item>
|
||||
<Paper elevation={0}>
|
||||
<RelevantDocumentList />
|
||||
</Paper>
|
||||
<Divider />
|
||||
</Item>
|
||||
<Item>
|
||||
<Paper elevation={0}>
|
||||
<CommunityManager article={article} open={communityManagerOpen} setOpen={setCommunityManagerOpen} imgUrl={imgUrl}/>
|
||||
</Paper>
|
||||
<Divider />
|
||||
</Item>
|
||||
</ThemeProvider>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Background>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
"use client";
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
|
||||
import '@fontsource/roboto/300.css';
|
||||
import '@fontsource/roboto/400.css';
|
||||
import '@fontsource/roboto/500.css';
|
||||
import '@fontsource/roboto/700.css';
|
||||
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Avatar, Box, Container } from '@mui/material';
|
||||
import Badge, { BadgeProps } from '@mui/material/Badge';
|
||||
import { Typography } from '@mui/material';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemAvatar from '@mui/material/ListItemAvatar';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import { Title } from '@refinedev/mui';
|
||||
|
||||
const GreenStyledBadge = styled(Badge)(({ theme }) => ({
|
||||
'& .MuiBadge-badge': {
|
||||
backgroundColor: '#44b700',
|
||||
color: '#44b700',
|
||||
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '50%',
|
||||
animation: 'ripple 1.2s infinite ease-in-out',
|
||||
border: '1px solid currentColor',
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
'@keyframes ripple': {
|
||||
'0%': {
|
||||
transform: 'scale(.8)',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'scale(2.4)',
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const RedStyledBadge = styled(Badge)(({ theme }) => ({
|
||||
'& .MuiBadge-badge': {
|
||||
backgroundColor: 'red',
|
||||
color: '#44b700',
|
||||
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '50%',
|
||||
animation: 'ripple 1.2s infinite ease-in-out',
|
||||
border: '1px solid currentColor',
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
'@keyframes ripple': {
|
||||
'0%': {
|
||||
transform: 'scale(.8)',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'scale(2.4)',
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default function StakeholderList() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
console.log(`[Marketing] Rendering.`);
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<List sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
|
||||
<ListItemButton
|
||||
alignItems="flex-start"
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{
|
||||
px: 3,
|
||||
pt: 2.5,
|
||||
pb: open ? 0 : 2.5,
|
||||
'&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ my: 0, opacity: 1, class: "menuicon" }}>
|
||||
<PersonIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Auditor"
|
||||
primaryTypographyProps={{
|
||||
fontSize: 15,
|
||||
fontWeight: 'medium',
|
||||
lineHeight: '20px',
|
||||
mb: '2px',
|
||||
}}
|
||||
secondary="Auditing rules"
|
||||
secondaryTypographyProps={{
|
||||
noWrap: true,
|
||||
fontSize: 12,
|
||||
lineHeight: '16px',
|
||||
color: open ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)',
|
||||
}}
|
||||
sx={{ my: 0 }}
|
||||
/>
|
||||
<KeyboardArrowDown
|
||||
id="arrowdownicon"
|
||||
sx={{
|
||||
mr: -1,
|
||||
opacity: 0,
|
||||
transform: open ? 'rotate(-180deg)' : 'rotate(0)',
|
||||
transition: '0.2s',
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
{open && (
|
||||
<Box>
|
||||
<ListItemButton alignItems="flex-start">
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="Language check" src="/static/check.png" />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Language check"
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton alignItems="flex-start">
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="Financial check" src="/static/check.png" />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Financial check"
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton alignItems="flex-start">
|
||||
<ListItemAvatar>
|
||||
<Avatar alt="Auto approval" src="/static/check.png" />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Auto approval"
|
||||
/>
|
||||
</ListItemButton>
|
||||
</Box>
|
||||
)}
|
||||
{open && (
|
||||
<p>Questions? These are relevant stakeholders for you:</p>
|
||||
)}
|
||||
{open && (
|
||||
<Box>
|
||||
<ListItemButton alignItems="flex-start">
|
||||
<ListItemAvatar>
|
||||
<RedStyledBadge
|
||||
overlap="circular"
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
variant="dot"
|
||||
>
|
||||
<Avatar alt="Lawrence Law" src="/static/face2.jpg" />
|
||||
</RedStyledBadge>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Lina Maria"
|
||||
secondary={
|
||||
<React.Fragment>
|
||||
<Typography
|
||||
sx={{ display: 'inline' }}
|
||||
component="span"
|
||||
variant="body2"
|
||||
color="text.primary"
|
||||
>
|
||||
General Attorney
|
||||
</Typography>
|
||||
</React.Fragment>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<ListItemButton alignItems="flex-start">
|
||||
<ListItemAvatar>
|
||||
<GreenStyledBadge
|
||||
overlap="circular"
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
variant="dot"
|
||||
>
|
||||
<Avatar alt="Remy Sharp" src="/static/face.jpg" />
|
||||
</GreenStyledBadge>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Lawrence Gevaert"
|
||||
secondary={
|
||||
<React.Fragment>
|
||||
<Typography
|
||||
sx={{ display: 'inline' }}
|
||||
component="span"
|
||||
variant="body2"
|
||||
color="text.primary"
|
||||
>
|
||||
Marketing Manager
|
||||
</Typography>
|
||||
</React.Fragment>
|
||||
}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</Box>
|
||||
)}
|
||||
</List>
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
"use client";
|
||||
|
||||
import { Authenticated } from "@refinedev/core";
|
||||
import { ErrorComponent } from "@refinedev/mui";
|
||||
import { Suspense } from "react";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<Suspense>
|
||||
<Authenticated key="not-found">
|
||||
<ErrorComponent />
|
||||
</Authenticated>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
"use client";
|
||||
|
||||
import { Suspense } from "react";
|
||||
import { NavigateToResource } from "@refinedev/nextjs-router";
|
||||
|
||||
export default function IndexPage() {
|
||||
return (
|
||||
<Suspense>
|
||||
<NavigateToResource />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
DevtoolsPanel,
|
||||
DevtoolsProvider as DevtoolsProviderBase,
|
||||
} from "@refinedev/devtools";
|
||||
import React from "react";
|
||||
|
||||
export const DevtoolsProvider = (props: React.PropsWithChildren) => {
|
||||
return (
|
||||
<DevtoolsProviderBase>
|
||||
{props.children}
|
||||
<DevtoolsPanel />
|
||||
</DevtoolsProviderBase>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@pages/*": [
|
||||
"./pages/*"
|
||||
]
|
||||
},
|
||||
"incremental": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Extensions.cs
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
|
||||
// This project should be referenced by each service project in your solution.
|
||||
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
|
||||
public static class Extensions
|
||||
{
|
||||
public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.ConfigureOpenTelemetry();
|
||||
|
||||
builder.AddDefaultHealthChecks();
|
||||
|
||||
builder.Services.AddServiceDiscovery();
|
||||
|
||||
builder.Services.ConfigureHttpClientDefaults(http =>
|
||||
{
|
||||
// Turn on resilience by default
|
||||
http.AddStandardResilienceHandler();
|
||||
|
||||
// Turn on service discovery by default
|
||||
http.AddServiceDiscovery();
|
||||
});
|
||||
|
||||
// Uncomment the following to restrict the allowed schemes for service discovery.
|
||||
// builder.Services.Configure<ServiceDiscoveryOptions>(options =>
|
||||
// {
|
||||
// options.AllowedSchemes = ["https"];
|
||||
// });
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Logging.AddOpenTelemetry(logging =>
|
||||
{
|
||||
logging.IncludeFormattedMessage = true;
|
||||
logging.IncludeScopes = true;
|
||||
});
|
||||
|
||||
builder.Services.AddOpenTelemetry()
|
||||
.WithMetrics(metrics =>
|
||||
{
|
||||
metrics.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddRuntimeInstrumentation()
|
||||
.AddMeter("Microsoft.Orleans");
|
||||
})
|
||||
.WithTracing(tracing =>
|
||||
{
|
||||
tracing.AddAspNetCoreInstrumentation()
|
||||
//.AddGrpcClientInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddSource("Microsoft.Orleans.Application")
|
||||
.AddSource("AutoGen.Agent");
|
||||
});
|
||||
|
||||
builder.AddOpenTelemetryExporters();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
|
||||
{
|
||||
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
|
||||
|
||||
if (useOtlpExporter)
|
||||
{
|
||||
builder.Services.AddOpenTelemetry().UseOtlpExporter();
|
||||
}
|
||||
|
||||
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
|
||||
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
|
||||
//{
|
||||
// builder.Services.AddOpenTelemetry()
|
||||
// .UseAzureMonitor();
|
||||
//}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddHealthChecks()
|
||||
// Add a default liveness check to ensure app is responsive
|
||||
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static WebApplication MapDefaultEndpoints(this WebApplication app)
|
||||
{
|
||||
// Adding health checks endpoints to applications in non-development environments has security implications.
|
||||
// See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
// All health checks must pass for app to be considered ready to accept traffic after starting
|
||||
app.MapHealthChecks("/health");
|
||||
|
||||
// Only health checks tagged with the "live" tag must pass for app to be considered alive
|
||||
app.MapHealthChecks("/alive", new HealthCheckOptions
|
||||
{
|
||||
Predicate = r => r.Tags.Contains("live")
|
||||
});
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
|
||||
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Memory" />
|
||||
<PackageReference Include="Google.Protobuf" />
|
||||
<PackageReference Include="Grpc.Tools" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Protobuf Include="..\Protos\messages.proto" Link="Protos\messages.proto" />
|
||||
<Protobuf Include="..\Protos\states.proto" Link="Protos\states.proto" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.AutoGen\Agents\Microsoft.AutoGen.Agents.csproj" />
|
||||
<ProjectReference Include="..\Marketing.ServiceDefaults\Marketing.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Consts.cs
|
||||
|
||||
namespace Marketing.Shared.Options;
|
||||
|
||||
public static class Consts
|
||||
{
|
||||
public const string OrleansNamespace = "default";
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// OpenAIOptions.cs
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Marketing.Shared.Options;
|
||||
|
||||
public class OpenAIOptions
|
||||
{
|
||||
// Embeddings
|
||||
[Required]
|
||||
public required string EmbeddingsEndpoint { get; set; }
|
||||
[Required]
|
||||
public required string EmbeddingsApiKey { get; set; }
|
||||
[Required]
|
||||
public required string EmbeddingsDeploymentOrModelId { get; set; }
|
||||
|
||||
// Chat
|
||||
[Required]
|
||||
public required string ChatEndpoint { get; set; }
|
||||
[Required]
|
||||
public required string ChatApiKey { get; set; }
|
||||
[Required]
|
||||
public required string ChatDeploymentOrModelId { get; set; }
|
||||
|
||||
// TextToImage
|
||||
[Required]
|
||||
public required string ImageEndpoint { get; set; }
|
||||
[Required]
|
||||
public required string ImageApiKey { get; set; }
|
||||
// When using OpenAI, this is not required.
|
||||
public required string ImageDeploymentOrModelId { get; set; }
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SemanticKernelHostingExtensions.cs
|
||||
|
||||
using System.ClientModel;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
using Marketing.Shared.Options;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using OpenAI;
|
||||
|
||||
namespace Marketing.Shared;
|
||||
public static class SemanticKernelHostingExtensions
|
||||
{
|
||||
public static IHostApplicationBuilder ConfigureSemanticKernel(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddTransient(CreateKernel);
|
||||
builder.Services.AddTransient(CreateMemory);
|
||||
|
||||
builder.Services.Configure<OpenAIOptions>(o =>
|
||||
{
|
||||
o.EmbeddingsEndpoint = o.ImageEndpoint = o.ChatEndpoint = builder.Configuration["OpenAI:Endpoint"] ?? throw new InvalidOperationException("Ensure that OpenAI:Endpoint is set in configuration");
|
||||
o.EmbeddingsApiKey = o.ImageApiKey = o.ChatApiKey = builder.Configuration["OpenAI:Key"]!;
|
||||
o.EmbeddingsDeploymentOrModelId = "text-embedding-ada-002";
|
||||
o.ImageDeploymentOrModelId = "dall-e-3";
|
||||
o.ChatDeploymentOrModelId = "gpt-4o";
|
||||
});
|
||||
|
||||
builder.Services.Configure<AzureOpenAIClientOptions>(o =>
|
||||
{
|
||||
o.NetworkTimeout = TimeSpan.FromMinutes(3);
|
||||
});
|
||||
|
||||
builder.Services.Configure<JsonSerializerOptions>(options =>
|
||||
{
|
||||
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
});
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static ISemanticTextMemory CreateMemory(IServiceProvider provider)
|
||||
{
|
||||
var openAiConfig = provider.GetRequiredService<IOptions<OpenAIOptions>>().Value;
|
||||
var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
|
||||
var memoryBuilder = new MemoryBuilder();
|
||||
#pragma warning disable SKEXP0050 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
return memoryBuilder.WithLoggerFactory(loggerFactory)
|
||||
.WithMemoryStore(new VolatileMemoryStore())
|
||||
.WithOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAiConfig.EmbeddingsEndpoint, openAiConfig.EmbeddingsApiKey)
|
||||
.Build();
|
||||
#pragma warning restore SKEXP0050 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
}
|
||||
|
||||
public static Kernel CreateKernel(IServiceProvider provider)
|
||||
{
|
||||
OpenAIOptions openAiConfig = provider.GetRequiredService<IOptions<OpenAIOptions>>().Value;
|
||||
var builder = Kernel.CreateBuilder();
|
||||
|
||||
// Chat
|
||||
if (openAiConfig.ChatEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var openAIClient = new AzureOpenAIClient(new Uri(openAiConfig.ChatEndpoint), new ApiKeyCredential(openAiConfig.ChatApiKey));
|
||||
builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient);
|
||||
}
|
||||
else
|
||||
{
|
||||
var openAIClient = new OpenAIClient(openAiConfig.ChatApiKey);
|
||||
builder.Services.AddOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient);
|
||||
}
|
||||
|
||||
// Text to Image
|
||||
if (openAiConfig.ImageEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(openAiConfig.ImageDeploymentOrModelId);
|
||||
var openAIClient = new AzureOpenAIClient(new Uri(openAiConfig.ImageEndpoint), new ApiKeyCredential(openAiConfig.ImageApiKey));
|
||||
builder.Services.AddAzureOpenAITextToImage(openAiConfig.ImageDeploymentOrModelId, openAIClient);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Services.AddOpenAITextToImage(openAiConfig.ImageApiKey, modelId: openAiConfig.ImageDeploymentOrModelId);
|
||||
}
|
||||
|
||||
// Embeddings
|
||||
if (openAiConfig.EmbeddingsEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var openAIClient = new AzureOpenAIClient(new Uri(openAiConfig.EmbeddingsEndpoint), new ApiKeyCredential(openAiConfig.EmbeddingsApiKey));
|
||||
builder.Services.AddAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient);
|
||||
}
|
||||
else
|
||||
{
|
||||
var openAIClient = new OpenAIClient(openAiConfig.EmbeddingsApiKey);
|
||||
builder.Services.AddOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient);
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package marketing;
|
||||
|
||||
option csharp_namespace = "Marketing.Shared";
|
||||
|
||||
message UserChatInput {
|
||||
string user_id = 1;
|
||||
string user_message = 2;
|
||||
}
|
||||
|
||||
message ArticleCreated {
|
||||
string user_id = 1;
|
||||
string article = 2;
|
||||
string user_message = 3;
|
||||
}
|
||||
message UserConnected {
|
||||
string user_id = 1;
|
||||
}
|
||||
message GraphicDesignCreated {
|
||||
string user_id = 1;
|
||||
string image_uri = 2;
|
||||
}
|
||||
message SocialMediaPostCreated {
|
||||
string user_id = 1;
|
||||
string social_media_post = 2;
|
||||
}
|
||||
message AuditText {
|
||||
string user_id = 1;
|
||||
string text = 2;
|
||||
}
|
||||
message AuditorAlert {
|
||||
string user_id = 1;
|
||||
string auditor_alert_message = 2;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package marketing;
|
||||
|
||||
option csharp_namespace = "Marketing.Shared";
|
||||
|
||||
message CommunityManagerState {
|
||||
string written_social_media_post = 1;
|
||||
string article = 2;
|
||||
}
|
||||
|
||||
message WriterState {
|
||||
string written_article = 1;
|
||||
}
|
||||
|
||||
message GraphicDesignerState {
|
||||
string image_url = 1;
|
||||
}
|
||||
|
||||
message AuditorState {
|
||||
string article = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
## How to run this
|
||||
|
||||
- Install [.NET SDK 8.0.302 ](https://dotnet.microsoft.com/en-us/download/dotnet)
|
||||
- Install [Nodejs](https://nodejs.org/en/download/package-manager)
|
||||
- Clone the repo (if you haven't already)
|
||||
```bash
|
||||
git clone https://github.com/microsoft/agnext.git
|
||||
```
|
||||
+ Switch to the branch
|
||||
```bash
|
||||
git checkout kostapetan/marketing-sample
|
||||
```
|
||||
+ Install node packages for the frontend
|
||||
```bash
|
||||
cd ./dotnet/samples/marketing-team/Marketing.Frontend
|
||||
npm install
|
||||
```
|
||||
+ Add OpenAI Key and Endpoint
|
||||
```bash
|
||||
cd ..\Marketing.AppHost\
|
||||
dotnet user-secrets set "OpenAI:Key" "your_key"
|
||||
dotnet user-secrets set "OpenAI:Endpoint" "https://your_endpoint.openai.azure.com/"
|
||||
```
|
||||
+ Run the application
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
|
@ -0,0 +1,8 @@
|
|||
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
|
||||
|
||||
name: marketing-team
|
||||
services:
|
||||
app:
|
||||
language: dotnet
|
||||
project: .\Marketing.AppHost\Marketing.AppHost.csproj
|
||||
host: containerapp
|
|
@ -6,7 +6,6 @@ using Google.Protobuf;
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AutoGen.Runtime;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.AutoGen.Agents;
|
||||
|
||||
|
@ -25,13 +24,13 @@ public static class AgentsApp
|
|||
}
|
||||
builder.AddAgentWorker()
|
||||
.AddAgents(agentTypes);
|
||||
builder.AddServiceDefaults();
|
||||
// builder.AddServiceDefaults();
|
||||
var app = builder.Build();
|
||||
if (local)
|
||||
{
|
||||
app.MapAgentService();
|
||||
}
|
||||
app.MapDefaultEndpoints();
|
||||
// app.MapDefaultEndpoints();
|
||||
Host = app;
|
||||
await app.StartAsync().ConfigureAwait(false);
|
||||
return Host;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Host.cs
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.AutoGen.Runtime;
|
||||
|
||||
|
@ -11,7 +10,7 @@ public static class Host
|
|||
public static async Task<WebApplication> StartAsync(bool local = false)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
builder.AddServiceDefaults();
|
||||
//builder.AddServiceDefaults();
|
||||
if (local)
|
||||
{
|
||||
builder.AddLocalAgentService();
|
||||
|
@ -22,7 +21,7 @@ public static class Host
|
|||
}
|
||||
var app = builder.Build();
|
||||
app.MapAgentService();
|
||||
app.MapDefaultEndpoints();
|
||||
// app.MapDefaultEndpoints();
|
||||
await app.StartAsync().ConfigureAwait(false);
|
||||
return app;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Abstractions\Microsoft.AutoGen.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\ServiceDefaults\Microsoft.AutoGen.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -28,7 +27,7 @@
|
|||
<PackageReference Include="Microsoft.Orleans.Reminders.Cosmos" />
|
||||
<PackageReference Include="Microsoft.Orleans.Streaming.EventHubs" />
|
||||
<PackageReference Include="Microsoft.Orleans.Reminders" />
|
||||
<PackageReference Include="OrleansDashboard"/>
|
||||
<PackageReference Include="OrleansDashboard" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Loading…
Reference in New Issue