Move AI EF Core migrations to provider projects
This commit is contained in:
parent
92f451e655
commit
5c0d8b0f4e
103
Elsa.sln
103
Elsa.sln
|
|
@ -427,6 +427,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "keyvalues", "keyvalues", "{
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dashboard", "dashboard", "{DD8D1712-B42C-4BF2-99AF-3F092E508C62}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AI.Persistence.EFCore.Sqlite", "src\modules\Elsa.AI.Persistence.EFCore.Sqlite\Elsa.AI.Persistence.EFCore.Sqlite.csproj", "{4A57961A-ED52-471F-BA21-EAEE9100E485}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AI.Persistence.EFCore.SqlServer", "src\modules\Elsa.AI.Persistence.EFCore.SqlServer\Elsa.AI.Persistence.EFCore.SqlServer.csproj", "{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AI.Persistence.EFCore.PostgreSql", "src\modules\Elsa.AI.Persistence.EFCore.PostgreSql\Elsa.AI.Persistence.EFCore.PostgreSql.csproj", "{32F2EE33-8190-41D7-BD12-45AA02BEB930}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AI.Persistence.EFCore.MySql", "src\modules\Elsa.AI.Persistence.EFCore.MySql\Elsa.AI.Persistence.EFCore.MySql.csproj", "{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.AI.Persistence.EFCore.Oracle", "src\modules\Elsa.AI.Persistence.EFCore.Oracle\Elsa.AI.Persistence.EFCore.Oracle.csproj", "{743C1835-E41E-4E5C-9D12-585BAEE59EEE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -1887,6 +1897,66 @@ Global
|
|||
{DDEA0B6A-A615-4CF8-8B23-F93E390454B2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DDEA0B6A-A615-4CF8-8B23-F93E390454B2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DDEA0B6A-A615-4CF8-8B23-F93E390454B2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|x64.Build.0 = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -1917,6 +1987,7 @@ Global
|
|||
{29638A67-E79F-44FE-AC05-DA499EBA929E} = {2F3E1026-5054-4E1F-899B-F1A7F70F9912}
|
||||
{A516931E-EDBB-4FC3-BB94-1BB824D5BC61} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{BBCE36D1-6767-4ED1-B3E8-84D2567A962A} = {A516931E-EDBB-4FC3-BB94-1BB824D5BC61}
|
||||
{73BBB1E3-AEEC-44E8-83D7-6DD9CD687FE3} = {9323DC40-29B4-4438-AAD7-C4D4069C072B}
|
||||
{B0946844-DE0E-4C59-9391-C0EB649DBF4E} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{34BC9836-681D-43A5-BC39-E4FEE17FC528} = {08B41FFA-CEE3-46A7-B5C0-3EB65D37A16C}
|
||||
{CBB515F3-A0EF-43B5-A907-FD4E652DD66E} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
|
||||
|
|
@ -2020,21 +2091,12 @@ Global
|
|||
{E4B1546A-3F35-4B5C-815C-07E58B00163F} = {D3E5E9EF-DE26-41BF-A239-3241B5B5FD89}
|
||||
{E18931B2-82EE-4398-B38A-7B8B449957CD} = {D3E5E9EF-DE26-41BF-A239-3241B5B5FD89}
|
||||
{729FD075-2863-48AB-A3C0-A4F7A9277263} = {D3E5E9EF-DE26-41BF-A239-3241B5B5FD89}
|
||||
{4FD4C59B-2804-4F6B-AD38-2562CC01C510} = {DD8D1712-B42C-4BF2-99AF-3F092E508C62}
|
||||
{157EDBA7-B04F-4EA0-8377-434D1065ACF6} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{27300F17-F959-4D4A-885F-FDDBE81456C1} = {DD8D1712-B42C-4BF2-99AF-3F092E508C62}
|
||||
{05AC1253-922A-4BC4-93D0-765752026B29} = {B08B4E00-C2AB-48F3-8389-449F42AEF179}
|
||||
{D1212632-20D4-4115-9E8F-05EEEC4604BE} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D}
|
||||
{215555CD-3B4A-46E7-ACE0-B4ADE1F0FE62} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D}
|
||||
{418472CD-1215-4962-9024-F26E9863B5A4} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{C597B963-A80F-4093-B3CC-9060854D9D38} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{E087B3BD-D579-422B-A29F-965D33E2C769} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{1C70A220-E69F-434B-966B-9C53A35B072B} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{9B74CCC3-9634-4A09-A270-CE1101D96824} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{DDEA0B6A-A615-4CF8-8B23-F93E390454B2} = {1B8D5897-902E-4632-8698-E89CAF3DDF54}
|
||||
{F52DF980-C8F7-49D5-A8A1-249B44223600} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{E8D76C93-4FE6-4B97-BC16-C8490CF3C8CC} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{C9E1429E-BC22-4ABC-820D-08709793ECE7} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{24CE63F9-29D1-4243-9144-BB2C1590FCC0} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{D3F07276-CD16-46BD-AEB1-8C7D6D7910C5} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{A5BE660B-BED0-4D72-BC60-2E6EB42061C0} = {3D0A6C71-4B96-411B-80DB-DDFAFF77C748}
|
||||
{86A93965-54B1-4983-9A87-6E3ADB584BED} = {3D0A6C71-4B96-411B-80DB-DDFAFF77C748}
|
||||
{E1F2B414-D9E4-4789-8138-3F9DA076FFB6} = {3D0A6C71-4B96-411B-80DB-DDFAFF77C748}
|
||||
|
|
@ -2044,11 +2106,24 @@ Global
|
|||
{6A17BD0C-8643-4684-BC3F-9E378A467605} = {3D0A6C71-4B96-411B-80DB-DDFAFF77C748}
|
||||
{2248A649-6CA4-4A1A-8BC3-34257238B560} = {3D0A6C71-4B96-411B-80DB-DDFAFF77C748}
|
||||
{807C6ACA-1C4B-4AC4-A60C-1FE6B9AB38AC} = {D3E5E9EF-DE26-41BF-A239-3241B5B5FD89}
|
||||
{418472CD-1215-4962-9024-F26E9863B5A4} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{E8D76C93-4FE6-4B97-BC16-C8490CF3C8CC} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{C9E1429E-BC22-4ABC-820D-08709793ECE7} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{24CE63F9-29D1-4243-9144-BB2C1590FCC0} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{D3F07276-CD16-46BD-AEB1-8C7D6D7910C5} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{C597B963-A80F-4093-B3CC-9060854D9D38} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{E087B3BD-D579-422B-A29F-965D33E2C769} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{1C70A220-E69F-434B-966B-9C53A35B072B} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{9B74CCC3-9634-4A09-A270-CE1101D96824} = {18453B51-25EB-4317-A4B3-B10518252E92}
|
||||
{DDEA0B6A-A615-4CF8-8B23-F93E390454B2} = {1B8D5897-902E-4632-8698-E89CAF3DDF54}
|
||||
{F52DF980-C8F7-49D5-A8A1-249B44223600} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{9323DC40-29B4-4438-AAD7-C4D4069C072B} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{73BBB1E3-AEEC-44E8-83D7-6DD9CD687FE3} = {9323DC40-29B4-4438-AAD7-C4D4069C072B}
|
||||
{DD8D1712-B42C-4BF2-99AF-3F092E508C62} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
|
||||
{27300F17-F959-4D4A-885F-FDDBE81456C1} = {DD8D1712-B42C-4BF2-99AF-3F092E508C62}
|
||||
{4FD4C59B-2804-4F6B-AD38-2562CC01C510} = {DD8D1712-B42C-4BF2-99AF-3F092E508C62}
|
||||
{4A57961A-ED52-471F-BA21-EAEE9100E485} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{6BE15A6D-F543-4084-BF6E-F00FD71F60F3} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{32F2EE33-8190-41D7-BD12-45AA02BEB930} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{2D51FFE0-F114-48E1-BF58-FCED0FD1944F} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
{743C1835-E41E-4E5C-9D12-585BAEE59EEE} = {F52DF980-C8F7-49D5-A8A1-249B44223600}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
using Elsa.Persistence.EFCore.Abstractions;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AIDbContextFactory : MySqlAIDesignTimeDbContextFactory<AIDbContext>;
|
||||
|
||||
public class MySqlAIDesignTimeDbContextFactory<TDbContext> : DesignTimeDbContextFactoryBase<TDbContext> where TDbContext : DbContext
|
||||
{
|
||||
protected override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMySqlEntityModelCreatingHandlers();
|
||||
}
|
||||
|
||||
protected override void ConfigureBuilder(DbContextOptionsBuilder<TDbContext> builder, string connectionString)
|
||||
{
|
||||
builder.UseElsaMySql(GetType().Assembly, connectionString, serverVersion: ServerVersion.Parse("9.0.0"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Pomelo targets EF Core up to 9.x, so exclude MySQL provider for net10.0. -->
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<Description>
|
||||
Provides MySQL EF Core migrations for Elsa AI persistence.
|
||||
</Description>
|
||||
<PackageTags>elsa module ai persistence efcore mysql</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.MySql\Elsa.Persistence.EFCore.MySql.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Host\Elsa.AI.Host.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System.Reflection;
|
||||
using Elsa.AI.Persistence.EFCore.Features;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql.Extensions;
|
||||
|
||||
public static class MySqlAIPersistenceFeatureExtensions
|
||||
{
|
||||
private static Assembly Assembly => typeof(MySqlAIPersistenceFeatureExtensions).Assembly;
|
||||
|
||||
public static AIPersistenceFeature UseMySql(
|
||||
this AIPersistenceFeature feature,
|
||||
string connectionString,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<MySqlDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseMySql(_ => connectionString, options, configure);
|
||||
}
|
||||
|
||||
public static AIPersistenceFeature UseMySql(
|
||||
this AIPersistenceFeature feature,
|
||||
Func<IServiceProvider, string> connectionStringFunc,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<MySqlDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseMySql(Assembly, connectionStringFunc, options, configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||
</Weavers>
|
||||
208
src/modules/Elsa.AI.Persistence.EFCore.MySql/Migrations/AI/20260608124957_Initial.Designer.cs
generated
Normal file
208
src/modules/Elsa.AI.Persistence.EFCore.MySql/Migrations/AI/20260608124957_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260608124957_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
using System;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql.Migrations.AI
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
private readonly IElsaDbContextSchema _schema;
|
||||
|
||||
public Initial(IElsaDbContextSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: _schema.Schema);
|
||||
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TenantId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ActorId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConversationId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ProposalId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ToolInvocationId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Type = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Timestamp = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false),
|
||||
TraceId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Summary = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Data = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TenantId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Title = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false),
|
||||
ProviderSessionId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RetentionMode = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RetentionExpiresAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
|
||||
Messages = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TenantId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ConversationId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Kind = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
BaselineVersionId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
WorkflowPayload = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Rationale = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Warnings = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ValidationDiagnostics = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
GraphDiff = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedBy = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false),
|
||||
ReviewedBy = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ReviewedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
|
||||
AppliedBy = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
AppliedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using CShells.Features;
|
||||
using Elsa.AI.Host.ShellFeatures;
|
||||
using Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.MySql.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
DisplayName = "MySQL AI Persistence",
|
||||
Description = "Provides MySQL persistence for Weaver AI conversations, proposals and audit records",
|
||||
DependsOn = [typeof(AIFeature)])]
|
||||
[UsedImplicitly]
|
||||
[ManifestInfrastructure("mysql-database", "database", Reason = "Stores Weaver AI persistence data in MySQL.", Providers = new[] { "MySQL" }, ConfigurationKeys = new[] { "ConnectionString" })]
|
||||
public class MySqlAIPersistenceShellFeature : EFCoreAIPersistenceShellFeatureBase
|
||||
{
|
||||
protected override void ConfigureProvider(DbContextOptionsBuilder builder, Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options)
|
||||
{
|
||||
builder.UseElsaMySql(migrationsAssembly, connectionString, options);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(IServiceCollection services)
|
||||
{
|
||||
services.AddMySqlEntityModelCreatingHandlers();
|
||||
base.OnConfiguring(services);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Abstractions;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AIDbContextFactory : OracleAIDesignTimeDbContextFactory<AIDbContext>;
|
||||
|
||||
public class OracleAIDesignTimeDbContextFactory<TDbContext> : DesignTimeDbContextFactoryBase<TDbContext> where TDbContext : DbContext
|
||||
{
|
||||
protected override void ConfigureBuilder(DbContextOptionsBuilder<TDbContext> builder, string connectionString)
|
||||
{
|
||||
var options = new ElsaDbContextOptions().ConfigureOracle();
|
||||
builder.UseElsaOracle(GetType().Assembly, connectionString, options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>
|
||||
Provides Oracle EF Core migrations for Elsa AI persistence.
|
||||
</Description>
|
||||
<PackageTags>elsa module ai persistence efcore oracle</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.Oracle\Elsa.Persistence.EFCore.Oracle.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Host\Elsa.AI.Host.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System.Reflection;
|
||||
using Elsa.AI.Persistence.EFCore.Features;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Oracle.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle.Extensions;
|
||||
|
||||
public static class OracleAIPersistenceFeatureExtensions
|
||||
{
|
||||
private static Assembly Assembly => typeof(OracleAIPersistenceFeatureExtensions).Assembly;
|
||||
|
||||
public static AIPersistenceFeature UseOracle(
|
||||
this AIPersistenceFeature feature,
|
||||
string connectionString,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<OracleDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseOracle(_ => connectionString, options, configure);
|
||||
}
|
||||
|
||||
public static AIPersistenceFeature UseOracle(
|
||||
this AIPersistenceFeature feature,
|
||||
Func<IServiceProvider, string> connectionStringFunc,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<OracleDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseOracle(Assembly, connectionStringFunc, options, configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||
</Weavers>
|
||||
208
src/modules/Elsa.AI.Persistence.EFCore.Oracle/Migrations/AI/20260608125003_Initial.Designer.cs
generated
Normal file
208
src/modules/Elsa.AI.Persistence.EFCore.Oracle/Migrations/AI/20260608125003_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Oracle.EntityFrameworkCore.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260608125003_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
using System;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle.Migrations.AI
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
private readonly IElsaDbContextSchema _schema;
|
||||
|
||||
public Initial(IElsaDbContextSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: _schema.Schema);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
ActorId = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
ConversationId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
ProposalId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
ToolInvocationId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
Type = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
Timestamp = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false),
|
||||
TraceId = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
Summary = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
Data = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
UserId = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
Title = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
Status = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false),
|
||||
ProviderSessionId = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
RetentionMode = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
RetentionExpiresAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: true),
|
||||
Messages = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "NVARCHAR2(450)", nullable: true),
|
||||
ConversationId = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
Kind = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
Status = table.Column<string>(type: "NVARCHAR2(450)", nullable: false),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
BaselineVersionId = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
WorkflowPayload = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
Rationale = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
Warnings = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
ValidationDiagnostics = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
GraphDiff = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
CreatedBy = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false),
|
||||
ReviewedBy = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
ReviewedAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: true),
|
||||
AppliedBy = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true),
|
||||
AppliedAt = table.Column<DateTimeOffset>(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Oracle.EntityFrameworkCore.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("TIMESTAMP(7) WITH TIME ZONE");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("NVARCHAR2(450)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("NVARCHAR2(2000)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using System.Reflection;
|
||||
using CShells.Features;
|
||||
using Elsa.AI.Host.ShellFeatures;
|
||||
using Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Oracle.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
DisplayName = "Oracle AI Persistence",
|
||||
Description = "Provides Oracle persistence for Weaver AI conversations, proposals and audit records",
|
||||
DependsOn = [typeof(AIFeature)])]
|
||||
[UsedImplicitly]
|
||||
[ManifestInfrastructure("oracle-database", "database", Reason = "Stores Weaver AI persistence data in Oracle Database.", Providers = new[] { "Oracle" }, ConfigurationKeys = new[] { "ConnectionString" })]
|
||||
public class OracleAIPersistenceShellFeature : EFCoreAIPersistenceShellFeatureBase
|
||||
{
|
||||
protected override void ConfigureProvider(DbContextOptionsBuilder builder, Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options)
|
||||
{
|
||||
options = options.ConfigureOracle();
|
||||
builder.UseElsaOracle(migrationsAssembly, connectionString, options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Elsa.Persistence.EFCore.Abstractions;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AIDbContextFactory : PostgreSqlAIDesignTimeDbContextFactory<AIDbContext>;
|
||||
|
||||
public class PostgreSqlAIDesignTimeDbContextFactory<TDbContext> : DesignTimeDbContextFactoryBase<TDbContext> where TDbContext : DbContext
|
||||
{
|
||||
protected override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddPostgreSqlEntityModelCreatingHandlers();
|
||||
}
|
||||
|
||||
protected override void ConfigureBuilder(DbContextOptionsBuilder<TDbContext> builder, string connectionString)
|
||||
{
|
||||
builder.UseElsaPostgreSql(GetType().Assembly, connectionString);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>
|
||||
Provides PostgreSQL EF Core migrations for Elsa AI persistence.
|
||||
</Description>
|
||||
<PackageTags>elsa module ai persistence efcore postgresql</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.PostgreSql\Elsa.Persistence.EFCore.PostgreSql.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Host\Elsa.AI.Host.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System.Reflection;
|
||||
using Elsa.AI.Persistence.EFCore.Features;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql.Extensions;
|
||||
|
||||
public static class PostgreSqlAIPersistenceFeatureExtensions
|
||||
{
|
||||
private static Assembly Assembly => typeof(PostgreSqlAIPersistenceFeatureExtensions).Assembly;
|
||||
|
||||
public static AIPersistenceFeature UsePostgreSql(
|
||||
this AIPersistenceFeature feature,
|
||||
string connectionString,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<NpgsqlDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UsePostgreSql(_ => connectionString, options, configure);
|
||||
}
|
||||
|
||||
public static AIPersistenceFeature UsePostgreSql(
|
||||
this AIPersistenceFeature feature,
|
||||
Func<IServiceProvider, string> connectionStringFunc,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<NpgsqlDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UsePostgreSql(Assembly, connectionStringFunc, options, configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||
</Weavers>
|
||||
208
src/modules/Elsa.AI.Persistence.EFCore.PostgreSql/Migrations/AI/20260608124950_Initial.Designer.cs
generated
Normal file
208
src/modules/Elsa.AI.Persistence.EFCore.PostgreSql/Migrations/AI/20260608124950_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260608124950_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
using System;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql.Migrations.AI
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
private readonly IElsaDbContextSchema _schema;
|
||||
|
||||
public Initial(IElsaDbContextSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: _schema.Schema);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "text", nullable: false),
|
||||
TenantId = table.Column<string>(type: "text", nullable: true),
|
||||
ActorId = table.Column<string>(type: "text", nullable: false),
|
||||
ConversationId = table.Column<string>(type: "text", nullable: true),
|
||||
ProposalId = table.Column<string>(type: "text", nullable: true),
|
||||
ToolInvocationId = table.Column<string>(type: "text", nullable: true),
|
||||
Type = table.Column<string>(type: "text", nullable: false),
|
||||
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
TraceId = table.Column<string>(type: "text", nullable: true),
|
||||
Summary = table.Column<string>(type: "text", nullable: false),
|
||||
Data = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "text", nullable: false),
|
||||
TenantId = table.Column<string>(type: "text", nullable: true),
|
||||
UserId = table.Column<string>(type: "text", nullable: false),
|
||||
Title = table.Column<string>(type: "text", nullable: true),
|
||||
Status = table.Column<string>(type: "text", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
ProviderSessionId = table.Column<string>(type: "text", nullable: true),
|
||||
RetentionMode = table.Column<string>(type: "text", nullable: false),
|
||||
RetentionExpiresAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
Messages = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "text", nullable: false),
|
||||
TenantId = table.Column<string>(type: "text", nullable: true),
|
||||
ConversationId = table.Column<string>(type: "text", nullable: false),
|
||||
Kind = table.Column<string>(type: "text", nullable: false),
|
||||
Status = table.Column<string>(type: "text", nullable: false),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(type: "text", nullable: true),
|
||||
BaselineVersionId = table.Column<string>(type: "text", nullable: true),
|
||||
WorkflowPayload = table.Column<string>(type: "text", nullable: false),
|
||||
Rationale = table.Column<string>(type: "text", nullable: false),
|
||||
Warnings = table.Column<string>(type: "text", nullable: false),
|
||||
ValidationDiagnostics = table.Column<string>(type: "text", nullable: false),
|
||||
GraphDiff = table.Column<string>(type: "text", nullable: true),
|
||||
CreatedBy = table.Column<string>(type: "text", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
ReviewedBy = table.Column<string>(type: "text", nullable: true),
|
||||
ReviewedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
AppliedBy = table.Column<string>(type: "text", nullable: true),
|
||||
AppliedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using CShells.Features;
|
||||
using Elsa.AI.Host.ShellFeatures;
|
||||
using Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.PostgreSql.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
DisplayName = "PostgreSQL AI Persistence",
|
||||
Description = "Provides PostgreSQL persistence for Weaver AI conversations, proposals and audit records",
|
||||
DependsOn = [typeof(AIFeature)])]
|
||||
[UsedImplicitly]
|
||||
[ManifestInfrastructure("postgresql-database", "database", Reason = "Stores Weaver AI persistence data in PostgreSQL.", Providers = new[] { "PostgreSQL" }, ConfigurationKeys = new[] { "ConnectionString" })]
|
||||
public class PostgreSqlAIPersistenceShellFeature : EFCoreAIPersistenceShellFeatureBase
|
||||
{
|
||||
protected override void ConfigureProvider(DbContextOptionsBuilder builder, Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options)
|
||||
{
|
||||
builder.UseElsaPostgreSql(migrationsAssembly, connectionString, options);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(IServiceCollection services)
|
||||
{
|
||||
services.AddPostgreSqlEntityModelCreatingHandlers();
|
||||
base.OnConfiguring(services);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Elsa.Persistence.EFCore.Abstractions;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AIDbContextFactory : SqlServerAIDesignTimeDbContextFactory<AIDbContext>;
|
||||
|
||||
public class SqlServerAIDesignTimeDbContextFactory<TDbContext> : DesignTimeDbContextFactoryBase<TDbContext> where TDbContext : DbContext
|
||||
{
|
||||
protected override void ConfigureBuilder(DbContextOptionsBuilder<TDbContext> builder, string connectionString)
|
||||
{
|
||||
builder.UseElsaSqlServer(GetType().Assembly, connectionString);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>
|
||||
Provides SQL Server EF Core migrations for Elsa AI persistence.
|
||||
</Description>
|
||||
<PackageTags>elsa module ai persistence efcore sqlserver</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.SqlServer\Elsa.Persistence.EFCore.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Host\Elsa.AI.Host.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System.Reflection;
|
||||
using Elsa.AI.Persistence.EFCore.Features;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer.Extensions;
|
||||
|
||||
public static class SqlServerAIPersistenceFeatureExtensions
|
||||
{
|
||||
private static Assembly Assembly => typeof(SqlServerAIPersistenceFeatureExtensions).Assembly;
|
||||
|
||||
public static AIPersistenceFeature UseSqlServer(
|
||||
this AIPersistenceFeature feature,
|
||||
string connectionString,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<SqlServerDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseSqlServer(_ => connectionString, options, configure);
|
||||
}
|
||||
|
||||
public static AIPersistenceFeature UseSqlServer(
|
||||
this AIPersistenceFeature feature,
|
||||
Func<IServiceProvider, string> connectionStringFunc,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<SqlServerDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseSqlServer(Assembly, connectionStringFunc, options, configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||
</Weavers>
|
||||
208
src/modules/Elsa.AI.Persistence.EFCore.SqlServer/Migrations/AI/20260608124944_Initial.Designer.cs
generated
Normal file
208
src/modules/Elsa.AI.Persistence.EFCore.SqlServer/Migrations/AI/20260608124944_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260608124944_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
using System;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer.Migrations.AI
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
private readonly IElsaDbContextSchema _schema;
|
||||
|
||||
public Initial(IElsaDbContextSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: _schema.Schema);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
ActorId = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
ConversationId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
ProposalId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
ToolInvocationId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
Type = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Timestamp = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||
TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
Summary = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Data = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
Status = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||
ProviderSessionId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
RetentionMode = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
RetentionExpiresAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
|
||||
Messages = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
TenantId = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
ConversationId = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
Kind = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Status = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
BaselineVersionId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
WorkflowPayload = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Rationale = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Warnings = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
ValidationDiagnostics = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
GraphDiff = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||
ReviewedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
ReviewedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
|
||||
AppliedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
AppliedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using System.Reflection;
|
||||
using CShells.Features;
|
||||
using Elsa.AI.Host.ShellFeatures;
|
||||
using Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.SqlServer.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
DisplayName = "SQL Server AI Persistence",
|
||||
Description = "Provides SQL Server persistence for Weaver AI conversations, proposals and audit records",
|
||||
DependsOn = [typeof(AIFeature)])]
|
||||
[UsedImplicitly]
|
||||
[ManifestInfrastructure("sqlserver-database", "database", Reason = "Stores Weaver AI persistence data in SQL Server.", Providers = new[] { "SQL Server" }, ConfigurationKeys = new[] { "ConnectionString" })]
|
||||
public class SqlServerAIPersistenceShellFeature : EFCoreAIPersistenceShellFeatureBase
|
||||
{
|
||||
protected override void ConfigureProvider(DbContextOptionsBuilder builder, Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options)
|
||||
{
|
||||
builder.UseElsaSqlServer(migrationsAssembly, connectionString, options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Elsa.Persistence.EFCore.Abstractions;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AIDbContextFactory : SqliteAIDesignTimeDbContextFactory<AIDbContext>;
|
||||
|
||||
public class SqliteAIDesignTimeDbContextFactory<TDbContext> : DesignTimeDbContextFactoryBase<TDbContext> where TDbContext : DbContext
|
||||
{
|
||||
protected override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSqliteEntityModelCreatingHandlers();
|
||||
}
|
||||
|
||||
protected override void ConfigureBuilder(DbContextOptionsBuilder<TDbContext> builder, string connectionString)
|
||||
{
|
||||
builder.UseElsaSqlite(GetType().Assembly, connectionString);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>
|
||||
Provides SQLite EF Core migrations for Elsa AI persistence.
|
||||
</Description>
|
||||
<PackageTags>elsa module ai persistence efcore sqlite</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.Sqlite\Elsa.Persistence.EFCore.Sqlite.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Host\Elsa.AI.Host.csproj" />
|
||||
<ProjectReference Include="..\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System.Reflection;
|
||||
using Elsa.AI.Persistence.EFCore.Features;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite.Extensions;
|
||||
|
||||
public static class SqliteAIPersistenceFeatureExtensions
|
||||
{
|
||||
private static Assembly Assembly => typeof(SqliteAIPersistenceFeatureExtensions).Assembly;
|
||||
|
||||
public static AIPersistenceFeature UseSqlite(
|
||||
this AIPersistenceFeature feature,
|
||||
string? connectionString = null,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<SqliteDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
connectionString ??= "Data Source=elsa.sqlite.db;Cache=Shared;";
|
||||
return feature.UseSqlite(_ => connectionString, options, configure);
|
||||
}
|
||||
|
||||
public static AIPersistenceFeature UseSqlite(
|
||||
this AIPersistenceFeature feature,
|
||||
Func<IServiceProvider, string> connectionStringFunc,
|
||||
ElsaDbContextOptions? options = null,
|
||||
Action<SqliteDbContextOptionsBuilder>? configure = null)
|
||||
{
|
||||
return feature.UseSqlite(Assembly, connectionStringFunc, options, configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||
</Weavers>
|
||||
207
src/modules/Elsa.AI.Persistence.EFCore.Sqlite/Migrations/AI/20260608124921_Initial.Designer.cs
generated
Normal file
207
src/modules/Elsa.AI.Persistence.EFCore.Sqlite/Migrations/AI/20260608124921_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// <auto-generated />
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260608124921_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16");
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Timestamp")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RetentionExpiresAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UpdatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AppliedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReviewedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
using System;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite.Migrations.AI
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
private readonly IElsaDbContextSchema _schema;
|
||||
|
||||
public Initial(IElsaDbContextSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: _schema.Schema);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
TenantId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ActorId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ConversationId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ProposalId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ToolInvocationId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Type = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Timestamp = table.Column<string>(type: "TEXT", nullable: false),
|
||||
TraceId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Summary = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Data = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
TenantId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
UserId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Status = table.Column<string>(type: "TEXT", nullable: false),
|
||||
CreatedAt = table.Column<string>(type: "TEXT", nullable: false),
|
||||
UpdatedAt = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ProviderSessionId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
RetentionMode = table.Column<string>(type: "TEXT", nullable: false),
|
||||
RetentionExpiresAt = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Messages = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema,
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
TenantId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ConversationId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Kind = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Status = table.Column<string>(type: "TEXT", nullable: false),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
BaselineVersionId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
WorkflowPayload = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Rationale = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Warnings = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ValidationDiagnostics = table.Column<string>(type: "TEXT", nullable: false),
|
||||
GraphDiff = table.Column<string>(type: "TEXT", nullable: true),
|
||||
CreatedBy = table.Column<string>(type: "TEXT", nullable: false),
|
||||
CreatedAt = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ReviewedBy = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ReviewedAt = table.Column<string>(type: "TEXT", nullable: true),
|
||||
AppliedBy = table.Column<string>(type: "TEXT", nullable: true),
|
||||
AppliedAt = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
schema: _schema.Schema,
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIAuditRecords",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIConversations",
|
||||
schema: _schema.Schema);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AIProposals",
|
||||
schema: _schema.Schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
// <auto-generated />
|
||||
using Elsa.AI.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite.Migrations.AI
|
||||
{
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("Elsa")
|
||||
.HasAnnotation("ProductVersion", "9.0.16");
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProposalId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Timestamp")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ToolInvocationId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TraceId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderSessionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RetentionExpiresAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UpdatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations", "Elsa");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AppliedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AppliedBy")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("BaselineVersionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedAt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GraphDiff")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReviewedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReviewedBy")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TenantId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals", "Elsa");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using CShells.Features;
|
||||
using Elsa.AI.Host.ShellFeatures;
|
||||
using Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Elsa.Persistence.EFCore.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Sqlite.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
DisplayName = "SQLite AI Persistence",
|
||||
Description = "Provides SQLite persistence for Weaver AI conversations, proposals and audit records",
|
||||
DependsOn = [typeof(AIFeature)])]
|
||||
[UsedImplicitly]
|
||||
[ManifestInfrastructure("sqlite-database", "database", Reason = "Stores Weaver AI persistence data in SQLite.", Providers = new[] { "SQLite" }, ConfigurationKeys = new[] { "ConnectionString" })]
|
||||
public class SqliteAIPersistenceShellFeature : EFCoreAIPersistenceShellFeatureBase
|
||||
{
|
||||
protected override void ConfigureProvider(DbContextOptionsBuilder builder, Assembly migrationsAssembly, string connectionString, ElsaDbContextOptions? options)
|
||||
{
|
||||
builder.UseElsaSqlite(migrationsAssembly, connectionString, options);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(IServiceCollection services)
|
||||
{
|
||||
services.AddSqliteEntityModelCreatingHandlers();
|
||||
base.OnConfiguring(services);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,21 @@
|
|||
using Elsa.AI.Persistence.EFCore.Entities;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore;
|
||||
|
||||
public class AIDbContext(DbContextOptions<AIDbContext> options) : DbContext(options)
|
||||
public class AIDbContext : ElsaDbContextBase
|
||||
{
|
||||
private static readonly IServiceProvider EmptyServiceProvider = new ServiceCollection().BuildServiceProvider();
|
||||
|
||||
public AIDbContext(DbContextOptions<AIDbContext> options) : this(options, EmptyServiceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public AIDbContext(DbContextOptions<AIDbContext> options, IServiceProvider serviceProvider) : base(options, serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<AIConversationRecord> Conversations => Set<AIConversationRecord>();
|
||||
public DbSet<AIProposalRecord> Proposals => Set<AIProposalRecord>();
|
||||
public DbSet<AIAuditRecord> AuditRecords => Set<AIAuditRecord>();
|
||||
|
|
@ -46,5 +58,7 @@ public class AIDbContext(DbContextOptions<AIDbContext> options) : DbContext(opti
|
|||
entity.Property(x => x.RetentionMode).IsRequired();
|
||||
entity.Property(x => x.Messages).IsRequired();
|
||||
});
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
<PackageReference Include="CShells" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Elsa.AI.Abstractions\Elsa.AI.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore.Common\Elsa.Persistence.EFCore.Common.csproj" />
|
||||
<ProjectReference Include="..\..\common\Elsa.Features\Elsa.Features.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,13 @@ public static class ServiceCollectionExtensions
|
|||
}
|
||||
|
||||
services.TryAddScoped<AIDbContext>();
|
||||
services.AddAIPersistenceStoreServices();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddAIPersistenceStoreServices(this IServiceCollection services)
|
||||
{
|
||||
services.Replace(ServiceDescriptor.Scoped<IAIConversationStore, EFCoreAIConversationStore>());
|
||||
services.Replace(ServiceDescriptor.Scoped<IAIProposalStore, EFCoreAIProposalStore>());
|
||||
services.TryAddEnumerable(ServiceDescriptor.Scoped<IAIAuditEventHandler, EFCoreAIAuditSink>());
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Features.Abstractions;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Features;
|
||||
|
||||
public class AIPersistenceFeature(IModule module) : FeatureBase(module)
|
||||
public class AIPersistenceFeature(IModule module) : PersistenceFeatureBase<AIPersistenceFeature, AIDbContext>(module)
|
||||
{
|
||||
public Action<DbContextOptionsBuilder>? ConfigureDbContext { get; set; }
|
||||
|
||||
public override void Apply()
|
||||
{
|
||||
Services.AddAIPersistenceStores(ConfigureDbContext);
|
||||
if (DbContextOptionsBuilder == null && ConfigureDbContext != null)
|
||||
DbContextOptionsBuilder = (_, builder) => ConfigureDbContext(builder);
|
||||
|
||||
base.Apply();
|
||||
Services.AddScoped(sp => sp.GetRequiredService<IDbContextFactory<AIDbContext>>().CreateDbContext());
|
||||
Services.AddAIPersistenceStoreServices();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Migrations;
|
||||
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
[Migration("20260521002000_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.16");
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ConversationId");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ProposalId");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp");
|
||||
|
||||
b.Property<string>("ToolInvocationId");
|
||||
|
||||
b.Property<string>("TraceId");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ProviderSessionId");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<string>("AppliedBy");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt");
|
||||
|
||||
b.Property<string>("BaselineVersionId");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("GraphDiff");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ReviewedBy");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Migrations;
|
||||
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIAuditRecords",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
TenantId = table.Column<string>(nullable: true),
|
||||
ActorId = table.Column<string>(nullable: false),
|
||||
ConversationId = table.Column<string>(nullable: true),
|
||||
ProposalId = table.Column<string>(nullable: true),
|
||||
ToolInvocationId = table.Column<string>(nullable: true),
|
||||
Type = table.Column<string>(nullable: false),
|
||||
Timestamp = table.Column<DateTimeOffset>(nullable: false),
|
||||
TraceId = table.Column<string>(nullable: true),
|
||||
Summary = table.Column<string>(nullable: false),
|
||||
Data = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIAuditRecords", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIConversations",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
TenantId = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
Title = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(nullable: false),
|
||||
ProviderSessionId = table.Column<string>(nullable: true),
|
||||
RetentionMode = table.Column<string>(nullable: false),
|
||||
RetentionExpiresAt = table.Column<DateTimeOffset>(nullable: true),
|
||||
Messages = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIConversations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AIProposals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
TenantId = table.Column<string>(nullable: true),
|
||||
ConversationId = table.Column<string>(nullable: false),
|
||||
Kind = table.Column<string>(nullable: false),
|
||||
Status = table.Column<string>(nullable: false),
|
||||
BaselineWorkflowDefinitionId = table.Column<string>(nullable: true),
|
||||
BaselineVersionId = table.Column<string>(nullable: true),
|
||||
WorkflowPayload = table.Column<string>(nullable: false),
|
||||
Rationale = table.Column<string>(nullable: false),
|
||||
Warnings = table.Column<string>(nullable: false),
|
||||
ValidationDiagnostics = table.Column<string>(nullable: false),
|
||||
GraphDiff = table.Column<string>(nullable: true),
|
||||
CreatedBy = table.Column<string>(nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(nullable: false),
|
||||
ReviewedBy = table.Column<string>(nullable: true),
|
||||
ReviewedAt = table.Column<DateTimeOffset>(nullable: true),
|
||||
AppliedBy = table.Column<string>(nullable: true),
|
||||
AppliedAt = table.Column<DateTimeOffset>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AIProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ProposalId",
|
||||
table: "AIAuditRecords",
|
||||
column: "ProposalId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ActorId",
|
||||
table: "AIAuditRecords",
|
||||
column: "ActorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_Timestamp",
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "Timestamp" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_TenantId_ConversationId",
|
||||
table: "AIAuditRecords",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIAuditRecords_ToolInvocationId",
|
||||
table: "AIAuditRecords",
|
||||
column: "ToolInvocationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_RetentionExpiresAt",
|
||||
table: "AIConversations",
|
||||
column: "RetentionExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_Status",
|
||||
table: "AIConversations",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIConversations_TenantId_UserId",
|
||||
table: "AIConversations",
|
||||
columns: new[] { "TenantId", "UserId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_Status",
|
||||
table: "AIProposals",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AIProposals_TenantId_ConversationId",
|
||||
table: "AIProposals",
|
||||
columns: new[] { "TenantId", "ConversationId" });
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(name: "AIAuditRecords");
|
||||
migrationBuilder.DropTable(name: "AIConversations");
|
||||
migrationBuilder.DropTable(name: "AIProposals");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.Migrations;
|
||||
|
||||
[DbContext(typeof(AIDbContext))]
|
||||
partial class AIDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.16");
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIAuditRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<string>("ActorId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ConversationId");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ProposalId");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp");
|
||||
|
||||
b.Property<string>("ToolInvocationId");
|
||||
|
||||
b.Property<string>("TraceId");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ActorId");
|
||||
|
||||
b.HasIndex("ProposalId");
|
||||
|
||||
b.HasIndex("ToolInvocationId");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.HasIndex("TenantId", "Timestamp");
|
||||
|
||||
b.ToTable("AIAuditRecords");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIConversationRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt");
|
||||
|
||||
b.Property<string>("Messages")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ProviderSessionId");
|
||||
|
||||
b.Property<DateTimeOffset?>("RetentionExpiresAt");
|
||||
|
||||
b.Property<string>("RetentionMode")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RetentionExpiresAt");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "UserId");
|
||||
|
||||
b.ToTable("AIConversations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Elsa.AI.Persistence.EFCore.Entities.AIProposalRecord", b =>
|
||||
{
|
||||
b.Property<string>("Id");
|
||||
|
||||
b.Property<string>("AppliedBy");
|
||||
|
||||
b.Property<DateTimeOffset?>("AppliedAt");
|
||||
|
||||
b.Property<string>("BaselineVersionId");
|
||||
|
||||
b.Property<string>("BaselineWorkflowDefinitionId");
|
||||
|
||||
b.Property<string>("ConversationId")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("GraphDiff");
|
||||
|
||||
b.Property<string>("Kind")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Rationale")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("ReviewedBy");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReviewedAt");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("TenantId");
|
||||
|
||||
b.Property<string>("ValidationDiagnostics")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("Warnings")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<string>("WorkflowPayload")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("TenantId", "ConversationId");
|
||||
|
||||
b.ToTable("AIProposals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
using CShells.Features;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Platform.PackageManifest.Generator.Hints;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
|
||||
[ManifestFeatureCategory("AI")]
|
||||
[ManifestFeatureCategory("Persistence")]
|
||||
[ShellFeature(
|
||||
"AIPersistence",
|
||||
DisplayName = "AI Persistence",
|
||||
Description = "Registers durable EF Core stores for Weaver AI conversations, proposals and audit records")]
|
||||
[UsedImplicitly]
|
||||
public class AIPersistenceFeature : IShellFeature
|
||||
{
|
||||
public Action<DbContextOptionsBuilder>? ConfigureDbContext { get; set; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddAIPersistenceStores(ConfigureDbContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.ShellFeatures;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for provider-specific AI persistence shell features.
|
||||
/// </summary>
|
||||
public abstract class EFCoreAIPersistenceShellFeatureBase : PersistenceShellFeatureBase<AIDbContext>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void OnConfiguring(IServiceCollection services)
|
||||
{
|
||||
services.AddScoped(sp => sp.GetRequiredService<IDbContextFactory<AIDbContext>>().CreateDbContext());
|
||||
services.AddAIPersistenceStoreServices();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using Elsa.AI.Persistence.EFCore.Sqlite;
|
||||
using Elsa.Persistence.EFCore;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elsa.AI.Persistence.EFCore.UnitTests;
|
||||
|
||||
internal static class AIDbContextOptionsBuilderExtensions
|
||||
{
|
||||
public static DbContextOptionsBuilder<AIDbContext> UseSqliteAIMigrations(this DbContextOptionsBuilder<AIDbContext> builder, SqliteConnection connection)
|
||||
{
|
||||
builder.UseElsaDbContextOptions(null);
|
||||
return builder.UseSqlite(connection, db => db.MigrationsAssembly(typeof(AIDbContextFactory).Assembly.GetName().Name));
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ public class EFCoreAIAuditSinkTests : IAsyncLifetime
|
|||
public async Task InitializeAsync()
|
||||
{
|
||||
await _connection.OpenAsync();
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqlite(_connection).Options);
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqliteAIMigrations(_connection).Options);
|
||||
await _dbContext.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ public class EFCoreAIConversationStoreTests : IAsyncLifetime
|
|||
public async Task InitializeAsync()
|
||||
{
|
||||
await _connection.OpenAsync();
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqlite(_connection).Options);
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqliteAIMigrations(_connection).Options);
|
||||
await _dbContext.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ public class EFCoreAIProposalStoreTests : IAsyncLifetime
|
|||
public async Task ProposalStoreRetriesConcurrentInsertsAsUpdates()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<AIDbContext>()
|
||||
.UseSqlite(_connection)
|
||||
.UseSqliteAIMigrations(_connection)
|
||||
.AddInterceptors(new ConcurrentProposalInsertInterceptor(_connection))
|
||||
.Options;
|
||||
await using var context = new AIDbContext(options);
|
||||
|
|
@ -344,7 +344,7 @@ public class EFCoreAIProposalStoreTests : IAsyncLifetime
|
|||
public async Task InitializeAsync()
|
||||
{
|
||||
await _connection.OpenAsync();
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqlite(_connection).Options);
|
||||
_dbContext = new AIDbContext(new DbContextOptionsBuilder<AIDbContext>().UseSqliteAIMigrations(_connection).Options);
|
||||
await _dbContext.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
|
|
@ -368,7 +368,7 @@ public class EFCoreAIProposalStoreTests : IAsyncLifetime
|
|||
return result;
|
||||
|
||||
_inserted = true;
|
||||
var options = new DbContextOptionsBuilder<AIDbContext>().UseSqlite(connection).Options;
|
||||
var options = new DbContextOptionsBuilder<AIDbContext>().UseSqliteAIMigrations(connection).Options;
|
||||
await using var competingContext = new AIDbContext(options);
|
||||
competingContext.Proposals.Add(new AIProposalRecord
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.AI.Persistence.EFCore.Sqlite\Elsa.AI.Persistence.EFCore.Sqlite.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.AI.Persistence.EFCore\Elsa.AI.Persistence.EFCore.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Loading…
Reference in a new issue