diff --git a/dotnet/.editorconfig b/dotnet/.editorconfig
new file mode 100644
index 0000000000..1e31197419
--- /dev/null
+++ b/dotnet/.editorconfig
@@ -0,0 +1,478 @@
+; EditorConfig to support per-solution formatting.
+; Use the EditorConfig VS add-in to make this work.
+; http://editorconfig.org/
+;
+; Here are some resources for what's supported for .NET/C#
+; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
+; https://learn.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference
+;
+; Be **careful** editing this because some of the rules don't support adding a severity level
+; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`)
+; then the rule will be silently ignored.
+
+; This is the default for the codeline.
+root = true
+
+[*]
+indent_style = space
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+spelling_exclusion_path = spelling.dic
+
+[*.cs]
+indent_size = 4
+dotnet_sort_system_directives_first = true
+
+# Don't use this. qualifier
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+
+# use int x = .. over Int32
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+
+# use int.MaxValue over Int32.MaxValue
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# Require var all the time.
+csharp_style_var_for_built_in_types = true:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = true:suggestion
+
+# Disallow throw expressions.
+csharp_style_throw_expression = false:suggestion
+
+# Newline settings
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+
+# Namespace settings
+csharp_style_namespace_declarations = file_scoped
+
+# Brace settings
+csharp_prefer_braces = true # Prefer curly braces even for one line of code
+
+# name all constant fields using PascalCase
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = warning
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+# static fields should have s_ prefix
+dotnet_naming_rule.static_fields_should_have_prefix.severity = warning
+dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
+dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
+dotnet_naming_style.static_prefix_style.required_prefix = s_
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
+
+# internal and private fields should be _camelCase
+dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
+dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
+dotnet_naming_style.camel_case_underscore_style.required_prefix = _
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+
+[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_size = 2
+
+[*.json]
+indent_size = 2
+
+[*.{ps1,psm1}]
+indent_size = 4
+
+[*.sh]
+indent_size = 4
+end_of_line = lf
+
+[*.{razor,cshtml}]
+charset = utf-8-bom
+
+[*.{cs,vb}]
+
+# SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time
+dotnet_diagnostic.SYSLIB1054.severity = warning
+
+# CA1018: Mark attributes with AttributeUsageAttribute
+dotnet_diagnostic.CA1018.severity = warning
+
+# CA1047: Do not declare protected member in sealed type
+dotnet_diagnostic.CA1047.severity = warning
+
+# CA1305: Specify IFormatProvider
+dotnet_diagnostic.CA1305.severity = warning
+
+# CA1507: Use nameof to express symbol names
+dotnet_diagnostic.CA1507.severity = warning
+
+# CA1510: Use ArgumentNullException throw helper
+dotnet_diagnostic.CA1510.severity = warning
+
+# CA1511: Use ArgumentException throw helper
+dotnet_diagnostic.CA1511.severity = warning
+
+# CA1512: Use ArgumentOutOfRangeException throw helper
+dotnet_diagnostic.CA1512.severity = warning
+
+# CA1513: Use ObjectDisposedException throw helper
+dotnet_diagnostic.CA1513.severity = warning
+
+# CA1725: Parameter names should match base declaration
+dotnet_diagnostic.CA1725.severity = suggestion
+
+# CA1802: Use literals where appropriate
+dotnet_diagnostic.CA1802.severity = warning
+
+# CA1805: Do not initialize unnecessarily
+dotnet_diagnostic.CA1805.severity = warning
+
+# CA1810: Do not initialize unnecessarily
+dotnet_diagnostic.CA1810.severity = warning
+
+# CA1821: Remove empty Finalizers
+dotnet_diagnostic.CA1821.severity = warning
+
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = warning
+dotnet_code_quality.CA1822.api_surface = private, internal
+
+# CA1823: Avoid unused private fields
+dotnet_diagnostic.CA1823.severity = warning
+
+# CA1825: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = warning
+
+# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
+dotnet_diagnostic.CA1826.severity = warning
+
+# CA1827: Do not use Count() or LongCount() when Any() can be used
+dotnet_diagnostic.CA1827.severity = warning
+
+# CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used
+dotnet_diagnostic.CA1828.severity = warning
+
+# CA1829: Use Length/Count property instead of Count() when available
+dotnet_diagnostic.CA1829.severity = warning
+
+# CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder
+dotnet_diagnostic.CA1830.severity = warning
+
+# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1831.severity = warning
+
+# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1832.severity = warning
+
+# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1833.severity = warning
+
+# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
+dotnet_diagnostic.CA1834.severity = warning
+
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = warning
+
+# CA1836: Prefer IsEmpty over Count
+dotnet_diagnostic.CA1836.severity = warning
+
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = warning
+
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = warning
+
+# CA1839: Use 'Environment.ProcessPath'
+dotnet_diagnostic.CA1839.severity = warning
+
+# CA1840: Use 'Environment.CurrentManagedThreadId'
+dotnet_diagnostic.CA1840.severity = warning
+
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = warning
+
+# CA1842: Do not use 'WhenAll' with a single task
+dotnet_diagnostic.CA1842.severity = warning
+
+# CA1843: Do not use 'WaitAll' with a single task
+dotnet_diagnostic.CA1843.severity = warning
+
+# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
+dotnet_diagnostic.CA1844.severity = warning
+
+# CA1845: Use span-based 'string.Concat'
+dotnet_diagnostic.CA1845.severity = warning
+
+# CA1846: Prefer AsSpan over Substring
+dotnet_diagnostic.CA1846.severity = warning
+
+# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
+dotnet_diagnostic.CA1847.severity = warning
+
+# CA1852: Seal internal types
+dotnet_diagnostic.CA1852.severity = warning
+
+# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
+dotnet_diagnostic.CA1854.severity = warning
+
+# CA1855: Prefer 'Clear' over 'Fill'
+dotnet_diagnostic.CA1855.severity = warning
+
+# CA1856: Incorrect usage of ConstantExpected attribute
+dotnet_diagnostic.CA1856.severity = error
+
+# CA1857: A constant is expected for the parameter
+dotnet_diagnostic.CA1857.severity = warning
+
+# CA1858: Use 'StartsWith' instead of 'IndexOf'
+dotnet_diagnostic.CA1858.severity = warning
+
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = warning
+
+# CA2008: Do not create tasks without passing a TaskScheduler
+dotnet_diagnostic.CA2008.severity = warning
+
+# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value
+dotnet_diagnostic.CA2009.severity = warning
+
+# CA2011: Avoid infinite recursion
+dotnet_diagnostic.CA2011.severity = warning
+
+# CA2012: Use ValueTask correctly
+dotnet_diagnostic.CA2012.severity = warning
+
+# CA2013: Do not use ReferenceEquals with value types
+dotnet_diagnostic.CA2013.severity = warning
+
+# CA2014: Do not use stackalloc in loops.
+dotnet_diagnostic.CA2014.severity = warning
+
+# CA2016: Forward the 'CancellationToken' parameter to methods that take one
+dotnet_diagnostic.CA2016.severity = warning
+
+# CA2200: Rethrow to preserve stack details
+dotnet_diagnostic.CA2200.severity = warning
+
+# CA2201: Do not raise reserved exception types
+dotnet_diagnostic.CA2201.severity = warning
+
+# CA2208: Instantiate argument exceptions correctly
+dotnet_diagnostic.CA2208.severity = warning
+
+# CA2245: Do not assign a property to itself
+dotnet_diagnostic.CA2245.severity = warning
+
+# CA2246: Assigning symbol and its member in the same statement
+dotnet_diagnostic.CA2246.severity = warning
+
+# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
+dotnet_diagnostic.CA2249.severity = warning
+
+# IDE0005: Remove unnecessary usings
+dotnet_diagnostic.IDE0005.severity = warning
+
+# IDE0011: Curly braces to surround blocks of code
+dotnet_diagnostic.IDE0011.severity = warning
+
+# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
+dotnet_diagnostic.IDE0020.severity = warning
+
+# IDE0029: Use coalesce expression (non-nullable types)
+dotnet_diagnostic.IDE0029.severity = warning
+
+# IDE0030: Use coalesce expression (nullable types)
+dotnet_diagnostic.IDE0030.severity = warning
+
+# IDE0031: Use null propagation
+dotnet_diagnostic.IDE0031.severity = warning
+
+# IDE0035: Remove unreachable code
+dotnet_diagnostic.IDE0035.severity = warning
+
+# IDE0036: Order modifiers
+csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+dotnet_diagnostic.IDE0036.severity = warning
+
+# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
+dotnet_diagnostic.IDE0038.severity = warning
+
+# IDE0043: Format string contains invalid placeholder
+dotnet_diagnostic.IDE0043.severity = warning
+
+# IDE0044: Make field readonly
+dotnet_diagnostic.IDE0044.severity = warning
+
+# IDE0051: Remove unused private members
+dotnet_diagnostic.IDE0051.severity = warning
+
+# IDE0055: All formatting rules
+dotnet_diagnostic.IDE0055.severity = suggestion
+
+# IDE0059: Unnecessary assignment to a value
+dotnet_diagnostic.IDE0059.severity = warning
+
+# IDE0060: Remove unused parameter
+dotnet_code_quality_unused_parameters = non_public
+dotnet_diagnostic.IDE0060.severity = warning
+
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = warning
+
+# IDE0073: File header
+dotnet_diagnostic.IDE0073.severity = warning
+file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.
+
+# IDE1006: Required naming style
+dotnet_diagnostic.IDE1006.severity = warning
+
+# IDE0161: Convert to file-scoped namespace
+dotnet_diagnostic.IDE0161.severity = warning
+
+# IDE0200: Lambda expression can be removed
+dotnet_diagnostic.IDE0200.severity = warning
+
+# IDE2000: Disallow multiple blank lines
+dotnet_style_allow_multiple_blank_lines_experimental = false
+dotnet_diagnostic.IDE2000.severity = warning
+
+[{eng/tools/**.cs,**/{test,testassets,samples,Samples,perf,benchmarkapps,scripts,stress}/**.cs,src/Hosting/Server.IntegrationTesting/**.cs,src/Servers/IIS/IntegrationTesting.IIS/**.cs,src/Shared/Http2cat/**.cs,src/Testing/**.cs}]
+# CA1018: Mark attributes with AttributeUsageAttribute
+dotnet_diagnostic.CA1018.severity = suggestion
+# CA1507: Use nameof to express symbol names
+dotnet_diagnostic.CA1507.severity = suggestion
+# CA1510: Use ArgumentNullException throw helper
+dotnet_diagnostic.CA1510.severity = suggestion
+# CA1511: Use ArgumentException throw helper
+dotnet_diagnostic.CA1511.severity = suggestion
+# CA1512: Use ArgumentOutOfRangeException throw helper
+dotnet_diagnostic.CA1512.severity = suggestion
+# CA1513: Use ObjectDisposedException throw helper
+dotnet_diagnostic.CA1513.severity = suggestion
+# CA1802: Use literals where appropriate
+dotnet_diagnostic.CA1802.severity = suggestion
+# CA1805: Do not initialize unnecessarily
+dotnet_diagnostic.CA1805.severity = suggestion
+# CA1810: Do not initialize unnecessarily
+dotnet_diagnostic.CA1810.severity = suggestion
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = suggestion
+# CA1823: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = suggestion
+# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
+dotnet_diagnostic.CA1826.severity = suggestion
+# CA1827: Do not use Count() or LongCount() when Any() can be used
+dotnet_diagnostic.CA1827.severity = suggestion
+# CA1829: Use Length/Count property instead of Count() when available
+dotnet_diagnostic.CA1829.severity = suggestion
+# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1831.severity = suggestion
+# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1832.severity = suggestion
+# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1833.severity = suggestion
+# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
+dotnet_diagnostic.CA1834.severity = suggestion
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = suggestion
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = suggestion
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = suggestion
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = suggestion
+# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
+dotnet_diagnostic.CA1844.severity = suggestion
+# CA1845: Use span-based 'string.Concat'
+dotnet_diagnostic.CA1845.severity = suggestion
+# CA1846: Prefer AsSpan over Substring
+dotnet_diagnostic.CA1846.severity = suggestion
+# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
+dotnet_diagnostic.CA1847.severity = suggestion
+# CA1852: Seal internal types
+dotnet_diagnostic.CA1852.severity = suggestion
+# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
+dotnet_diagnostic.CA1854.severity = suggestion
+# CA1855: Prefer 'Clear' over 'Fill'
+dotnet_diagnostic.CA1855.severity = suggestion
+# CA1856: Incorrect usage of ConstantExpected attribute
+dotnet_diagnostic.CA1856.severity = suggestion
+# CA1857: A constant is expected for the parameter
+dotnet_diagnostic.CA1857.severity = suggestion
+# CA1858: Use 'StartsWith' instead of 'IndexOf'
+dotnet_diagnostic.CA1858.severity = suggestion
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = suggestion
+# CA2008: Do not create tasks without passing a TaskScheduler
+dotnet_diagnostic.CA2008.severity = suggestion
+# CA2012: Use ValueTask correctly
+dotnet_diagnostic.CA2012.severity = suggestion
+# CA2201: Do not raise reserved exception types
+dotnet_diagnostic.CA2201.severity = suggestion
+# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
+dotnet_diagnostic.CA2249.severity = suggestion
+# IDE0005: Remove unnecessary usings
+dotnet_diagnostic.IDE0005.severity = suggestion
+# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
+dotnet_diagnostic.IDE0020.severity = suggestion
+# IDE0029: Use coalesce expression (non-nullable types)
+dotnet_diagnostic.IDE0029.severity = suggestion
+# IDE0030: Use coalesce expression (nullable types)
+dotnet_diagnostic.IDE0030.severity = suggestion
+# IDE0031: Use null propagation
+dotnet_diagnostic.IDE0031.severity = suggestion
+# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
+dotnet_diagnostic.IDE0038.severity = suggestion
+# IDE0044: Make field readonly
+dotnet_diagnostic.IDE0044.severity = suggestion
+# IDE0051: Remove unused private members
+dotnet_diagnostic.IDE0051.severity = suggestion
+# IDE0059: Unnecessary assignment to a value
+dotnet_diagnostic.IDE0059.severity = suggestion
+# IDE0060: Remove unused parameters
+dotnet_diagnostic.IDE0060.severity = suggestion
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = suggestion
+# IDE0200: Lambda expression can be removed
+dotnet_diagnostic.IDE0200.severity = suggestion
+
+# CA2016: Forward the 'CancellationToken' parameter to methods that take one
+dotnet_diagnostic.CA2016.severity = suggestion
+
+# Defaults for content in the shared src/ and shared runtime dir
+
+[{**/Shared/runtime/**.{cs,vb},src/Shared/test/Shared.Tests/runtime/**.{cs,vb},**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = silent
+# IDE0011: Use braces
+dotnet_diagnostic.IDE0011.severity = silent
+# IDE0055: Fix formatting
+dotnet_diagnostic.IDE0055.severity = silent
+# IDE0060: Remove unused parameters
+dotnet_diagnostic.IDE0060.severity = silent
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = silent
+# IDE0161: Convert to file-scoped namespace
+dotnet_diagnostic.IDE0161.severity = silent
+
+[{**/Shared/**.cs,**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
+# IDE0005: Remove unused usings. Ignore for shared src files since imports for those depend on the projects in which they are included.
+dotnet_diagnostic.IDE0005.severity = silent
+
+[{*.razor.cs,src/Aspire.Dashboard/Components/**.cs}]
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = silent
diff --git a/dotnet/.gitattributes b/dotnet/.gitattributes
new file mode 100644
index 0000000000..671f86ba76
--- /dev/null
+++ b/dotnet/.gitattributes
@@ -0,0 +1,60 @@
+# Set default behavior to automatically normalize line endings.
+* text=auto
+
+# Collapse these files in PRs by default
+*.xlf linguist-generated=true
+*.lcl linguist-generated=true
+
+*.jpg binary
+*.png binary
+*.gif binary
+
+# Force bash scripts to always use lf line endings so that if a repo is accessed
+# in Unix via a file share from Windows, the scripts will work.
+*.in text eol=lf
+*.sh text eol=lf
+
+# Likewise, force cmd and batch scripts to always use crlf
+*.cmd text eol=crlf
+*.bat text eol=crlf
+
+*.cs text=auto diff=csharp
+*.vb text=auto
+*.resx text=auto
+*.c text=auto
+*.cpp text=auto
+*.cxx text=auto
+*.h text=auto
+*.hxx text=auto
+*.py text=auto
+*.rb text=auto
+*.java text=auto
+*.html text=auto
+*.htm text=auto
+*.css text=auto
+*.scss text=auto
+*.sass text=auto
+*.less text=auto
+*.js text=auto
+*.lisp text=auto
+*.clj text=auto
+*.sql text=auto
+*.php text=auto
+*.lua text=auto
+*.m text=auto
+*.asm text=auto
+*.erl text=auto
+*.fs text=auto
+*.fsx text=auto
+*.hs text=auto
+
+*.csproj text=auto
+*.vbproj text=auto
+*.fsproj text=auto
+*.dbproj text=auto
+*.sln text=auto eol=crlf
+
+# Set linguist language for .h files explicitly based on
+# https://github.com/github/linguist/issues/1626#issuecomment-401442069
+# this only affects the repo's language statistics
+*.h linguist-language=C
diff --git a/dotnet/.gitignore b/dotnet/.gitignore
new file mode 100644
index 0000000000..b53c09b668
--- /dev/null
+++ b/dotnet/.gitignore
@@ -0,0 +1,146 @@
+syntax: glob
+
+### VisualStudio ###
+
+# Tools directory
+.dotnet/
+.packages/
+.tools/
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Build results
+
+artifacts/
+artifacts_stage_1/
+[Dd]ebug/
+[Rr]elease/
+x64/ !eng/common/cross/x64/
+x86/ !eng/common/cross/x86/
+[Bb]in/
+[Oo]bj/
+msbuild.log
+msbuild.err
+msbuild.wrn
+*.binlog
+
+# Visual Studio 2015
+.vs/
+
+# Visual Studio 2015 Pre-CTP6
+*.sln.ide
+*.ide/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NuGet Packages
+*.nuget.props
+*.nuget.targets
+*.nupkg
+**/packages/*
+
+### Windows ###
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+### Linux ###
+
+*~
+
+# KDE directory preferences
+.directory
+
+### OSX ###
+
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# vim temporary files
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+*~
+
+# Visual Studio Code
+.vscode/
+
+# Private test configuration and binaries.
+config.ps1
+**/IISApplications
+
+
+# Node.js modules
+node_modules/
+
+# Python Compile Outputs
+
+*.pyc
+
+# IntelliJ
+.idea/
+
+# vscode python env files
+.env
+
+# Storage emulator storage files
+**/.azurite/*
+
+# Azure Developer CLI files
+/playground/**/.gitignore
+/playground/**/azure.yaml
+/playground/**/next-steps.md
diff --git a/dotnet/AGNext.sln b/dotnet/AGNext.sln
new file mode 100644
index 0000000000..f43a8caf45
--- /dev/null
+++ b/dotnet/AGNext.sln
@@ -0,0 +1,82 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "csharp\src", "{290F9824-BAD3-4703-B9B7-FE9C4BE3A1CF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AI.Agents", "csharp\src\Microsoft.AI.Agents\Microsoft.AI.Agents.csproj", "{B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AI.Agents.Dapr", "csharp\src\Microsoft.AI.Agents.Dapr\Microsoft.AI.Agents.Dapr.csproj", "{1972846E-4C21-4E40-B448-D78B73806BD9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AI.Agents.Orleans", "csharp\src\Microsoft.AI.Agents.Orleans\Microsoft.AI.Agents.Orleans.csproj", "{A4AE4656-4919-45E2-9680-C317FBCF7693}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples\csharp", "{943853E7-513D-45EA-870F-549CFC0AF8E8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gh-flow", "gh-flow", "{E0E93575-7187-4975-8D72-6F285CD01767}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "csharp\src", "{50809508-F830-4553-9C4E-C802E0A0F690}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AI.DevTeam", "examples\csharp\gh-flow\src\Microsoft.AI.DevTeam\Microsoft.AI.DevTeam.csproj", "{79981945-61F7-4E1A-8949-7808FD75471B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AI.DevTeam.Dapr", "examples\csharp\gh-flow\src\Microsoft.AI.DevTeam.Dapr\Microsoft.AI.DevTeam.Dapr.csproj", "{A7677950-18F1-42FF-8018-870395417465}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "marketing", "marketing", "{1FF691E4-E27D-4A7E-861C-4D6291B6EE35}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "csharp\src", "{4225F3BA-A39D-4680-945E-F2869E98AEA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marketing", "examples\csharp\marketing\src\backend\Marketing.csproj", "{62F276F3-9184-4908-A7FB-065B4E491BE2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "seed-memory", "examples\csharp\gh-flow\src\seed-memory\seed-memory.csproj", "{EF5DF177-F4F2-49D5-9E1C-2E37869238D8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1972846E-4C21-4E40-B448-D78B73806BD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1972846E-4C21-4E40-B448-D78B73806BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1972846E-4C21-4E40-B448-D78B73806BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1972846E-4C21-4E40-B448-D78B73806BD9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4AE4656-4919-45E2-9680-C317FBCF7693}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4AE4656-4919-45E2-9680-C317FBCF7693}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4AE4656-4919-45E2-9680-C317FBCF7693}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4AE4656-4919-45E2-9680-C317FBCF7693}.Release|Any CPU.Build.0 = Release|Any CPU
+ {79981945-61F7-4E1A-8949-7808FD75471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {79981945-61F7-4E1A-8949-7808FD75471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {79981945-61F7-4E1A-8949-7808FD75471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {79981945-61F7-4E1A-8949-7808FD75471B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7677950-18F1-42FF-8018-870395417465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7677950-18F1-42FF-8018-870395417465}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7677950-18F1-42FF-8018-870395417465}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7677950-18F1-42FF-8018-870395417465}.Release|Any CPU.Build.0 = Release|Any CPU
+ {62F276F3-9184-4908-A7FB-065B4E491BE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {62F276F3-9184-4908-A7FB-065B4E491BE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {62F276F3-9184-4908-A7FB-065B4E491BE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {62F276F3-9184-4908-A7FB-065B4E491BE2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF5DF177-F4F2-49D5-9E1C-2E37869238D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF5DF177-F4F2-49D5-9E1C-2E37869238D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF5DF177-F4F2-49D5-9E1C-2E37869238D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF5DF177-F4F2-49D5-9E1C-2E37869238D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {B0BF1CD6-34E3-4ED4-9B2A-9B8781E9BE20} = {290F9824-BAD3-4703-B9B7-FE9C4BE3A1CF}
+ {1972846E-4C21-4E40-B448-D78B73806BD9} = {290F9824-BAD3-4703-B9B7-FE9C4BE3A1CF}
+ {A4AE4656-4919-45E2-9680-C317FBCF7693} = {290F9824-BAD3-4703-B9B7-FE9C4BE3A1CF}
+ {E0E93575-7187-4975-8D72-6F285CD01767} = {943853E7-513D-45EA-870F-549CFC0AF8E8}
+ {50809508-F830-4553-9C4E-C802E0A0F690} = {E0E93575-7187-4975-8D72-6F285CD01767}
+ {79981945-61F7-4E1A-8949-7808FD75471B} = {50809508-F830-4553-9C4E-C802E0A0F690}
+ {A7677950-18F1-42FF-8018-870395417465} = {50809508-F830-4553-9C4E-C802E0A0F690}
+ {1FF691E4-E27D-4A7E-861C-4D6291B6EE35} = {943853E7-513D-45EA-870F-549CFC0AF8E8}
+ {4225F3BA-A39D-4680-945E-F2869E98AEA2} = {1FF691E4-E27D-4A7E-861C-4D6291B6EE35}
+ {62F276F3-9184-4908-A7FB-065B4E491BE2} = {4225F3BA-A39D-4680-945E-F2869E98AEA2}
+ {EF5DF177-F4F2-49D5-9E1C-2E37869238D8} = {943853E7-513D-45EA-870F-549CFC0AF8E8}
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/samples/WorkflowsApp/.env_example b/dotnet/samples/WorkflowsApp/.env_example
new file mode 100644
index 0000000000..94c2700521
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/.env_example
@@ -0,0 +1,8 @@
+
+# Replace with your own values
+export SERVICETYPE=AzureOpenAI
+export SERVICEID=gpt-4
+export DEPLOYMENTORMODELID=gpt-4
+export EMBEDDINGDEPLOYMENTORMODELID=text-embedding-ada-002
+export ENDPOINT="Error - you mus update your OpenAI Endpoint"
+export APIKEY="Error - you must update your OpenAPI or Azure API key"
diff --git a/dotnet/samples/WorkflowsApp/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs b/dotnet/samples/WorkflowsApp/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs
new file mode 100644
index 0000000000..4c8256994c
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs
@@ -0,0 +1,201 @@
+using System.Reflection;
+using Azure;
+using Azure.AI.OpenAI;
+using Elsa.Extensions;
+using Elsa.Workflows;
+using Elsa.Workflows.Contracts;
+using Elsa.Workflows.Models;
+using Elsa.Workflows.UIHints;
+using Microsoft.Extensions.Http.Resilience;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SKDevTeam;
+
+namespace Elsa.SemanticKernel;
+
+//
+// Loads the Semantic Kernel skills and then generates activites for each skill
+//
+public class SemanticKernelActivityProvider : IActivityProvider
+{
+ private readonly IActivityFactory _activityFactory;
+ private readonly IActivityDescriber _activityDescriber;
+
+ public SemanticKernelActivityProvider(IActivityFactory activityFactory, IActivityDescriber activityDescriber)
+ {
+ _activityFactory = activityFactory;
+ _activityDescriber = activityDescriber;
+ }
+ public async ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default)
+ {
+ // get the kernel
+ var kernel = KernelBuilder();
+
+ // get a list of skills in the assembly
+ var skills = LoadSkillsFromAssemblyAsync("skills", kernel);
+ var functionsAvailable = kernel.Plugins.GetFunctionsMetadata();
+
+ // create activity descriptors for each skilland function
+ var activities = new List();
+ foreach (var function in functionsAvailable)
+ {
+ Console.WriteLine($"Creating Activities for Plugin: {function.PluginName}");
+ activities.Add(CreateActivityDescriptorFromSkillAndFunction(function, cancellationToken));
+ }
+
+ return activities;
+ }
+
+ ///
+ /// Creates an activity descriptor from a skill and function.
+ ///
+ /// The semantic kernel function
+ /// An optional cancellation token.
+ /// An activity descriptor.
+ private ActivityDescriptor CreateActivityDescriptorFromSkillAndFunction(KernelFunctionMetadata function, CancellationToken cancellationToken = default)
+ {
+ // Create a fully qualified type name for the activity
+ var thisNamespace = GetType().Namespace;
+ var fullTypeName = $"{thisNamespace}.{function.PluginName}.{function.Name}";
+ Console.WriteLine($"Creating Activity: {fullTypeName}");
+
+ // create inputs from the function parameters - the SemanticKernelSkill activity will be the base for each activity
+ var inputs = new List();
+ foreach (var p in function.Parameters) { inputs.Add(CreateInputDescriptorFromSKParameter(p)); }
+ inputs.Add(CreateInputDescriptor(typeof(string), "SkillName", function.PluginName, "The name of the skill to use (generated, do not change)"));
+ inputs.Add(CreateInputDescriptor(typeof(string), "FunctionName", function.Name, "The name of the function to use (generated, do not change)"));
+ inputs.Add(CreateInputDescriptor(typeof(int), "MaxRetries", KernelSettings.DefaultMaxRetries, "Max Retries to contact AI Service"));
+
+ return new ActivityDescriptor
+ {
+ Kind = ActivityKind.Task,
+ Category = "Semantic Kernel",
+ Description = function.Description,
+ Name = function.Name,
+ TypeName = fullTypeName,
+ Namespace = $"{thisNamespace}.{function.PluginName}",
+ DisplayName = $"{function.PluginName}.{function.Name}",
+ Inputs = inputs,
+ Outputs = new[] {new OutputDescriptor()},
+ Constructor = context =>
+ {
+ // The constructor is called when an activity instance of this type is requested.
+
+ // Create the activity instance.
+ var activityInstance = _activityFactory.Create(context);
+
+ // Customize the activity type name.
+ activityInstance.Type = fullTypeName;
+
+ // Configure the activity's URL and method properties.
+ activityInstance.SkillName = new Input(function.PluginName);
+ activityInstance.FunctionName = new Input(function.Name);
+
+ return activityInstance;
+ }
+ };
+
+ }
+ ///
+ /// Creates an input descriptor for a single line string
+ ///
+ /// The name of the input field
+ /// The description of the input field
+ private InputDescriptor CreateInputDescriptor(Type inputType, string name, Object defaultValue, string description)
+ {
+ var inputDescriptor = new InputDescriptor
+ {
+ Description = description,
+ DefaultValue = defaultValue,
+ Type = inputType,
+ Name = name,
+ DisplayName = name,
+ IsSynthetic = true, // This is a synthetic property, i.e. it is not part of the activity's .NET type.
+ IsWrapped = true, // This property is wrapped within an Input object.
+ UIHint = InputUIHints.SingleLine,
+ ValueGetter = activity => activity.SyntheticProperties.GetValueOrDefault(name),
+ ValueSetter = (activity, value) => activity.SyntheticProperties[name] = value!,
+ };
+ return inputDescriptor;
+ }
+
+ ///
+ /// Creates an input descriptor from an sk funciton parameter definition.
+ ///
+ /// The function parameter.
+ /// An input descriptor.
+ private InputDescriptor CreateInputDescriptorFromSKParameter(KernelParameterMetadata parameter)
+ {
+ var inputDescriptor = new InputDescriptor
+ {
+ Description = string.IsNullOrEmpty(parameter.Description) ? parameter.Name : parameter.Description,
+ DefaultValue = parameter.DefaultValue == null ? string.Empty : parameter.DefaultValue,
+ Type = typeof(string),
+ Name = parameter.Name,
+ DisplayName = parameter.Name,
+ IsSynthetic = true, // This is a synthetic property, i.e. it is not part of the activity's .NET type.
+ IsWrapped = true, // This property is wrapped within an Input object.
+ UIHint = InputUIHints.MultiLine,
+ ValueGetter = activity => activity.SyntheticProperties.GetValueOrDefault(parameter.Name),
+ ValueSetter = (activity, value) => activity.SyntheticProperties[parameter.Name] = value!,
+
+ };
+ return inputDescriptor;
+ }
+
+ ///
+ /// Gets a list of the skills in the assembly
+ ///
+ private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, Kernel kernel)
+ {
+ var skills = new List();
+ var assembly = Assembly.Load(assemblyName);
+ Type[] skillTypes = assembly.GetTypes().ToArray();
+ foreach (Type skillType in skillTypes)
+ {
+ if (skillType.Namespace.Equals("Microsoft.AI.DevTeam"))
+ {
+ skills.Add(skillType.Name);
+ var functions = skillType.GetFields();
+ foreach (var function in functions)
+ {
+ string field = function.FieldType.ToString();
+ if (field.Equals("Microsoft.AI.DevTeam.SemanticFunctionConfig"))
+ {
+ var promptTemplate = SemanticFunctionConfig.ForSkillAndFunction(skillType.Name, function.Name);
+ var skfunc = kernel.CreateFunctionFromPrompt(
+ promptTemplate.PromptTemplate, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 });
+
+ Console.WriteLine($"SKActivityProvider Added SK function: {skfunc.Metadata.PluginName}.{skfunc.Name}");
+ }
+ }
+ }
+ }
+ return skills;
+ }
+
+ ///
+ /// Gets a semantic kernel instance
+ ///
+ /// Microsoft.SemanticKernel.IKernel
+ private Kernel KernelBuilder()
+ {
+ var kernelSettings = KernelSettings.LoadSettings();
+
+ var clientOptions = new OpenAIClientOptions();
+ clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5);
+ var openAIClient = new OpenAIClient(new Uri(kernelSettings.Endpoint), new AzureKeyCredential(kernelSettings.ApiKey), clientOptions);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddLogging( c=> c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug));
+ builder.Services.AddAzureOpenAIChatCompletion(kernelSettings.DeploymentOrModelId, openAIClient);
+ builder.Services.ConfigureHttpClientDefaults(c=>
+ {
+ c.AddStandardResilienceHandler().Configure( o=> {
+ o.Retry.MaxRetryAttempts = 5;
+ o.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
+ });
+ });
+ return builder.Build();
+ }
+}
+
diff --git a/dotnet/samples/WorkflowsApp/Activities/SemanticKernel.cs b/dotnet/samples/WorkflowsApp/Activities/SemanticKernel.cs
new file mode 100644
index 0000000000..85ad789eb0
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Activities/SemanticKernel.cs
@@ -0,0 +1,195 @@
+using Elsa.Extensions;
+using JetBrains.Annotations;
+using System.Text;
+using System.Reflection;
+using Elsa.Workflows;
+using Elsa.Workflows.Attributes;
+using Elsa.Workflows.UIHints;
+using Elsa.Workflows.Models;
+using Microsoft.SKDevTeam;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel;
+using Azure.AI.OpenAI;
+using Azure;
+using Microsoft.Extensions.Http.Resilience;
+
+
+namespace Elsa.SemanticKernel;
+
+///
+/// Invoke a Semantic Kernel skill.
+///
+[Activity("Elsa", "Semantic Kernel", "Invoke a Semantic Kernel skill. ", DisplayName = "Generic Semantic Kernel Skill", Kind = ActivityKind.Task)]
+[PublicAPI]
+public class SemanticKernelSkill : CodeActivity
+{
+ [Input(
+ Description = "System Prompt",
+ UIHint = InputUIHints.MultiLine,
+ DefaultValue = PromptDefaults.SystemPrompt)]
+ public Input SysPrompt { get; set; } = default!;
+
+ [Input(
+ Description = "User Input Prompt",
+ UIHint = InputUIHints.MultiLine,
+ DefaultValue = PromptDefaults.UserPrompt)]
+ public Input Prompt { get; set; }
+
+ [Input(
+ Description = "Max retries",
+ UIHint = InputUIHints.SingleLine,
+ DefaultValue = KernelSettings.DefaultMaxRetries)]
+ public Input MaxRetries { get; set; }
+
+ [Input(
+ Description = "The skill to invoke from the semantic kernel",
+ UIHint = InputUIHints.SingleLine,
+ DefaultValue = "Chat")]
+ public Input SkillName { get; set; }
+
+ [Input(
+ Description = "The function to invoke from the skill",
+ UIHint = InputUIHints.SingleLine,
+ DefaultValue = "ChatCompletion")]
+ public Input FunctionName { get; set; }
+
+ /* [Input(
+ Description = "Mockup - don't actually call the AI, just output the prompts",
+ UIHint = InputUIHints.Checkbox,
+ DefaultValue = false)]
+ public Input Mockup { get; set; } */
+
+ ///
+ protected override async ValueTask ExecuteAsync(ActivityExecutionContext workflowContext)
+ {
+ var test = SkillName.Get(workflowContext);
+ var skillName = SkillName.Get(workflowContext);
+ var functionName = FunctionName.Get(workflowContext);
+ var systemPrompt = SysPrompt.Get(workflowContext);
+ var maxRetries = MaxRetries.Get(workflowContext);
+ var prompt = Prompt.Get(workflowContext);
+ //var mockup = Mockup.Get(workflowContext);
+ var mockup = false;
+
+ string info = ($"#################\nSkill: {skillName}\nFunction: {functionName}\nPrompt: {prompt}\n#################\n\n");
+
+ if (mockup)
+ {
+ workflowContext.SetResult(info);
+ }
+ else
+ {
+ // get the kernel
+ var kernel = KernelBuilder();
+
+ // load the skill
+ var promptTemplate = SemanticFunctionConfig.ForSkillAndFunction(skillName, functionName);
+
+ var function = kernel.CreateFunctionFromPrompt(promptTemplate.PromptTemplate, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 });
+
+ // set the context (our prompt)
+ var arguments = new KernelArguments{
+ ["input"] = prompt
+ };
+
+ var answer = await kernel.InvokeAsync(function, arguments);
+ workflowContext.SetResult(answer);
+ }
+ }
+
+ ///
+ /// Load the skills into the kernel
+ ///
+ private string ListSkillsInKernel(Kernel kernel)
+ {
+
+ var theSkills = LoadSkillsFromAssemblyAsync("skills", kernel);
+ var functionsAvailable = kernel.Plugins.GetFunctionsMetadata();
+
+ var list = new StringBuilder();
+ foreach (var function in functionsAvailable)
+ {
+ Console.WriteLine($"Skill: {function.PluginName}");
+
+ // Function description
+ if (function.Description != null)
+ {
+ list.AppendLine($"// {function.Description}");
+ }
+ else
+ {
+ Console.WriteLine("{0}.{1} is missing a description", function.PluginName, function.Name);
+ list.AppendLine($"// Function {function.PluginName}.{function.Name}.");
+ }
+
+ // Function name
+ list.AppendLine($"{function.PluginName}.{function.Name}");
+
+ // Function parameters
+ foreach (var p in function.Parameters)
+ {
+ var description = string.IsNullOrEmpty(p.Description) ? p.Name : p.Description;
+ var defaultValueString = p.DefaultValue == null ? string.Empty : $" (default value: {p.DefaultValue})";
+ list.AppendLine($"Parameter \"{p.Name}\": {description} {defaultValueString}");
+ }
+ }
+
+ Console.WriteLine($"List of all skills ----- {list.ToString()}");
+ return list.ToString();
+ }
+
+ ///
+ /// Gets a semantic kernel instance
+ ///
+ /// Microsoft.SemanticKernel.IKernel
+ private Kernel KernelBuilder()
+ {
+ var kernelSettings = KernelSettings.LoadSettings();
+
+ var clientOptions = new OpenAIClientOptions();
+ clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5);
+ var openAIClient = new OpenAIClient(new Uri(kernelSettings.Endpoint), new AzureKeyCredential(kernelSettings.ApiKey), clientOptions);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddLogging( c=> c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug));
+ builder.Services.AddAzureOpenAIChatCompletion(kernelSettings.DeploymentOrModelId, openAIClient);
+ builder.Services.ConfigureHttpClientDefaults(c=>
+ {
+ c.AddStandardResilienceHandler().Configure( o=> {
+ o.Retry.MaxRetryAttempts = 5;
+ o.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
+ });
+ });
+ return builder.Build();
+ }
+
+ ///
+ /// Gets a list of the skills in the assembly
+ ///
+ private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, Kernel kernel)
+ {
+ var skills = new List();
+ var assembly = Assembly.Load(assemblyName);
+ Type[] skillTypes = assembly.GetTypes().ToArray();
+ foreach (Type skillType in skillTypes)
+ {
+ if (skillType.Namespace.Equals("Microsoft.SKDevTeam"))
+ {
+ skills.Add(skillType.Name);
+ var functions = skillType.GetFields();
+ foreach (var function in functions)
+ {
+ string field = function.FieldType.ToString();
+ if (field.Equals("Microsoft.SKDevTeam.SemanticFunctionConfig"))
+ {
+ var prompt = SemanticFunctionConfig.ForSkillAndFunction(skillType.Name, function.Name);
+ var skfunc = kernel.CreateFunctionFromPrompt(
+ prompt.PromptTemplate, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 });
+
+ Console.WriteLine($"SK Added function: {skfunc.Metadata.PluginName}.{skfunc.Metadata.Name}");
+ }
+ }
+ }
+ }
+ return skills;
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Config/KernelSettings.cs b/dotnet/samples/WorkflowsApp/Config/KernelSettings.cs
new file mode 100644
index 0000000000..7e549c9aff
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Config/KernelSettings.cs
@@ -0,0 +1,95 @@
+using System.Text.Json.Serialization;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using System.IO;
+using System;
+
+internal class KernelSettings
+{
+ public const string DefaultConfigFile = "config/appsettings.json";
+ public const string OpenAI = "OPENAI";
+ public const string AzureOpenAI = "AZUREOPENAI";
+ public const int DefaultMaxRetries = 9;
+
+ [JsonPropertyName("serviceType")]
+ public string ServiceType { get; set; } = string.Empty;
+
+ [JsonPropertyName("serviceId")]
+ public string ServiceId { get; set; } = string.Empty;
+
+ [JsonPropertyName("deploymentOrModelId")]
+ public string DeploymentOrModelId { get; set; } = string.Empty;
+ [JsonPropertyName("embeddingDeploymentOrModelId")]
+ public string EmbeddingDeploymentOrModelId { get; set; } = string.Empty;
+
+ [JsonPropertyName("endpoint")]
+ public string Endpoint { get; set; } = string.Empty;
+
+ [JsonPropertyName("apiKey")]
+ public string ApiKey { get; set; } = string.Empty;
+
+ [JsonPropertyName("orgId")]
+ public string OrgId { get; set; } = string.Empty;
+
+ [JsonPropertyName("logLevel")]
+ public LogLevel? LogLevel { get; set; }
+
+ ///
+ /// Load the kernel settings from settings.json if the file exists and if not attempt to use user secrets.
+ ///
+ internal static KernelSettings LoadSettings()
+ {
+ try
+ {
+ if (File.Exists(DefaultConfigFile))
+ {
+ return FromFile(DefaultConfigFile);
+ }
+
+ Console.WriteLine($"Semantic kernel settings '{DefaultConfigFile}' not found, attempting to load configuration from user secrets.");
+
+ return FromUserSecrets();
+ }
+ catch (InvalidDataException ide)
+ {
+ Console.Error.WriteLine(
+ "Unable to load semantic kernel settings, please provide configuration settings using instructions in the README.\n" +
+ "Please refer to: https://github.com/microsoft/semantic-kernel-starters/blob/main/sk-csharp-hello-world/README.md#configuring-the-starter"
+ );
+ throw new InvalidOperationException(ide.Message);
+ }
+ }
+
+ ///
+ /// Load the kernel settings from the specified configuration file if it exists.
+ ///
+ internal static KernelSettings FromFile(string configFile = DefaultConfigFile)
+ {
+ if (!File.Exists(configFile))
+ {
+ throw new FileNotFoundException($"Configuration not found: {configFile}");
+ }
+
+ var configuration = new ConfigurationBuilder()
+ .SetBasePath(System.IO.Directory.GetCurrentDirectory())
+ .AddJsonFile(configFile, optional: true, reloadOnChange: true)
+ .Build();
+
+ return configuration.Get()
+ ?? throw new InvalidDataException($"Invalid semantic kernel settings in '{configFile}', please provide configuration settings using instructions in the README.");
+ }
+
+ ///
+ /// Load the kernel settings from user secrets.
+ ///
+ internal static KernelSettings FromUserSecrets()
+ {
+ var configuration = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+ return configuration.Get()
+ ?? throw new InvalidDataException("Invalid semantic kernel settings in user secrets, please provide configuration settings using instructions in the README.");
+ }
+}
diff --git a/dotnet/samples/WorkflowsApp/Config/PromptDefaults.cs b/dotnet/samples/WorkflowsApp/Config/PromptDefaults.cs
new file mode 100644
index 0000000000..6f5a16c75c
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Config/PromptDefaults.cs
@@ -0,0 +1,7 @@
+internal static class PromptDefaults {
+ public const string SystemPrompt = @"You are fulfilling roles on a software development team.
+ Provide a response to the following prompt, do not provide any additional output.";
+
+ public const string UserPrompt = @"Let's build a ToDoList Application!";
+
+ }
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/NuGet.Config b/dotnet/samples/WorkflowsApp/NuGet.Config
new file mode 100644
index 0000000000..a89a1e8b5b
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/NuGet.Config
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Pages/Index.cshtml b/dotnet/samples/WorkflowsApp/Pages/Index.cshtml
new file mode 100644
index 0000000000..b889d560a9
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Pages/Index.cshtml
@@ -0,0 +1,22 @@
+@page "/"
+@{
+ var serverUrl = $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}";
+ var apiUrl = serverUrl + "elsa/api";
+}
+
+
+
+
+
+ Elsa Workflows 3.0
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Pages/_ViewImports.cshtml b/dotnet/samples/WorkflowsApp/Pages/_ViewImports.cshtml
new file mode 100644
index 0000000000..251d639084
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Pages/_ViewImports.cshtml
@@ -0,0 +1,2 @@
+@namespace WorkflowsApp.Pages
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Program.cs b/dotnet/samples/WorkflowsApp/Program.cs
new file mode 100644
index 0000000000..463bfda623
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Program.cs
@@ -0,0 +1,54 @@
+using Elsa.EntityFrameworkCore.Extensions;
+using Elsa.EntityFrameworkCore.Modules.Management;
+using Elsa.EntityFrameworkCore.Modules.Runtime;
+using Elsa.Extensions;
+using Elsa.SemanticKernel;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddElsa(elsa =>
+{
+ // Configure management feature to use EF Core.
+ elsa.UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite()));
+
+ elsa.UseWorkflowRuntime(runtime =>runtime.UseEntityFrameworkCore());
+
+ // Expose API endpoints.
+ elsa.UseWorkflowsApi();
+
+ // Add services for HTTP activities and workflow middleware.
+ elsa.UseHttp();
+
+ // Configure identity so that we can create a default admin user.
+ elsa.UseIdentity(identity =>
+ {
+ identity.UseAdminUserProvider();
+ identity.TokenOptions = options => options.SigningKey = "secret-token-signing-key";
+ });
+
+ // Use default authentication (JWT + API Key).
+ elsa.UseDefaultAuthentication(auth => auth.UseAdminApiKey());
+
+ // Add Semantic Kernel skill.
+ elsa.AddActivity();
+
+});
+
+// Add dynamic Activity Provider for SK skills.
+builder.Services.AddActivityProvider();
+
+// Add Razor pages.
+builder.Services.AddRazorPages();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+app.UseHttpsRedirection();
+app.UseStaticFiles();
+app.UseAuthentication();
+app.UseAuthorization();
+app.UseWorkflowsApi();
+app.UseWorkflows();
+app.MapRazorPages();
+app.Run();
diff --git a/dotnet/samples/WorkflowsApp/Properties/launchSettings.json b/dotnet/samples/WorkflowsApp/Properties/launchSettings.json
new file mode 100644
index 0000000000..b5db5f1dde
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Properties/launchSettings.json
@@ -0,0 +1,37 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:10492",
+ "sslPort": 44312
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5181",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7077;http://localhost:5181",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/dotnet/samples/WorkflowsApp/README.md b/dotnet/samples/WorkflowsApp/README.md
new file mode 100644
index 0000000000..d24e358521
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/README.md
@@ -0,0 +1,64 @@
+# SemanticKernel Activity Provider for Elsa Workflows 3.x
+
+The project supports running [Microsoft Semantic Kernel](https://github.com/microsoft/semantic-kernel) Skills as workflows using [Elsa Workflows](https://v3.elsaworkflows.io). You can build the workflows as .NET code or in the visual designer.
+To run the designer:
+
+```bash
+> cd WorkflowsApp
+> cp .env_example .env
+# Edit the .env file to choose your AI model, add your API Endpoint, and secrets.
+> . ./.env
+> dotnet build
+> dotnet run
+# Open browser to the URI in the console output
+```
+
+By Default you can use "admin" and "password" to login. Please review [Workflow Security](https://v3.elsaworkflows.io/docs/installation/aspnet-apps-workflow-server) for into on securing the app, using API tokens, and more.
+
+To [invoke](https://v3.elsaworkflows.io/docs/guides/invoking-workflows) a workflow, first it must be "Published". If your workflow has a trigger activity, you can use that. When your workflow is ready, click the "Publish" button. You can also execute the workflow using the API. Then, find the Workflow Definition ID. From a command line, you can use "curl":
+
+```bash
+> curl --location 'https://localhost:5001/elsa/api/workflow-definitions/{workflow_definition_id}/execute' \
+--header 'Content-Type: application/json' \
+--header 'Authorization: ApiKey {api_key}' \
+--data '{
+}'
+```
+
+Once you have the app runing locally, you can login (admin/password - see the [Elsa Workflows](https://v3.elsaworkflows.io) for info about securing). Then you can click "new workflow" to begin building your workflow with semantic kernel skills.
+
+1. Drag workflow Activity blocks into the designer, and examine the settings.
+2. Connect the Activities to specify an order of operations.
+3. You can use Workfflow Variables to pass state between activities.
+ 1. Create a Workflow Variable, "MyVariable"
+ 2. Click on the Activity that you want to use to populate the variable.
+ 3. In the Settings box for the Activity, Click "Output"
+ 4. Set the "Output" to the variable chosen.
+ 5. Click the Activity that will use the variable. Click on "Settings".
+ 6. Find the text box representing the variable that you want to populate, in this case usually "input".
+ 7. Click the "..." widget above the text box, and select "javascript"
+ 8. Set the value of the text box to
+
+ ```javascript
+ `${getMyVariable()}`
+ ```
+
+ 9. Run the workflow.
+
+## Run via codespaces
+
+The easiest way to run the project is in Codespaces. Codespaces will start a qdrant instance for you.
+
+1. Create a new codespace from the *code* button on the main branch.
+2. Once the code space setup is finished, from the terminal:
+
+```bash
+> cd cli
+cli> cp ../WorkflowsApp/.env_example .
+# Edit the .env file to choose your AI model, add your API Endpoint, and secrets.
+cli> bash .env
+cli> dotnet build
+cli> dotnet run --file util/ToDoListSamplePrompt.txt do it
+```
+
+You will find the output in the *output/* directory.
diff --git a/dotnet/samples/WorkflowsApp/Skills/DevLeadPrompts.cs b/dotnet/samples/WorkflowsApp/Skills/DevLeadPrompts.cs
new file mode 100644
index 0000000000..4072a8a3f8
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Skills/DevLeadPrompts.cs
@@ -0,0 +1,47 @@
+namespace Microsoft.SKDevTeam;
+public static class DevLead {
+ public static SemanticFunctionConfig Plan = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Dev Lead for an application team, building the application described below.
+ Please break down the steps and modules required to develop the complete application, describe each step in detail.
+ Make prescriptive architecture, language, and frameowrk choices, do not provide a range of choices.
+ For each step or module then break down the steps or subtasks required to complete that step or module.
+ For each subtask write an LLM prompt that would be used to tell a model to write the coee that will accomplish that subtask. If the subtask involves taking action/running commands tell the model to write the script that will run those commands.
+ In each LLM prompt restrict the model from outputting other text that is not in the form of code or code comments.
+ Please output a JSON array data structure, in the precise schema shown below, with a list of steps and a description of each step, and the steps or subtasks that each requires, and the LLM prompts for each subtask.
+ Example:
+ {
+ "steps": [
+ {
+ "step": "1",
+ "description": "This is the first step",
+ "subtasks": [
+ {
+ "subtask": "Subtask 1",
+ "description": "This is the first subtask",
+ "prompt": "Write the code to do the first subtask"
+ },
+ {
+ "subtask": "Subtask 2",
+ "description": "This is the second subtask",
+ "prompt": "Write the code to do the second subtask"
+ }
+ ]
+ }
+ ]
+ }
+ Do not output any other text.
+ Input: {{$input}}
+ {{$wafContext}}
+ """,
+ Name = nameof(Plan),
+ SkillName = nameof(DevLead),
+ Description = "From a simple description of an application output a development plan for building the application.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Skills/Developer.cs b/dotnet/samples/WorkflowsApp/Skills/Developer.cs
new file mode 100644
index 0000000000..ed4ed5781e
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Skills/Developer.cs
@@ -0,0 +1,46 @@
+namespace Microsoft.SKDevTeam;
+public static class Developer {
+ public static SemanticFunctionConfig Implement = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Developer for an application.
+ Please output the code required to accomplish the task assigned to you below and wrap it in a bash script that creates the files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$wafContext}}
+ """,
+ Name = nameof(Implement),
+ SkillName = nameof(Developer),
+ Description = "From a description of a coding task out put the code or scripts necessary to complete the task.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+
+ public static SemanticFunctionConfig Improve = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Developer for an application. Your job is to imrove the code that you are given in the input below.
+ Please output a new version of code that fixes any problems with this version.
+ If there is an error message in the input you should fix that error in the code.
+ Wrap the code output up in a bash script that creates the necessary files by overwriting any previous files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$wafContext}}
+ """,
+ Name = nameof(Improve),
+ SkillName = nameof(Developer),
+ Description = "From a description of a coding task out put the code or scripts necessary to complete the task.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Skills/PMPrompts.cs b/dotnet/samples/WorkflowsApp/Skills/PMPrompts.cs
new file mode 100644
index 0000000000..c8fb118830
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Skills/PMPrompts.cs
@@ -0,0 +1,42 @@
+namespace Microsoft.SKDevTeam;
+public static class PM
+{
+ public static SemanticFunctionConfig BootstrapProject = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ Please write a bash script with the commands that would be required to generate applications as described in the following input.
+ You may add comments to the script and the generated output but do not add any other text except the bash script.
+ You may include commands to build the applications but do not run them.
+ Do not include any git commands.
+ Input: {{$input}}
+ {{$wafContext}}
+ """,
+ Name = nameof(BootstrapProject),
+ SkillName = nameof(PM),
+ Description = "Bootstrap a new project",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+ public static SemanticFunctionConfig Readme = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a program manager on a software development team. You are working on an app described below.
+ Based on the input below, and any dialog or other context, please output a raw README.MD markdown file documenting the main features of the app and the architecture or code organization.
+ Do not describe how to create the application.
+ Write the README as if it were documenting the features and architecture of the application. You may include instructions for how to run the application.
+ Input: {{$input}}
+ {{$wafContext}}
+ """,
+ Name = nameof(Readme),
+ SkillName = nameof(PM),
+ Description = "From a simple description output a README.md file for a GitHub repository.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/Skills/SemanticFunctionConfig.cs b/dotnet/samples/WorkflowsApp/Skills/SemanticFunctionConfig.cs
new file mode 100644
index 0000000000..1569962e2a
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/Skills/SemanticFunctionConfig.cs
@@ -0,0 +1,23 @@
+namespace Microsoft.SKDevTeam;
+
+public class SemanticFunctionConfig
+{
+ public string PromptTemplate { get; set; }
+ public string Name { get; set; }
+ public string SkillName { get; set; }
+ public string Description { get; set; }
+ public int MaxTokens { get; set; }
+ public double Temperature { get; set; }
+ public double TopP { get; set; }
+ public double PPenalty { get; set; }
+ public double FPenalty { get; set; }
+ public static SemanticFunctionConfig ForSkillAndFunction(string skillName, string functionName) =>
+ (skillName, functionName) switch
+ {
+ (nameof(PM), nameof(PM.Readme)) => PM.Readme,
+ (nameof(DevLead), nameof(DevLead.Plan)) => DevLead.Plan,
+ (nameof(Developer), nameof(Developer.Implement)) => Developer.Implement,
+ (nameof(Developer), nameof(Developer.Improve)) => Developer.Improve,
+ _ => throw new ArgumentException($"Unable to find {skillName}.{functionName}")
+ };
+}
\ No newline at end of file
diff --git a/dotnet/samples/WorkflowsApp/WorkflowsApp.csproj b/dotnet/samples/WorkflowsApp/WorkflowsApp.csproj
new file mode 100644
index 0000000000..d0f32f3fe2
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/WorkflowsApp.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/WorkflowsApp/appsettings.Development.json b/dotnet/samples/WorkflowsApp/appsettings.Development.json
new file mode 100644
index 0000000000..0c208ae918
--- /dev/null
+++ b/dotnet/samples/WorkflowsApp/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/dotnet/samples/gh-flow/README.md b/dotnet/samples/gh-flow/README.md
new file mode 100644
index 0000000000..ff0aed310a
--- /dev/null
+++ b/dotnet/samples/gh-flow/README.md
@@ -0,0 +1,69 @@
+# GitHub Dev Team with AI Agents
+
+Build a Dev Team using event driven agents. This project is an experiment and is not intended to be used in production.
+
+## Background
+
+From a natural language specification, set out to integrate a team of AI agents into your team’s dev process, either for discrete tasks on an existing repo (unit tests, pipeline expansions, PRs for specific intents), developing a new feature, or even building an application from scratch. Starting from an existing repo and a broad statement of intent, work with multiple AI agents, each of which has a different emphasis - from architecture, to task breakdown, to plans for individual tasks, to code output, code review, efficiency, documentation, build, writing tests, setting up pipelines, deployment, integration tests, and then validation.
+The system will present a view that facilitates chain-of-thought coordination across multiple trees of reasoning with the dev team agents.
+
+
+
+## Get it running
+
+Check [the getting started guide](./docs/github-flow-getting-started.md).
+
+## Demo
+
+https://github.com/microsoft/azure-openai-dev-skills-orchestrator/assets/10728102/cafb1546-69ab-4c27-aaf5-1968313d637f
+
+## Solution overview
+
+![General overview](./docs/images/overview.png)
+
+## How it works
+
+* User begins with creating an issue and then stateing what they want to accomplish, natural language, as simple or as detailed as needed.
+* Product manager agent will respond with a Readme, which can be iterated upon.
+ * User approves the readme or gives feedback via issue comments.
+ * Once the readme is approved, the user closes the issue and the Readme is commited to a PR.
+* Developer lead agent responds with a decomposed plan for development, which also can be iterated upon.
+ * User approves the plan or gives feedback via issue comments.
+ * Once the readme is approved, the user closes the issue and the plan is used to break down the task to different developer agents.
+* Developer agents respond with code, which can be iterated upon.
+ * User approves the code or gives feedback via issue comments.
+ * Once the code is approved, the user closes the issue and the code is commited to a PR.
+
+```mermaid
+graph TD;
+ NEA([NewAsk event]) -->|Hubber| NEA1[Creation of PM issue, DevLead issue, and new branch];
+
+ RR([ReadmeRequested event]) -->|ProductManager| PM1[Generation of new README];
+ NEA1 --> RR;
+ PM1 --> RG([ReadmeGenerated event]);
+ RG -->|Hubber| RC[Post the readme as a new comment on the issue];
+ RC --> RCC([ReadmeChainClosed event]);
+ RCC -->|ProductManager| RCR([ReadmeCreated event]);
+ RCR --> |AzureGenie| RES[Store Readme in blob storage];
+ RES --> RES2([ReadmeStored event]);
+ RES2 --> |Hubber| REC[Readme commited to branch and create new PR];
+
+ DPR([DevPlanRequested event]) -->|DeveloperLead| DPG[Generation of new development plan];
+ NEA1 --> DPR;
+ DPG --> DPGE([DevPlanGenerated event]);
+ DPGE -->|Hubber| DPGEC[Posting the plan as a new comment on the issue];
+ DPGEC --> DPCC([DevPlanChainClosed event]);
+ DPCC -->|DeveloperLead| DPCE([DevPlanCreated event]);
+ DPCE --> |Hubber| DPC[Creates a Dev issue for each subtask];
+
+ DPC([CodeGenerationRequested event]) -->|Developer| CG[Generation of new code];
+ CG --> CGE([CodeGenerated event]);
+ CGE -->|Hubber| CGC[Posting the code as a new comment on the issue];
+ CGC --> CCCE([CodeChainClosed event]);
+ CCCE -->|Developer| CCE([CodeCreated event]);
+ CCE --> |AzureGenie| CS[Store code in blob storage and schedule a run in the sandbox];
+ CS --> SRC([SandboxRunCreated event]);
+ SRC --> |Sandbox| SRM[Check every minute if the run finished];
+ SRM --> SRF([SandboxRunFinished event]);
+ SRF --> |Hubber| SRCC[Code files commited to branch];
+```
diff --git a/dotnet/samples/gh-flow/azure.yaml b/dotnet/samples/gh-flow/azure.yaml
new file mode 100644
index 0000000000..8553ba154f
--- /dev/null
+++ b/dotnet/samples/gh-flow/azure.yaml
@@ -0,0 +1,10 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
+
+name: ai-dev-team
+services:
+ gh-flow:
+ project: "src/Microsoft.AI.DevTeam"
+ language: csharp
+ host: containerapp
+ docker:
+ context: ../../../../
diff --git a/dotnet/samples/gh-flow/components/pubsub.yaml b/dotnet/samples/gh-flow/components/pubsub.yaml
new file mode 100644
index 0000000000..5aec174af9
--- /dev/null
+++ b/dotnet/samples/gh-flow/components/pubsub.yaml
@@ -0,0 +1,12 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: agents-pubsub
+spec:
+ type: pubsub.redis
+ version: v1
+ metadata:
+ - name: redisHost
+ value: localhost:6379
+ - name: redisPassword
+ value: ""
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/components/statestore.yaml b/dotnet/samples/gh-flow/components/statestore.yaml
new file mode 100644
index 0000000000..9693888f26
--- /dev/null
+++ b/dotnet/samples/gh-flow/components/statestore.yaml
@@ -0,0 +1,14 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: agents-statestore
+spec:
+ type: state.redis
+ version: v1
+ metadata:
+ - name: redisHost
+ value: localhost:6379
+ - name: redisPassword
+ value: ""
+ - name: actorStateStore
+ value: "true"
diff --git a/dotnet/samples/gh-flow/docs/github-flow-getting-started.md b/dotnet/samples/gh-flow/docs/github-flow-getting-started.md
new file mode 100644
index 0000000000..ebfb168256
--- /dev/null
+++ b/dotnet/samples/gh-flow/docs/github-flow-getting-started.md
@@ -0,0 +1,122 @@
+## Prerequisites
+
+- Access to gpt3.5-turbo or preferably gpt4 - [Get access here](https://learn.microsoft.com/en-us/azure/ai-services/openai/overview#how-do-i-get-access-to-azure-openai)
+- [Setup a Github app](#how-do-i-setup-the-github-app)
+- [Install the Github app](https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app)
+- [Provision the azure resources](#how-do-I-deploy-the-azure-bits)
+- [Create labels for the dev team skills](#which-labels-should-i-create)
+
+### How do I setup the Github app?
+
+- [Register a Github app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app), with the options listed below:
+ - Give your App a name and add a description
+ - Homepage URL: Can be anything (Example: repository URL)
+ - Add a dummy value for the webhook url, we'll come back to this setting
+ - Enter a webhook secret, which you'll need later on when filling in the `WebhookSecret` property in the `appsettings.json` file
+ - Setup the following permissions
+ - Repository
+ - Contents - read and write
+ - Issues - read and write
+ - Metadata - read only
+ - Pull requests - read and write
+ - Subscribe to the following events:
+ - Issues
+ - Issue comment
+ - Allow this app to be installed by any user or organization
+
+- After the app is created, generate a private key, we'll use it later for authentication to Github from the app
+
+### Which labels should I create?
+
+In order for us to know which skill and persona we need to talk with, we are using Labels in Github Issues.
+
+The default bunch of skills and personnas are as follow:
+- PM.Readme
+- Do.It
+- DevLead.Plan
+- Developer.Implement
+
+Add them to your repository (They are not there by default).
+
+Once you start adding your own skills, just remember to add the corresponding label to your repository.
+
+## How do I run this locally?
+
+Codespaces are preset for this repo. For codespaces there is a 'free' tier for individual accounts. See: https://github.com/pricing
+Start by creating a codespace:
+https://docs.github.com/en/codespaces/developing-in-a-codespace/creating-a-codespace-for-a-repository
+
+![Alt text](./images/new-codespace.png)
+
+In this sample's folder there are two files called appsettings.azure.template.json and appsettings.local.template.json. If you run this demo locally, use the local template and if you want to run it within Azure use the Azure template. Rename the selected file to appsettings.json and fill out the config values within the file.
+
+### GitHubOptions
+
+For the GitHubOptions section, you'll need to fill in the following values:
+- **AppKey (PrivateKey)**: this is a key generated while creating a GitHub App. If you haven't saved it during creation, you'll need to generate a new one. Go to the settings of your GitHub app, scroll down to "Private keys" and click on "Generate a new private key". It will download a .pem file that contains your App Key. Then copy and paste all the **-----BEGIN RSA PRIVATE KEY---- your key -----END RSA PRIVATE KEY-----** content here, in one line.
+- **AppId**: This can be found on the same page where you created your app. Go to the settings of your GitHub app and you can see the App ID at the top of the page.
+- **InstallationId**: Access to your GitHub app installation and take note of the number (long type) at the end of the URL (which should be in the following format: https://github.com/settings/installations/installation-id).
+- **WebhookSecret**: This is a value that you set when you create your app. In the app settings, go to the "Webhooks" section. Here you can find the "Secret" field where you can set your Webhook Secret.
+
+### AzureOptions
+
+The following fields are required and need to be filled in:
+- **SubscriptionId**: The id of the subscription you want to work on.
+- **Location**
+- **ContainerInstancesResourceGroup**: The name of the resource group where container instances will be deployed.
+- **FilesAccountName**: Azure Storage Account name.
+- **FilesShareName**: The name of the File Share.
+- **FilesAccountKey**: The File Account key.
+- **SandboxImage**
+
+In the Explorer tab in VS Code, find the Solution explorer, right click on the `gh-flow` project and click Debug -> Start new instance
+
+![Alt text](./images/solution-explorer.png)
+
+We'll need to expose the running application to the GH App webhooks, for example using [DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview), but any tool like ngrok can also work.
+The following commands will create a persistent tunnel, so we need to only do this once:
+```bash
+TUNNEL_NAME=_name_your_tunnel_here_
+devtunnel user login
+devtunnel create -a $TUNNEL_NAME
+devtunnel port create -p 5244 $TUNNEL_NAME
+```
+and once we have the tunnel created we can just start forwarding with the following command:
+
+```bash
+devtunnel host $TUNNEL_NAME
+```
+
+Copy the local address (it will look something like https://your_tunnel_name.euw.devtunnels.ms) and append `/api/github/webhooks` at the end. Using this value, update the Github App's webhook URL and you are ready to go!
+
+Before you go and have the best of times, there is one last thing left to do [load the WAF into the vector DB](#load-the-waf-into-qdrant)
+
+Also, since this project is relying on Orleans for the Agents implementation, there is a [dashboard](https://github.com/OrleansContrib/OrleansDashboard) available at https://yout_tunnel_name.euw.devtunnels.ms/dashboard, with useful metrics and stats related to the running Agents.
+
+## How do I deploy the azure bits?
+
+This sample is setup to use [azd](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) to work with the Azure bits. `azd` is installed in the codespace.
+
+Let's start by logging in to Azure using
+```bash
+azd auth login
+```
+
+After we've logged in, we need to create a new environment provision the azure bits.
+
+```bash
+ENVIRONMENT=_name_of_your_env
+azd env new $ENVIRONMENT
+azd provision -e $ENVIRONMENT
+```
+After the provisioning is done, you can inspect the outputs with the following command
+
+```bash
+azd env get-values -e dev
+```
+As the last step, we also need to [load the WAF into the vector DB](#load-the-waf-into-qdrant)
+
+### Load the WAF into Qdrant.
+
+If you are running the app locally, we have [Qdrant](https://qdrant.tech/) setup in the Codespace and if you are running in Azure, Qdrant is deployed to ACA.
+The loader is a project in the `samples` folder, called `seed-memory`. We need to fill in the `appsettings.json` (after renaming `appsettings.template.json` in `appsettings.json`) file in the `config` folder with the OpenAI details and the Qdrant endpoint, then just run the loader with `dotnet run` and you are ready to go.
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/docs/images/github-sk-dev-team.png b/dotnet/samples/gh-flow/docs/images/github-sk-dev-team.png
new file mode 100644
index 0000000000..c70e4d87b5
Binary files /dev/null and b/dotnet/samples/gh-flow/docs/images/github-sk-dev-team.png differ
diff --git a/dotnet/samples/gh-flow/docs/images/new-codespace.png b/dotnet/samples/gh-flow/docs/images/new-codespace.png
new file mode 100644
index 0000000000..928756830f
Binary files /dev/null and b/dotnet/samples/gh-flow/docs/images/new-codespace.png differ
diff --git a/dotnet/samples/gh-flow/docs/images/overview.png b/dotnet/samples/gh-flow/docs/images/overview.png
new file mode 100644
index 0000000000..cdb0c0a5c1
Binary files /dev/null and b/dotnet/samples/gh-flow/docs/images/overview.png differ
diff --git a/dotnet/samples/gh-flow/docs/images/solution-explorer.png b/dotnet/samples/gh-flow/docs/images/solution-explorer.png
new file mode 100644
index 0000000000..48165f8ddb
Binary files /dev/null and b/dotnet/samples/gh-flow/docs/images/solution-explorer.png differ
diff --git a/dotnet/samples/gh-flow/infra/abbreviations.json b/dotnet/samples/gh-flow/infra/abbreviations.json
new file mode 100644
index 0000000000..fba689e2f5
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/abbreviations.json
@@ -0,0 +1,14 @@
+{
+ "appManagedEnvironments": "cae-",
+ "containerRegistryRegistries": "cr",
+ "insightsComponents": "appi-",
+ "operationalInsightsWorkspaces": "log-",
+ "portalDashboards": "dash-",
+ "resourcesResourceGroups": "rg-",
+ "storageStorageAccounts": "st",
+ "webServerFarms": "plan-",
+ "webSitesFunctions": "func-",
+ "appContainerApps": "ca-",
+ "managedIdentityUserAssignedIdentities": "id-",
+ "documentDBDatabaseAccounts":"cosmos-"
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/infra/app/db.bicep b/dotnet/samples/gh-flow/infra/app/db.bicep
new file mode 100644
index 0000000000..077bb72121
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/app/db.bicep
@@ -0,0 +1,46 @@
+param accountName string
+param location string = resourceGroup().location
+param tags object = {}
+
+param containers array = [
+ {
+ name: 'reminders'
+ id: 'reminders'
+ partitionKey: '/id'
+ }
+ {
+ name: 'persistence'
+ id: 'persistence'
+ partitionKey: '/id'
+ }
+ {
+ name: 'clustering'
+ id: 'clustering'
+ partitionKey: '/id'
+ }
+]
+
+param databaseName string = ''
+param principalIds array = []
+
+// Because databaseName is optional in main.bicep, we make sure the database name is set here.
+var defaultDatabaseName = 'Todo'
+var actualDatabaseName = !empty(databaseName) ? databaseName : defaultDatabaseName
+
+module cosmos '../core/database/cosmos/sql/cosmos-sql-db.bicep' = {
+ name: 'cosmos-sql'
+ params: {
+ accountName: accountName
+ location: location
+ tags: tags
+ containers: containers
+ databaseName: actualDatabaseName
+ principalIds: principalIds
+ }
+}
+
+output accountName string = cosmos.outputs.accountName
+output connectionStringKey string = cosmos.outputs.connectionStringKey
+output databaseName string = cosmos.outputs.databaseName
+output endpoint string = cosmos.outputs.endpoint
+output roleDefinitionId string = cosmos.outputs.roleDefinitionId
diff --git a/dotnet/samples/gh-flow/infra/app/gh-flow.bicep b/dotnet/samples/gh-flow/infra/app/gh-flow.bicep
new file mode 100644
index 0000000000..0a78aea504
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/app/gh-flow.bicep
@@ -0,0 +1,170 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param applicationInsightsName string
+param identityName string
+param serviceName string = 'gh-flow'
+param sandboxImage string = 'mcr.microsoft.com/dotnet/sdk:7.0'
+
+
+param containerAppsEnvironmentName string
+param containerRegistryName string
+param storageAccountName string
+param cosmosAccountName string
+
+@secure()
+param githubAppKey string
+param githubAppId string
+param githubAppInstallationId string
+param rgName string
+param aciShare string
+param openAIServiceType string
+param openAIServiceId string
+param openAIDeploymentId string
+param openAIEmbeddingId string
+param openAIEndpoint string
+@secure()
+param openAIKey string
+param qdrantEndpoint string
+
+resource ghFlowIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
+ name: identityName
+ location: location
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
+ name: applicationInsightsName
+}
+
+resource storage 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
+ name: storageAccountName
+}
+
+resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
+ name: cosmosAccountName
+}
+
+var contributorRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
+var wehbookSecret = uniqueString(resourceGroup().id)
+
+resource rgContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ name: guid(subscription().id, resourceGroup().id, contributorRole)
+ properties: {
+ roleDefinitionId: contributorRole
+ principalType: 'ServicePrincipal'
+ principalId: app.outputs.identityPrincipalId
+ }
+}
+
+module app '../core/host/container-app.bicep' = {
+ name: '${serviceName}-ghflow'
+ params: {
+ name: name
+ location: location
+ tags: union(tags, { 'azd-service-name': serviceName })
+ identityType: 'UserAssigned'
+ identityName: ghFlowIdentity.name
+ containerAppsEnvironmentName: containerAppsEnvironmentName
+ containerRegistryName: containerRegistryName
+ containerCpuCoreCount: '2.0'
+ containerMemory: '4.0Gi'
+ env: [
+ {
+ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
+ value: applicationInsights.properties.ConnectionString
+ }
+ {
+ name: 'SANDBOX_IMAGE'
+ value: sandboxImage
+ }
+ {
+ name: 'GithubOptions__AppKey'
+ value: githubAppKey
+ }
+ {
+ name: 'GithubOptions__AppId'
+ value: githubAppId
+ }
+ {
+ name: 'GithubOptions__InstallationId'
+ value: githubAppInstallationId
+ }
+ {
+ name: 'GithubOptions__WebhookSecret'
+ value: wehbookSecret
+ }
+ {
+ name: 'AzureOptions__SubscriptionId'
+ value: subscription().subscriptionId
+ }
+ {
+ name: 'AzureOptions__Location'
+ value: location
+ }
+ {
+ name: 'AZURE_CLIENT_ID'
+ value: ghFlowIdentity.properties.clientId
+ }
+ {
+ name: 'AzureOptions__ContainerInstancesResourceGroup'
+ value: rgName
+ }
+ {
+ name: 'AzureOptions__FilesAccountKey'
+ value: storage.listKeys().keys[0].value
+ }
+ {
+ name: 'AzureOptions__FilesShareName'
+ value: aciShare
+ }
+ {
+ name: 'AzureOptions__FilesAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'AzureOptions__CosmosConnectionString'
+ value: cosmos.listConnectionStrings().connectionStrings[0].connectionString
+ }
+ {
+ name: 'OpenAIOptions__ServiceType'
+ value: openAIServiceType
+ }
+ {
+ name: 'OpenAIOptions__ServiceId'
+ value: openAIServiceId
+ }
+ {
+ name: 'OpenAIOptions__DeploymentOrModelId'
+ value: openAIDeploymentId
+ }
+ {
+ name: 'OpenAIOptions__EmbeddingDeploymentOrModelId'
+ value: openAIEmbeddingId
+ }
+ {
+ name: 'OpenAIOptions__Endpoint'
+ value: openAIEndpoint
+ }
+ {
+ name: 'OpenAIOptions__ApiKey'
+ value: openAIKey
+ }
+ {
+ name: 'QdrantOptions__Endpoint'
+ value: qdrantEndpoint
+ }
+ {
+ name: 'QdrantOptions__VectorSize'
+ value: '1536'
+ }
+ ]
+ targetPort: 5274
+ }
+}
+
+
+output SERVICE_TRANSLATE_API_IDENTITY_PRINCIPAL_ID string = app.outputs.identityPrincipalId
+output SERVICE_TRANSLATE_API_NAME string = app.outputs.name
+output SERVICE_TRANSLATE_API_URI string = app.outputs.uri
+output WEBHOOK_SECRET string = wehbookSecret
diff --git a/dotnet/samples/gh-flow/infra/core/database/cosmos/cosmos-account.bicep b/dotnet/samples/gh-flow/infra/core/database/cosmos/cosmos-account.bicep
new file mode 100644
index 0000000000..4c129b0f79
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/cosmos/cosmos-account.bicep
@@ -0,0 +1,37 @@
+metadata description = 'Creates an Azure Cosmos DB account.'
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
+
+@allowed([ 'GlobalDocumentDB', 'MongoDB', 'Parse' ])
+param kind string
+
+resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = {
+ name: name
+ kind: kind
+ location: location
+ tags: tags
+ properties: {
+ consistencyPolicy: { defaultConsistencyLevel: 'Session' }
+ locations: [
+ {
+ locationName: location
+ failoverPriority: 0
+ isZoneRedundant: false
+ }
+ ]
+ databaseAccountOfferType: 'Standard'
+ enableAutomaticFailover: false
+ enableMultipleWriteLocations: false
+ apiProperties: (kind == 'MongoDB') ? { serverVersion: '4.0' } : {}
+ capabilities: [ { name: 'EnableServerless' } ]
+ }
+}
+
+
+output connectionStringKey string = connectionStringKey
+output endpoint string = cosmos.properties.documentEndpoint
+output id string = cosmos.id
+output name string = cosmos.name
diff --git a/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-account.bicep b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-account.bicep
new file mode 100644
index 0000000000..fee0f679e4
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-account.bicep
@@ -0,0 +1,19 @@
+metadata description = 'Creates an Azure Cosmos DB for NoSQL account.'
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+module cosmos '../../cosmos/cosmos-account.bicep' = {
+ name: 'cosmos-account'
+ params: {
+ name: name
+ location: location
+ tags: tags
+ kind: 'GlobalDocumentDB'
+ }
+}
+
+output connectionStringKey string = cosmos.outputs.connectionStringKey
+output endpoint string = cosmos.outputs.endpoint
+output id string = cosmos.outputs.id
+output name string = cosmos.outputs.name
diff --git a/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-db.bicep b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-db.bicep
new file mode 100644
index 0000000000..3c79064ec3
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-db.bicep
@@ -0,0 +1,72 @@
+metadata description = 'Creates an Azure Cosmos DB for NoSQL account with a database.'
+param accountName string
+param databaseName string
+param location string = resourceGroup().location
+param tags object = {}
+
+param containers array = []
+param principalIds array = []
+
+module cosmos 'cosmos-sql-account.bicep' = {
+ name: 'cosmos-sql-account'
+ params: {
+ name: accountName
+ location: location
+ tags: tags
+ }
+}
+
+resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = {
+ name: '${accountName}/${databaseName}'
+ properties: {
+ resource: { id: databaseName }
+ }
+
+ resource list 'containers' = [for container in containers: {
+ name: container.name
+ properties: {
+ resource: {
+ id: container.id
+ partitionKey: { paths: [ container.partitionKey ] }
+ }
+ options: {}
+ }
+ }]
+
+ dependsOn: [
+ cosmos
+ ]
+}
+
+module roleDefinition 'cosmos-sql-role-def.bicep' = {
+ name: 'cosmos-sql-role-definition'
+ params: {
+ accountName: accountName
+ }
+ dependsOn: [
+ cosmos
+ database
+ ]
+}
+
+// We need batchSize(1) here because sql role assignments have to be done sequentially
+@batchSize(1)
+module userRole 'cosmos-sql-role-assign.bicep' = [for principalId in principalIds: if (!empty(principalId)) {
+ name: 'cosmos-sql-user-role-${uniqueString(principalId)}'
+ params: {
+ accountName: accountName
+ roleDefinitionId: roleDefinition.outputs.id
+ principalId: principalId
+ }
+ dependsOn: [
+ cosmos
+ database
+ ]
+}]
+
+output accountId string = cosmos.outputs.id
+output accountName string = cosmos.outputs.name
+output connectionStringKey string = cosmos.outputs.connectionStringKey
+output databaseName string = databaseName
+output endpoint string = cosmos.outputs.endpoint
+output roleDefinitionId string = roleDefinition.outputs.id
diff --git a/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep
new file mode 100644
index 0000000000..3949efef0a
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep
@@ -0,0 +1,19 @@
+metadata description = 'Creates a SQL role assignment under an Azure Cosmos DB account.'
+param accountName string
+
+param roleDefinitionId string
+param principalId string = ''
+
+resource role 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2022-05-15' = {
+ parent: cosmos
+ name: guid(roleDefinitionId, principalId, cosmos.id)
+ properties: {
+ principalId: principalId
+ roleDefinitionId: roleDefinitionId
+ scope: cosmos.id
+ }
+}
+
+resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
+ name: accountName
+}
diff --git a/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep
new file mode 100644
index 0000000000..778d6dc47b
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep
@@ -0,0 +1,30 @@
+metadata description = 'Creates a SQL role definition under an Azure Cosmos DB account.'
+param accountName string
+
+resource roleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2022-08-15' = {
+ parent: cosmos
+ name: guid(cosmos.id, accountName, 'sql-role')
+ properties: {
+ assignableScopes: [
+ cosmos.id
+ ]
+ permissions: [
+ {
+ dataActions: [
+ 'Microsoft.DocumentDB/databaseAccounts/readMetadata'
+ 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*'
+ 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*'
+ ]
+ notDataActions: []
+ }
+ ]
+ roleName: 'Reader Writer'
+ type: 'CustomRole'
+ }
+}
+
+resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
+ name: accountName
+}
+
+output id string = roleDefinition.id
diff --git a/dotnet/samples/gh-flow/infra/core/database/postgresql/flexibleserver.bicep b/dotnet/samples/gh-flow/infra/core/database/postgresql/flexibleserver.bicep
new file mode 100644
index 0000000000..effda63de4
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/postgresql/flexibleserver.bicep
@@ -0,0 +1,64 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param sku object
+param storage object
+param administratorLogin string
+@secure()
+param administratorLoginPassword string
+param databaseNames array = []
+param allowAzureIPsFirewall bool = false
+param allowAllIPsFirewall bool = false
+param allowedSingleIPs array = []
+
+// PostgreSQL version
+param version string
+
+// Latest official version 2022-12-01 does not have Bicep types available
+resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = {
+ location: location
+ tags: tags
+ name: name
+ sku: sku
+ properties: {
+ version: version
+ administratorLogin: administratorLogin
+ administratorLoginPassword: administratorLoginPassword
+ storage: storage
+ highAvailability: {
+ mode: 'Disabled'
+ }
+ }
+
+ resource database 'databases' = [for name in databaseNames: {
+ name: name
+ }]
+
+ resource firewall_all 'firewallRules' = if (allowAllIPsFirewall) {
+ name: 'allow-all-IPs'
+ properties: {
+ startIpAddress: '0.0.0.0'
+ endIpAddress: '255.255.255.255'
+ }
+ }
+
+ resource firewall_azure 'firewallRules' = if (allowAzureIPsFirewall) {
+ name: 'allow-all-azure-internal-IPs'
+ properties: {
+ startIpAddress: '0.0.0.0'
+ endIpAddress: '0.0.0.0'
+ }
+ }
+
+ resource firewall_single 'firewallRules' = [for ip in allowedSingleIPs: {
+ name: 'allow-single-${replace(ip, '.', '')}'
+ properties: {
+ startIpAddress: ip
+ endIpAddress: ip
+ }
+ }]
+
+}
+
+output POSTGRES_DOMAIN_NAME string = postgresServer.properties.fullyQualifiedDomainName
diff --git a/dotnet/samples/gh-flow/infra/core/database/qdrant/qdrant-aca.bicep b/dotnet/samples/gh-flow/infra/core/database/qdrant/qdrant-aca.bicep
new file mode 100644
index 0000000000..a5f1573ebf
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/database/qdrant/qdrant-aca.bicep
@@ -0,0 +1,72 @@
+param containerAppsEnvironmentName string
+param storageName string
+param shareName string
+param location string
+var storageAccountKey = listKeys(resourceId('Microsoft.Storage/storageAccounts', storageName), '2021-09-01').keys[0].value
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-11-01-preview' existing = {
+ name: containerAppsEnvironmentName
+}
+
+var mountName = 'qdrantstoragemount'
+var volumeName = 'qdrantstoragevol'
+resource qdrantstorage 'Microsoft.App/managedEnvironments/storages@2022-11-01-preview' = {
+ name: '${containerAppsEnvironmentName}/${mountName}'
+ properties: {
+ azureFile: {
+ accountName: storageName
+ shareName: shareName
+ accountKey: storageAccountKey
+ accessMode: 'ReadWrite'
+ }
+ }
+}
+
+resource qdrant 'Microsoft.App/containerApps@2022-11-01-preview' = {
+ name: 'qdrant'
+ location: location
+ dependsOn:[
+ qdrantstorage
+ ]
+ properties: {
+ environmentId: containerAppsEnvironment.id
+ configuration: {
+ ingress: {
+ external: true
+ targetPort: 6333
+ }
+ }
+ template: {
+ containers: [
+ {
+ name: 'qdrant'
+ image: 'qdrant/qdrant'
+ resources: {
+ cpu: 1
+ memory: '2Gi'
+ }
+ volumeMounts: [
+ {
+ volumeName: volumeName
+ mountPath: '/qdrant/storage'
+ }
+ ]
+ }
+ ]
+ scale: {
+ minReplicas: 1
+ maxReplicas: 1
+ }
+ volumes: [
+ {
+ name: volumeName
+ storageName: mountName
+ storageType: 'AzureFile'
+ }
+ ]
+ }
+ }
+}
+
+output fqdn string = qdrant.properties.latestRevisionFqdn
+
diff --git a/dotnet/samples/gh-flow/infra/core/host/appservice-appsettings.bicep b/dotnet/samples/gh-flow/infra/core/host/appservice-appsettings.bicep
new file mode 100644
index 0000000000..574342a814
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/appservice-appsettings.bicep
@@ -0,0 +1,16 @@
+@description('The name of the app service resource within the current resource group scope')
+param name string
+
+@description('The app settings to be applied to the app service')
+@secure()
+param appSettings object
+
+resource appService 'Microsoft.Web/sites@2022-03-01' existing = {
+ name: name
+}
+
+resource settings 'Microsoft.Web/sites/config@2022-03-01' = {
+ name: 'appsettings'
+ parent: appService
+ properties: appSettings
+}
diff --git a/dotnet/samples/gh-flow/infra/core/host/appservice.bicep b/dotnet/samples/gh-flow/infra/core/host/appservice.bicep
new file mode 100644
index 0000000000..9ecb2b0827
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/appservice.bicep
@@ -0,0 +1,119 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+// Reference Properties
+param applicationInsightsName string = ''
+param appServicePlanId string
+param keyVaultName string = ''
+param managedIdentity bool
+
+// Runtime Properties
+@allowed([
+ 'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom'
+])
+param runtimeName string
+param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}'
+param runtimeVersion string
+
+// Microsoft.Web/sites Properties
+param kind string = 'app,linux'
+
+// Microsoft.Web/sites/config
+param allowedOrigins array = []
+param alwaysOn bool = true
+param appCommandLine string = ''
+@secure()
+param appSettings object = {}
+param clientAffinityEnabled bool = false
+param enableOryxBuild bool = contains(kind, 'linux')
+param functionAppScaleLimit int = -1
+param linuxFxVersion string = runtimeNameAndVersion
+param minimumElasticInstanceCount int = -1
+param numberOfWorkers int = -1
+param scmDoBuildDuringDeployment bool = false
+param use32BitWorkerProcess bool = false
+param ftpsState string = 'FtpsOnly'
+param healthCheckPath string = ''
+
+resource appService 'Microsoft.Web/sites@2022-03-01' = {
+ name: name
+ location: location
+ tags: tags
+ kind: kind
+ properties: {
+ serverFarmId: appServicePlanId
+ siteConfig: {
+
+ alwaysOn: alwaysOn
+ ftpsState: ftpsState
+ minTlsVersion: '1.2'
+ appCommandLine: appCommandLine
+ numberOfWorkers: numberOfWorkers != -1 ? numberOfWorkers : null
+ minimumElasticInstanceCount: minimumElasticInstanceCount != -1 ? minimumElasticInstanceCount : null
+ use32BitWorkerProcess: use32BitWorkerProcess
+ functionAppScaleLimit: functionAppScaleLimit != -1 ? functionAppScaleLimit : null
+ healthCheckPath: healthCheckPath
+ cors: {
+ allowedOrigins: union([ 'https://portal.azure.com', 'https://ms.portal.azure.com' ], allowedOrigins)
+ }
+ }
+ clientAffinityEnabled: clientAffinityEnabled
+ httpsOnly: true
+ }
+
+ identity: { type: managedIdentity ? 'SystemAssigned' : 'None' }
+
+ resource configLogs 'config' = {
+ name: 'logs'
+ properties: {
+ applicationLogs: { fileSystem: { level: 'Verbose' } }
+ detailedErrorMessages: { enabled: true }
+ failedRequestsTracing: { enabled: true }
+ httpLogs: { fileSystem: { enabled: true, retentionInDays: 1, retentionInMb: 35 } }
+ }
+ }
+
+ resource basicPublishingCredentialsPoliciesFtp 'basicPublishingCredentialsPolicies' = {
+ name: 'ftp'
+ location: location
+ properties: {
+ allow: false
+ }
+ }
+
+ resource basicPublishingCredentialsPoliciesScm 'basicPublishingCredentialsPolicies' = {
+ name: 'scm'
+ location: location
+ properties: {
+ allow: false
+ }
+ }
+}
+
+module config 'appservice-appsettings.bicep' = if (!empty(appSettings)) {
+ name: '${name}-appSettings'
+ params: {
+ name: appService.name
+ appSettings: union(appSettings,
+ {
+ SCM_DO_BUILD_DURING_DEPLOYMENT: string(scmDoBuildDuringDeployment)
+ ENABLE_ORYX_BUILD: string(enableOryxBuild)
+ },
+ runtimeName == 'python' && appCommandLine == '' ? { PYTHON_ENABLE_GUNICORN_MULTIWORKERS: 'true'} : {},
+ !empty(applicationInsightsName) ? { APPLICATIONINSIGHTS_CONNECTION_STRING: applicationInsights.properties.ConnectionString } : {},
+ !empty(keyVaultName) ? { AZURE_KEY_VAULT_ENDPOINT: keyVault.properties.vaultUri } : {})
+ }
+}
+
+resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = if (!(empty(keyVaultName))) {
+ name: keyVaultName
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightsName)) {
+ name: applicationInsightsName
+}
+
+output identityPrincipalId string = managedIdentity ? appService.identity.principalId : ''
+output name string = appService.name
+output uri string = 'https://${appService.properties.defaultHostName}'
diff --git a/dotnet/samples/gh-flow/infra/core/host/appserviceplan.bicep b/dotnet/samples/gh-flow/infra/core/host/appserviceplan.bicep
new file mode 100644
index 0000000000..c444f40651
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/appserviceplan.bicep
@@ -0,0 +1,21 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param kind string = ''
+param reserved bool = true
+param sku object
+
+resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
+ name: name
+ location: location
+ tags: tags
+ sku: sku
+ kind: kind
+ properties: {
+ reserved: reserved
+ }
+}
+
+output id string = appServicePlan.id
+output name string = appServicePlan.name
diff --git a/dotnet/samples/gh-flow/infra/core/host/container-app-upsert.bicep b/dotnet/samples/gh-flow/infra/core/host/container-app-upsert.bicep
new file mode 100644
index 0000000000..d9be752b09
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/container-app-upsert.bicep
@@ -0,0 +1,104 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@description('The environment name for the container apps')
+param containerAppsEnvironmentName string
+
+@description('The number of CPU cores allocated to a single container instance, e.g., 0.5')
+param containerCpuCoreCount string = '0.5'
+
+@description('The maximum number of replicas to run. Must be at least 1.')
+@minValue(1)
+param containerMaxReplicas int = 10
+
+@description('The amount of memory allocated to a single container instance, e.g., 1Gi')
+param containerMemory string = '1.0Gi'
+
+@description('The minimum number of replicas to run. Must be at least 1.')
+@minValue(1)
+param containerMinReplicas int = 1
+
+@description('The name of the container')
+param containerName string = 'main'
+
+@description('The name of the container registry')
+param containerRegistryName string = ''
+
+@allowed([ 'http', 'grpc' ])
+@description('The protocol used by Dapr to connect to the app, e.g., HTTP or gRPC')
+param daprAppProtocol string = 'http'
+
+@description('Enable or disable Dapr for the container app')
+param daprEnabled bool = false
+
+@description('The Dapr app ID')
+param daprAppId string = containerName
+
+@description('Specifies if the resource already exists')
+param exists bool = false
+
+@description('Specifies if Ingress is enabled for the container app')
+param ingressEnabled bool = true
+
+@description('The type of identity for the resource')
+@allowed([ 'None', 'SystemAssigned', 'UserAssigned' ])
+param identityType string = 'None'
+
+@description('The name of the user-assigned identity')
+param identityName string = ''
+
+@description('The name of the container image')
+param imageName string = ''
+
+@description('The secrets required for the container')
+param secrets array = []
+
+@description('The environment variables for the container')
+param env array = []
+
+@description('Specifies if the resource ingress is exposed externally')
+param external bool = true
+
+@description('The service binds associated with the container')
+param serviceBinds array = []
+
+@description('The target port for the container')
+param targetPort int = 80
+
+resource existingApp 'Microsoft.App/containerApps@2023-04-01-preview' existing = if (exists) {
+ name: name
+}
+
+module app 'container-app.bicep' = {
+ name: '${deployment().name}-update'
+ params: {
+ name: name
+ location: location
+ tags: tags
+ identityType: identityType
+ identityName: identityName
+ ingressEnabled: ingressEnabled
+ containerName: containerName
+ containerAppsEnvironmentName: containerAppsEnvironmentName
+ containerRegistryName: containerRegistryName
+ containerCpuCoreCount: containerCpuCoreCount
+ containerMemory: containerMemory
+ containerMinReplicas: containerMinReplicas
+ containerMaxReplicas: containerMaxReplicas
+ daprEnabled: daprEnabled
+ daprAppId: daprAppId
+ daprAppProtocol: daprAppProtocol
+ secrets: secrets
+ external: external
+ env: env
+ imageName: !empty(imageName) ? imageName : exists ? existingApp.properties.template.containers[0].image : ''
+ targetPort: targetPort
+ serviceBinds: serviceBinds
+ }
+}
+
+output defaultDomain string = app.outputs.defaultDomain
+output imageName string = app.outputs.imageName
+output name string = app.outputs.name
+output uri string = app.outputs.uri
diff --git a/dotnet/samples/gh-flow/infra/core/host/container-app.bicep b/dotnet/samples/gh-flow/infra/core/host/container-app.bicep
new file mode 100644
index 0000000000..7781caa801
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/container-app.bicep
@@ -0,0 +1,161 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@description('Allowed origins')
+param allowedOrigins array = []
+
+@description('Name of the environment for container apps')
+param containerAppsEnvironmentName string
+
+@description('CPU cores allocated to a single container instance, e.g., 0.5')
+param containerCpuCoreCount string = '0.5'
+
+@description('The maximum number of replicas to run. Must be at least 1.')
+@minValue(1)
+param containerMaxReplicas int = 10
+
+@description('Memory allocated to a single container instance, e.g., 1Gi')
+param containerMemory string = '1.0Gi'
+
+@description('The minimum number of replicas to run. Must be at least 1.')
+param containerMinReplicas int = 1
+
+@description('The name of the container')
+param containerName string = 'main'
+
+@description('The name of the container registry')
+param containerRegistryName string = ''
+
+@description('The protocol used by Dapr to connect to the app, e.g., http or grpc')
+@allowed([ 'http', 'grpc' ])
+param daprAppProtocol string = 'http'
+
+@description('The Dapr app ID')
+param daprAppId string = containerName
+
+@description('Enable Dapr')
+param daprEnabled bool = false
+
+@description('The environment variables for the container')
+param env array = []
+
+@description('Specifies if the resource ingress is exposed externally')
+param external bool = true
+
+@description('The name of the user-assigned identity')
+param identityName string = ''
+
+@description('The type of identity for the resource')
+@allowed([ 'None', 'SystemAssigned', 'UserAssigned' ])
+param identityType string = 'None'
+
+@description('The name of the container image')
+param imageName string = ''
+
+@description('Specifies if Ingress is enabled for the container app')
+param ingressEnabled bool = true
+
+param revisionMode string = 'Single'
+
+@description('The secrets required for the container')
+param secrets array = []
+
+@description('The service binds associated with the container')
+param serviceBinds array = []
+
+@description('The name of the container apps add-on to use. e.g. redis')
+param serviceType string = ''
+
+@description('The target port for the container')
+param targetPort int = 80
+
+resource userIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(identityName)) {
+ name: identityName
+}
+
+// Private registry support requires both an ACR name and a User Assigned managed identity
+var usePrivateRegistry = !empty(identityName) && !empty(containerRegistryName)
+
+// Automatically set to `UserAssigned` when an `identityName` has been set
+var normalizedIdentityType = !empty(identityName) ? 'UserAssigned' : identityType
+
+module containerRegistryAccess '../security/registry-access.bicep' = if (usePrivateRegistry) {
+ name: '${deployment().name}-registry-access'
+ params: {
+ containerRegistryName: containerRegistryName
+ principalId: usePrivateRegistry ? userIdentity.properties.principalId : ''
+ }
+}
+
+resource app 'Microsoft.App/containerApps@2023-04-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ // It is critical that the identity is granted ACR pull access before the app is created
+ // otherwise the container app will throw a provision error
+ // This also forces us to use an user assigned managed identity since there would no way to
+ // provide the system assigned identity with the ACR pull access before the app is created
+ dependsOn: usePrivateRegistry ? [ containerRegistryAccess ] : []
+ identity: {
+ type: normalizedIdentityType
+ userAssignedIdentities: !empty(identityName) && normalizedIdentityType == 'UserAssigned' ? { '${userIdentity.id}': {} } : null
+ }
+ properties: {
+ managedEnvironmentId: containerAppsEnvironment.id
+ configuration: {
+ activeRevisionsMode: revisionMode
+ ingress: ingressEnabled ? {
+ external: external
+ targetPort: targetPort
+ transport: 'auto'
+ corsPolicy: {
+ allowedOrigins: union([ 'https://portal.azure.com', 'https://ms.portal.azure.com' ], allowedOrigins)
+ }
+ } : null
+ dapr: daprEnabled ? {
+ enabled: true
+ appId: daprAppId
+ appProtocol: daprAppProtocol
+ appPort: ingressEnabled ? targetPort : 0
+ } : { enabled: false }
+ secrets: secrets
+ service: !empty(serviceType) ? { type: serviceType } : null
+ registries: usePrivateRegistry ? [
+ {
+ server: '${containerRegistryName}.azurecr.io'
+ identity: userIdentity.id
+ }
+ ] : []
+ }
+ template: {
+ serviceBinds: !empty(serviceBinds) ? serviceBinds : null
+ containers: [
+ {
+ image: !empty(imageName) ? imageName : 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
+ name: containerName
+ env: env
+ resources: {
+ cpu: json(containerCpuCoreCount)
+ memory: containerMemory
+ }
+ }
+ ]
+ scale: {
+ minReplicas: containerMinReplicas
+ maxReplicas: containerMaxReplicas
+ }
+ }
+ }
+}
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-04-01-preview' existing = {
+ name: containerAppsEnvironmentName
+}
+
+output defaultDomain string = containerAppsEnvironment.properties.defaultDomain
+output identityPrincipalId string = normalizedIdentityType == 'None' ? '' : (empty(identityName) ? app.identity.principalId : userIdentity.properties.principalId)
+output imageName string = imageName
+output name string = app.name
+output serviceBind object = !empty(serviceType) ? { serviceId: app.id, name: name } : {}
+output uri string = ingressEnabled ? 'https://${app.properties.configuration.ingress.fqdn}' : ''
diff --git a/dotnet/samples/gh-flow/infra/core/host/container-apps-environment.bicep b/dotnet/samples/gh-flow/infra/core/host/container-apps-environment.bicep
new file mode 100644
index 0000000000..f29079a021
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/container-apps-environment.bicep
@@ -0,0 +1,40 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@description('Name of the Application Insights resource')
+param applicationInsightsName string = ''
+
+@description('Specifies if Dapr is enabled')
+param daprEnabled bool = false
+
+@description('Name of the Log Analytics workspace')
+param logAnalyticsWorkspaceName string
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-04-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ properties: {
+ appLogsConfiguration: {
+ destination: 'log-analytics'
+ logAnalyticsConfiguration: {
+ customerId: logAnalyticsWorkspace.properties.customerId
+ sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
+ }
+ }
+ daprAIInstrumentationKey: daprEnabled && !empty(applicationInsightsName) ? applicationInsights.properties.InstrumentationKey : ''
+ }
+}
+
+resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
+ name: logAnalyticsWorkspaceName
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (daprEnabled && !empty(applicationInsightsName)) {
+ name: applicationInsightsName
+}
+
+output defaultDomain string = containerAppsEnvironment.properties.defaultDomain
+output id string = containerAppsEnvironment.id
+output name string = containerAppsEnvironment.name
diff --git a/dotnet/samples/gh-flow/infra/core/host/container-apps.bicep b/dotnet/samples/gh-flow/infra/core/host/container-apps.bicep
new file mode 100644
index 0000000000..38f47e068c
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/container-apps.bicep
@@ -0,0 +1,37 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param containerAppsEnvironmentName string
+param containerRegistryName string
+param containerRegistryResourceGroupName string = ''
+param logAnalyticsWorkspaceName string
+param applicationInsightsName string = ''
+
+module containerAppsEnvironment 'container-apps-environment.bicep' = {
+ name: '${name}-container-apps-environment'
+ params: {
+ name: containerAppsEnvironmentName
+ location: location
+ tags: tags
+ logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
+ applicationInsightsName: applicationInsightsName
+ }
+}
+
+module containerRegistry 'container-registry.bicep' = {
+ name: '${name}-container-registry'
+ scope: !empty(containerRegistryResourceGroupName) ? resourceGroup(containerRegistryResourceGroupName) : resourceGroup()
+ params: {
+ name: containerRegistryName
+ location: location
+ tags: tags
+ }
+}
+
+output defaultDomain string = containerAppsEnvironment.outputs.defaultDomain
+output environmentName string = containerAppsEnvironment.outputs.name
+output environmentId string = containerAppsEnvironment.outputs.id
+
+output registryLoginServer string = containerRegistry.outputs.loginServer
+output registryName string = containerRegistry.outputs.name
diff --git a/dotnet/samples/gh-flow/infra/core/host/container-registry.bicep b/dotnet/samples/gh-flow/infra/core/host/container-registry.bicep
new file mode 100644
index 0000000000..02af29925e
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/container-registry.bicep
@@ -0,0 +1,82 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@description('Indicates whether admin user is enabled')
+param adminUserEnabled bool = false
+
+@description('Indicates whether anonymous pull is enabled')
+param anonymousPullEnabled bool = false
+
+@description('Indicates whether data endpoint is enabled')
+param dataEndpointEnabled bool = false
+
+@description('Encryption settings')
+param encryption object = {
+ status: 'disabled'
+}
+
+@description('Options for bypassing network rules')
+param networkRuleBypassOptions string = 'AzureServices'
+
+@description('Public network access setting')
+param publicNetworkAccess string = 'Enabled'
+
+@description('SKU settings')
+param sku object = {
+ name: 'Basic'
+}
+
+@description('Zone redundancy setting')
+param zoneRedundancy string = 'Disabled'
+
+@description('The log analytics workspace ID used for logging and monitoring')
+param workspaceId string = ''
+
+// 2022-02-01-preview needed for anonymousPullEnabled
+resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ sku: sku
+ properties: {
+ adminUserEnabled: adminUserEnabled
+ anonymousPullEnabled: anonymousPullEnabled
+ dataEndpointEnabled: dataEndpointEnabled
+ encryption: encryption
+ networkRuleBypassOptions: networkRuleBypassOptions
+ publicNetworkAccess: publicNetworkAccess
+ zoneRedundancy: zoneRedundancy
+ }
+}
+
+// TODO: Update diagnostics to be its own module
+// Blocking issue: https://github.com/Azure/bicep/issues/622
+// Unable to pass in a `resource` scope or unable to use string interpolation in resource types
+resource diagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(workspaceId)) {
+ name: 'registry-diagnostics'
+ scope: containerRegistry
+ properties: {
+ workspaceId: workspaceId
+ logs: [
+ {
+ category: 'ContainerRegistryRepositoryEvents'
+ enabled: true
+ }
+ {
+ category: 'ContainerRegistryLoginEvents'
+ enabled: true
+ }
+ ]
+ metrics: [
+ {
+ category: 'AllMetrics'
+ enabled: true
+ timeGrain: 'PT1M'
+ }
+ ]
+ }
+}
+
+output loginServer string = containerRegistry.properties.loginServer
+output name string = containerRegistry.name
diff --git a/dotnet/samples/gh-flow/infra/core/host/functions.bicep b/dotnet/samples/gh-flow/infra/core/host/functions.bicep
new file mode 100644
index 0000000000..9265c79194
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/host/functions.bicep
@@ -0,0 +1,87 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+// Reference Properties
+param applicationInsightsName string = ''
+param appServicePlanId string
+param keyVaultName string = ''
+param managedIdentity bool
+param storageAccountName string
+
+// Runtime Properties
+@allowed([
+ 'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom'
+])
+param runtimeName string
+param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}'
+param runtimeVersion string
+
+// Function Settings
+@allowed([
+ '~4', '~3', '~2', '~1'
+])
+param extensionVersion string = '~4'
+
+// Microsoft.Web/sites Properties
+param kind string = 'functionapp'
+
+// Microsoft.Web/sites/config
+param allowedOrigins array = []
+param alwaysOn bool = true
+param appCommandLine string = ''
+@secure()
+param appSettings object = {}
+param clientAffinityEnabled bool = false
+param enableOryxBuild bool = contains(kind, 'linux')
+param functionAppScaleLimit int = -1
+param linuxFxVersion string = runtimeNameAndVersion
+param minimumElasticInstanceCount int = -1
+param numberOfWorkers int = -1
+param scmDoBuildDuringDeployment bool = true
+param use32BitWorkerProcess bool = false
+param healthCheckPath string = ''
+
+
+module functions 'appservice.bicep' = {
+ name: '${name}-functions'
+ params: {
+ name: name
+ location: location
+ tags: tags
+ allowedOrigins: allowedOrigins
+ alwaysOn: alwaysOn
+ appCommandLine: appCommandLine
+ applicationInsightsName: applicationInsightsName
+ appServicePlanId: appServicePlanId
+ appSettings: union(appSettings, {
+ AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${storage.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
+ FUNCTIONS_EXTENSION_VERSION: extensionVersion
+ FUNCTIONS_WORKER_RUNTIME: runtimeName
+ 'AzureOptions__FilesAccountKey': storage.listKeys().keys[0].value
+ })
+ clientAffinityEnabled: clientAffinityEnabled
+ enableOryxBuild: enableOryxBuild
+ functionAppScaleLimit: functionAppScaleLimit
+ healthCheckPath: healthCheckPath
+ keyVaultName: keyVaultName
+ kind: kind
+ linuxFxVersion: linuxFxVersion
+ managedIdentity: managedIdentity
+ minimumElasticInstanceCount: minimumElasticInstanceCount
+ numberOfWorkers: numberOfWorkers
+ runtimeName: runtimeName
+ runtimeVersion: runtimeVersion
+ runtimeNameAndVersion: runtimeNameAndVersion
+ scmDoBuildDuringDeployment: scmDoBuildDuringDeployment
+ use32BitWorkerProcess: use32BitWorkerProcess
+ }
+}
+
+resource storage 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
+ name: storageAccountName
+}
+
+output identityPrincipalId string = managedIdentity ? functions.outputs.identityPrincipalId : ''
+output name string = functions.outputs.name
+output uri string = functions.outputs.uri
diff --git a/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights-dashboard.bicep b/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights-dashboard.bicep
new file mode 100644
index 0000000000..b7af2c1a10
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights-dashboard.bicep
@@ -0,0 +1,1235 @@
+param name string
+param applicationInsightsName string
+param location string = resourceGroup().location
+param tags object = {}
+
+// 2020-09-01-preview because that is the latest valid version
+resource applicationInsightsDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ properties: {
+ lenses: [
+ {
+ order: 0
+ parts: [
+ {
+ position: {
+ x: 0
+ y: 0
+ colSpan: 2
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'id'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart'
+ asset: {
+ idInputName: 'id'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'overview'
+ }
+ }
+ {
+ position: {
+ x: 2
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'ProactiveDetection'
+ }
+ }
+ {
+ position: {
+ x: 3
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-04T01:20:33.345Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 5
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-08T18:47:35.237Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'ConfigurationId'
+ value: '78ce933e-e864-4b05-a27b-71fd55a6afad'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AppMapButtonPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Usage'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 3
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-04T01:22:35.782Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Reliability'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 7
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ {
+ name: 'DataModel'
+ value: {
+ version: '1.0.0'
+ timeContext: {
+ durationMs: 86400000
+ createdTime: '2018-05-04T23:42:40.072Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ isOptional: true
+ }
+ {
+ name: 'ConfigurationId'
+ value: '8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart'
+ isAdapter: true
+ asset: {
+ idInputName: 'ResourceId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'failures'
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Responsiveness\r\n'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 11
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ {
+ name: 'DataModel'
+ value: {
+ version: '1.0.0'
+ timeContext: {
+ durationMs: 86400000
+ createdTime: '2018-05-04T23:43:37.804Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ isOptional: true
+ }
+ {
+ name: 'ConfigurationId'
+ value: '2a8ede4f-2bee-4b9c-aed9-2db0e8a01865'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart'
+ isAdapter: true
+ asset: {
+ idInputName: 'ResourceId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'performance'
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Browser'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 15
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'MetricsExplorerJsonDefinitionId'
+ value: 'BrowserPerformanceTimelineMetrics'
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ createdTime: '2018-05-08T12:16:27.534Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'CurrentFilter'
+ value: {
+ eventTypes: [
+ 4
+ 1
+ 3
+ 5
+ 2
+ 6
+ 13
+ ]
+ typeFacets: {}
+ isPermissive: false
+ }
+ }
+ {
+ name: 'id'
+ value: {
+ Name: applicationInsights.name
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'browser'
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'sessions/count'
+ aggregationType: 5
+ namespace: 'microsoft.insights/components/kusto'
+ metricVisualization: {
+ displayName: 'Sessions'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'users/count'
+ aggregationType: 5
+ namespace: 'microsoft.insights/components/kusto'
+ metricVisualization: {
+ displayName: 'Users'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Unique sessions and users'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ menuid: 'segmentationUsers'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'requests/failed'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Failed requests'
+ color: '#EC008C'
+ }
+ }
+ ]
+ title: 'Failed requests'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ menuid: 'failures'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'requests/duration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Server response time'
+ color: '#00BCF2'
+ }
+ }
+ ]
+ title: 'Server response time'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ menuid: 'performance'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'browserTimings/networkDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Page load network connect time'
+ color: '#7E58FF'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'browserTimings/processingDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Client processing time'
+ color: '#44F1C8'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'browserTimings/sendDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Send request time'
+ color: '#EB9371'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'browserTimings/receiveDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Receiving response time'
+ color: '#0672F1'
+ }
+ }
+ ]
+ title: 'Average page load time breakdown'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'availabilityResults/availabilityPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Availability'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average availability'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ menuid: 'availability'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'exceptions/server'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Server exceptions'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'dependencies/failed'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Dependency failures'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Server exceptions and Dependency failures'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'performanceCounters/processorCpuPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Processor time'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'performanceCounters/processCpuPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Process CPU'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Average processor and process CPU utilization'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'exceptions/browser'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Browser exceptions'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Browser exceptions'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'availabilityResults/count'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Availability test results count'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Availability test results count'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'performanceCounters/processIOBytesPerSecond'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Process IO rate'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average process I/O rate'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
+ }
+ name: 'performanceCounters/memoryAvailableBytes'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Available memory'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average available memory'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ ]
+ }
+ ]
+ }
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
+ name: applicationInsightsName
+}
diff --git a/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights.bicep b/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights.bicep
new file mode 100644
index 0000000000..9cb814321c
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/monitor/applicationinsights.bicep
@@ -0,0 +1,30 @@
+param name string
+param dashboardName string
+param location string = resourceGroup().location
+param tags object = {}
+param includeDashboard bool = true
+param logAnalyticsWorkspaceId string
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
+ name: name
+ location: location
+ tags: tags
+ kind: 'web'
+ properties: {
+ Application_Type: 'web'
+ WorkspaceResourceId: logAnalyticsWorkspaceId
+ }
+}
+
+module applicationInsightsDashboard 'applicationinsights-dashboard.bicep' = if (includeDashboard) {
+ name: 'application-insights-dashboard'
+ params: {
+ name: dashboardName
+ location: location
+ applicationInsightsName: applicationInsights.name
+ }
+}
+
+output connectionString string = applicationInsights.properties.ConnectionString
+output instrumentationKey string = applicationInsights.properties.InstrumentationKey
+output name string = applicationInsights.name
diff --git a/dotnet/samples/gh-flow/infra/core/monitor/loganalytics.bicep b/dotnet/samples/gh-flow/infra/core/monitor/loganalytics.bicep
new file mode 100644
index 0000000000..770544ccab
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/monitor/loganalytics.bicep
@@ -0,0 +1,21 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ properties: any({
+ retentionInDays: 30
+ features: {
+ searchVersion: 1
+ }
+ sku: {
+ name: 'PerGB2018'
+ }
+ })
+}
+
+output id string = logAnalytics.id
+output name string = logAnalytics.name
diff --git a/dotnet/samples/gh-flow/infra/core/monitor/monitoring.bicep b/dotnet/samples/gh-flow/infra/core/monitor/monitoring.bicep
new file mode 100644
index 0000000000..a56f9ecb1b
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/monitor/monitoring.bicep
@@ -0,0 +1,33 @@
+param logAnalyticsName string
+param applicationInsightsName string
+param applicationInsightsDashboardName string
+param location string = resourceGroup().location
+param tags object = {}
+param includeDashboard bool = true
+
+module logAnalytics 'loganalytics.bicep' = {
+ name: 'loganalytics'
+ params: {
+ name: logAnalyticsName
+ location: location
+ tags: tags
+ }
+}
+
+module applicationInsights 'applicationinsights.bicep' = {
+ name: 'applicationinsights'
+ params: {
+ name: applicationInsightsName
+ location: location
+ tags: tags
+ dashboardName: applicationInsightsDashboardName
+ includeDashboard: includeDashboard
+ logAnalyticsWorkspaceId: logAnalytics.outputs.id
+ }
+}
+
+output applicationInsightsConnectionString string = applicationInsights.outputs.connectionString
+output applicationInsightsInstrumentationKey string = applicationInsights.outputs.instrumentationKey
+output applicationInsightsName string = applicationInsights.outputs.name
+output logAnalyticsWorkspaceId string = logAnalytics.outputs.id
+output logAnalyticsWorkspaceName string = logAnalytics.outputs.name
diff --git a/dotnet/samples/gh-flow/infra/core/security/registry-access.bicep b/dotnet/samples/gh-flow/infra/core/security/registry-access.bicep
new file mode 100644
index 0000000000..5335efabc8
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/security/registry-access.bicep
@@ -0,0 +1,19 @@
+metadata description = 'Assigns ACR Pull permissions to access an Azure Container Registry.'
+param containerRegistryName string
+param principalId string
+
+var acrPullRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
+
+resource aksAcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: containerRegistry // Use when specifying a scope that is different than the deployment scope
+ name: guid(subscription().id, resourceGroup().id, principalId, acrPullRole)
+ properties: {
+ roleDefinitionId: acrPullRole
+ principalType: 'ServicePrincipal'
+ principalId: principalId
+ }
+}
+
+resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' existing = {
+ name: containerRegistryName
+}
diff --git a/dotnet/samples/gh-flow/infra/core/storage/storage-account.bicep b/dotnet/samples/gh-flow/infra/core/storage/storage-account.bicep
new file mode 100644
index 0000000000..75461a6542
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/core/storage/storage-account.bicep
@@ -0,0 +1,76 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@allowed([
+ 'Cool'
+ 'Hot'
+ 'Premium' ])
+param accessTier string = 'Hot'
+param allowBlobPublicAccess bool = true
+param allowCrossTenantReplication bool = true
+param allowSharedKeyAccess bool = true
+param containers array = []
+param defaultToOAuthAuthentication bool = false
+param deleteRetentionPolicy object = {}
+@allowed([ 'AzureDnsZone', 'Standard' ])
+param dnsEndpointType string = 'Standard'
+param kind string = 'StorageV2'
+param minimumTlsVersion string = 'TLS1_2'
+param networkAcls object = {
+ bypass: 'AzureServices'
+ defaultAction: 'Allow'
+}
+@allowed([ 'Enabled', 'Disabled' ])
+param publicNetworkAccess string = 'Enabled'
+param sku object = { name: 'Standard_LRS' }
+param fileShares array = []
+param tables array = []
+
+resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = {
+ name: name
+ location: location
+ tags: tags
+ kind: kind
+ sku: sku
+ properties: {
+ accessTier: accessTier
+ allowBlobPublicAccess: allowBlobPublicAccess
+ allowCrossTenantReplication: allowCrossTenantReplication
+ allowSharedKeyAccess: allowSharedKeyAccess
+ defaultToOAuthAuthentication: defaultToOAuthAuthentication
+ dnsEndpointType: dnsEndpointType
+ minimumTlsVersion: minimumTlsVersion
+ networkAcls: networkAcls
+ publicNetworkAccess: publicNetworkAccess
+ }
+
+ resource blobServices 'blobServices' = if (!empty(containers)) {
+ name: 'default'
+ properties: {
+ deleteRetentionPolicy: deleteRetentionPolicy
+ }
+ resource container 'containers' = [for container in containers: {
+ name: container.name
+ properties: {
+ publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None'
+ }
+ }]
+ }
+ resource fileServices 'fileServices' = if (!empty(fileShares)) {
+ name: 'default'
+ resource share 'shares' = [for fileShare in fileShares: {
+ name: fileShare
+ }]
+ }
+
+ resource tableServices 'tableServices' = if (!empty(tables)) {
+ name: 'default'
+ resource table 'tables' = [for table in tables: {
+ name: table
+ }]
+ }
+}
+
+output name string = storage.name
+output primaryEndpoints object = storage.properties.primaryEndpoints
diff --git a/dotnet/samples/gh-flow/infra/main.bicep b/dotnet/samples/gh-flow/infra/main.bicep
new file mode 100644
index 0000000000..331ac6595c
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/main.bicep
@@ -0,0 +1,160 @@
+targetScope = 'subscription'
+
+@minLength(1)
+@maxLength(64)
+@description('Name of the the environment which is used to generate a short unique hash used in all resources.')
+param environmentName string
+
+@minLength(1)
+@description('Primary location for all resources')
+param location string
+
+@secure()
+param githubAppKey string
+param githubAppId string
+param githubAppInstallationId string
+param openAIServiceType string
+param openAIServiceId string
+param openAIDeploymentId string
+param openAIEmbeddingId string
+param openAIEndpoint string
+@secure()
+param openAIKey string
+
+param applicationInsightsDashboardName string = ''
+param applicationInsightsName string = ''
+param logAnalyticsName string = ''
+param resourceGroupName string = ''
+param storageAccountName string = ''
+param containerAppsEnvironmentName string = ''
+param containerRegistryName string = ''
+param ghFlowServiceName string = ''
+param cosmosAccountName string = ''
+
+
+var aciShare = 'acishare'
+var qdrantShare = 'qdrantshare'
+
+var abbrs = loadJsonContent('./abbreviations.json')
+var resourceToken = toLower(uniqueString(subscription().id, environmentName, location))
+var tags = { 'azd-env-name': environmentName }
+
+// Organize resources in a resource group
+resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
+ name: !empty(resourceGroupName) ? resourceGroupName : '${abbrs.resourcesResourceGroups}${environmentName}'
+ location: location
+ tags: tags
+}
+
+module storage './core/storage/storage-account.bicep' = {
+ name: 'storage'
+ scope: rg
+ params: {
+ name: !empty(storageAccountName) ? storageAccountName : '${abbrs.storageStorageAccounts}${resourceToken}'
+ location: location
+ tags: tags
+ fileShares: [
+ aciShare
+ qdrantShare
+ ]
+ }
+}
+
+// Monitor application with Azure Monitor
+module monitoring './core/monitor/monitoring.bicep' = {
+ name: 'monitoring'
+ scope: rg
+ params: {
+ location: location
+ tags: tags
+ logAnalyticsName: !empty(logAnalyticsName) ? logAnalyticsName : '${abbrs.operationalInsightsWorkspaces}${resourceToken}'
+ applicationInsightsName: !empty(applicationInsightsName) ? applicationInsightsName : '${abbrs.insightsComponents}${resourceToken}'
+ applicationInsightsDashboardName: !empty(applicationInsightsDashboardName) ? applicationInsightsDashboardName : '${abbrs.portalDashboards}${resourceToken}'
+ }
+}
+
+// Container apps host (including container registry)
+module containerApps './core/host/container-apps.bicep' = {
+ name: 'container-apps'
+ scope: rg
+ params: {
+ name: 'app'
+ location: location
+ tags: tags
+ containerAppsEnvironmentName: !empty(containerAppsEnvironmentName) ? containerAppsEnvironmentName : '${abbrs.appManagedEnvironments}${resourceToken}'
+ containerRegistryName: !empty(containerRegistryName) ? containerRegistryName : '${abbrs.containerRegistryRegistries}${resourceToken}'
+ logAnalyticsWorkspaceName: monitoring.outputs.logAnalyticsWorkspaceName
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ }
+}
+
+module qdrant './core/database/qdrant/qdrant-aca.bicep' = {
+ name: 'qdrant-deploy'
+ scope: rg
+ params: {
+ location: location
+ containerAppsEnvironmentName: containerApps.outputs.environmentName
+ shareName: qdrantShare
+ storageName: storage.outputs.name
+ }
+}
+
+// The application database
+module cosmos './app/db.bicep' = {
+ name: 'cosmos'
+ scope: rg
+ params: {
+ accountName: !empty(cosmosAccountName) ? cosmosAccountName : '${abbrs.documentDBDatabaseAccounts}${resourceToken}'
+ databaseName: 'devteam'
+ location: location
+ tags: tags
+ }
+}
+
+module ghFlow './app/gh-flow.bicep' = {
+ name: 'gh-flow'
+ scope: rg
+ params: {
+ name: !empty(ghFlowServiceName) ? ghFlowServiceName : '${abbrs.appContainerApps}ghflow-${resourceToken}'
+ location: location
+ tags: tags
+ identityName: '${abbrs.managedIdentityUserAssignedIdentities}ghflow-${resourceToken}'
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ containerAppsEnvironmentName: containerApps.outputs.environmentName
+ containerRegistryName:containerApps.outputs.registryName
+ storageAccountName: storage.outputs.name
+ aciShare: aciShare
+ githubAppId: githubAppId
+ githubAppInstallationId: githubAppInstallationId
+ githubAppKey: githubAppKey
+ openAIDeploymentId: openAIDeploymentId
+ openAIEmbeddingId: openAIEmbeddingId
+ openAIEndpoint: openAIEndpoint
+ openAIKey: openAIKey
+ openAIServiceId: openAIServiceId
+ openAIServiceType: openAIServiceType
+ qdrantEndpoint: 'https://${qdrant.outputs.fqdn}'
+ rgName: rg.name
+ cosmosAccountName: cosmos.outputs.accountName
+ }
+}
+
+
+// App outputs
+output APPLICATIONINSIGHTS_CONNECTION_STRING string = monitoring.outputs.applicationInsightsConnectionString
+output AZURE_CONTAINER_ENVIRONMENT_NAME string = containerApps.outputs.environmentName
+output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerApps.outputs.registryLoginServer
+output AZURE_CONTAINER_REGISTRY_NAME string = containerApps.outputs.registryName
+output AZURE_LOCATION string = location
+output AZURE_TENANT_ID string = subscription().tenantId
+output AZURE_SUBSCRIPTION_ID string = subscription().subscriptionId
+output AZURE_RESOURCE_GROUP_NAME string = rg.name
+output AZURE_FILESHARE_NAME string = aciShare
+output AZURE_FILESHARE_ACCOUNT_NAME string = storage.outputs.name
+output QDRANT_ENDPOINT string = 'https://${qdrant.outputs.fqdn}'
+output WEBHOOK_SECRET string = ghFlow.outputs.WEBHOOK_SECRET
+
+// Data outputs
+output AZURE_COSMOS_ENDPOINT string = cosmos.outputs.endpoint
+output AZURE_COSMOS_CONNECTION_STRING_KEY string = cosmos.outputs.connectionStringKey
+output AZURE_COSMOS_DATABASE_NAME string = cosmos.outputs.databaseName
diff --git a/dotnet/samples/gh-flow/infra/main.parameters.json b/dotnet/samples/gh-flow/infra/main.parameters.json
new file mode 100644
index 0000000000..05edbfaaee
--- /dev/null
+++ b/dotnet/samples/gh-flow/infra/main.parameters.json
@@ -0,0 +1,42 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "environmentName": {
+ "value": "${AZURE_ENV_NAME}"
+ },
+ "location": {
+ "value": "${AZURE_LOCATION}"
+ },
+ "githubAppKey": {
+ "value": "${GH_APP_KEY}"
+ },
+ "githubAppId": {
+ "value": "${GH_APP_ID}"
+ },
+ "githubAppInstallationId": {
+ "value": "${GH_APP_INST_ID}"
+ },
+ "openAIServiceType": {
+ "value": "${OAI_SERVICE_TYPE}"
+ },
+ "openAIServiceId": {
+ "value": "${OAI_SERVICE_ID}"
+ },
+ "openAIDeploymentId": {
+ "value": "${OAI_DEPLOYMENT_ID}"
+ },
+ "openAIEmbeddingId": {
+ "value": "${OAI_EMBEDDING_ID}"
+ },
+ "openAIEndpoint": {
+ "value": "${OAI_ENDPOINT}"
+ },
+ "openAIKey": {
+ "value": "${OAI_KEY}"
+ },
+ "principalId": {
+ "value": "${AZURE_PRINCIPAL_ID}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Architect/Architect.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Architect/Architect.cs
new file mode 100644
index 0000000000..66812798aa
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Architect/Architect.cs
@@ -0,0 +1,29 @@
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+
+// The architect has Org+Repo scope and is holding the knowledge of the high level architecture of the project
+public class Architect : AiAgent,IDaprAgent
+{
+ public Architect(ActorHost host, DaprClient client, ISemanticTextMemory memory, Kernel kernel)
+ : base(host, client, memory, kernel)
+ {
+ }
+
+ public override Task HandleEvent(Event item)
+ {
+ return Task.CompletedTask;
+ }
+}
+
+public class ArchitectState
+{
+ public string FilesTree { get; set; }
+ public string HighLevelArchitecture { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/AzureGenie.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/AzureGenie.cs
new file mode 100644
index 0000000000..15305a5e04
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/AzureGenie.cs
@@ -0,0 +1,64 @@
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public class AzureGenie : Agent, IDaprAgent
+{
+ private readonly IManageAzure _azureService;
+
+ public AzureGenie(ActorHost host,DaprClient client, IManageAzure azureService) : base(host, client)
+ {
+ _azureService = azureService;
+ }
+
+ public override async Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.ReadmeCreated):
+ {
+ var context = item.ToGithubContext();
+ await Store(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber, "readme", "md", "output", item.Data["readme"]);
+ await PublishEvent(Consts.PubSub, Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.ReadmeStored),
+ Subject = context.Subject,
+ Data = context.ToData()
+ });
+ }
+
+ break;
+ case nameof(GithubFlowEventType.CodeCreated):
+ {
+ var context = item.ToGithubContext();
+ await Store(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber, "run", "sh", "output", item.Data["code"]);
+ await RunInSandbox(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber);
+ await PublishEvent(Consts.PubSub, Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.SandboxRunCreated),
+ Subject = context.Subject,
+ Data = context.ToData()
+ });
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output)
+ {
+ await _azureService.Store(org, repo, parentIssueNumber, issueNumber, filename, extension, dir, output);
+ }
+
+ public async Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ await _azureService.RunInSandbox(org, repo, parentIssueNumber, issueNumber);
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/Developer.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/Developer.cs
new file mode 100644
index 0000000000..8648cb6020
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/Developer.cs
@@ -0,0 +1,84 @@
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+namespace Microsoft.AI.DevTeam.Dapr;
+public class Dev : AiAgent, IDaprAgent
+{
+
+ private readonly ILogger _logger;
+
+ public Dev(ActorHost host, DaprClient client, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(host, client, memory, kernel)
+ {
+ _logger = logger;
+ }
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.CodeGenerationRequested):
+ {
+ var context = item.ToGithubContext();
+ var code = await GenerateCode(item.Data["input"]);
+ var data = context.ToData();
+ data["result"] = code;
+ await PublishEvent(Consts.PubSub, Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.CodeGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+ break;
+ case nameof(GithubFlowEventType.CodeChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var lastCode = state.History.Last().Message;
+ var data = context.ToData();
+ data["code"] = lastCode;
+ await PublishEvent(Consts.PubSub, Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.CodeCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task GenerateCode(string ask)
+ {
+ try
+ {
+ // TODO: ask the architect for the high level architecture as well as the files structure of the project
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask)};
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf",context);
+ return await CallFunction(DeveloperSkills.Implement, enhancedContext);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error generating code");
+ return default;
+ }
+ }
+}
+
+public class DeveloperState
+{
+ public string Understanding { get; set; }
+}
+
+public class UnderstandingResult
+{
+ public string NewUnderstanding { get; set; }
+ public string Explanation { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/DeveloperPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/DeveloperPrompts.cs
new file mode 100644
index 0000000000..1e876ad9e2
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Developer/DeveloperPrompts.cs
@@ -0,0 +1,56 @@
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public static class DeveloperSkills {
+ public static string Implement = """
+ You are a Developer for an application.
+ Please output the code required to accomplish the task assigned to you below and wrap it in a bash script that creates the files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Improve = """
+ You are a Developer for an application. Your job is to imrove the code that you are given in the input below.
+ Please output a new version of code that fixes any problems with this version.
+ If there is an error message in the input you should fix that error in the code.
+ Wrap the code output up in a bash script that creates the necessary files by overwriting any previous files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are an experienced software developer, with strong experience in Azure and Microsoft technologies.
+ Extract the key features and capabilities of the code file below, with the intent to build an understanding of an entire code repository.
+ You can include references or documentation links in your explanation. Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ Example:
+ Keywords: Azure, networking, security, authentication
+
+ ===code===
+ {{$input}}
+ ===end-code===
+ Only include the points in a bullet point format and DON'T add anything outside of the bulleted list.
+ Be short and concise.
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+ """;
+
+ public static string ConsolidateUnderstanding = """
+ You are an experienced software developer, with strong experience in Azure and Microsoft technologies.
+ You are trying to build an understanding of the codebase from code files. This is the current understanding of the project:
+ ===current-understanding===
+ {{$input}}
+ ===end-current-understanding===
+ and this is the new information that surfaced
+ ===new-understanding===
+ {{$newUnderstanding}}
+ ===end-new-understanding===
+ Your job is to update your current understanding with the new information.
+ Only include the points in a bullet point format and DON'T add anything outside of the bulleted list.
+ Be short and concise.
+ """;
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DevLeadPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DevLeadPrompts.cs
new file mode 100644
index 0000000000..e5cdba5daf
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DevLeadPrompts.cs
@@ -0,0 +1,51 @@
+namespace Microsoft.AI.DevTeam.Dapr;
+public static class DevLeadSkills {
+ public static string Plan = """
+ You are a Dev Lead for an application team, building the application described below.
+ Please break down the steps and modules required to develop the complete application, describe each step in detail.
+ Make prescriptive architecture, language, and frameowrk choices, do not provide a range of choices.
+ For each step or module then break down the steps or subtasks required to complete that step or module.
+ For each subtask write an LLM prompt that would be used to tell a model to write the coee that will accomplish that subtask. If the subtask involves taking action/running commands tell the model to write the script that will run those commands.
+ In each LLM prompt restrict the model from outputting other text that is not in the form of code or code comments.
+ Please output a JSON array data structure, in the precise schema shown below, with a list of steps and a description of each step, and the steps or subtasks that each requires, and the LLM prompts for each subtask.
+ Example:
+ {
+ "steps": [
+ {
+ "step": "1",
+ "description": "This is the first step",
+ "subtasks": [
+ {
+ "subtask": "Subtask 1",
+ "description": "This is the first subtask",
+ "prompt": "Write the code to do the first subtask"
+ },
+ {
+ "subtask": "Subtask 2",
+ "description": "This is the second subtask",
+ "prompt": "Write the code to do the second subtask"
+ }
+ ]
+ }
+ ]
+ }
+ Do not output any other text.
+ Do not wrap the JSON in any other text, output the JSON format described above, making sure it's a valid JSON.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are a Dev Lead.
+ Please explain the code that is in the input below. You can include references or documentation links in your explanation.
+ Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ example:
+ Keywords: Azure, networking, security, authentication
+
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+
+ --
+ Input: {{$input}}
+ """;
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DeveloperLead.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DeveloperLead.cs
new file mode 100644
index 0000000000..bae1059627
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/DeveloperLead/DeveloperLead.cs
@@ -0,0 +1,97 @@
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class DeveloperLead : AiAgent, IDaprAgent
+{
+ private readonly ILogger _logger;
+
+ public DeveloperLead(ActorHost host, DaprClient client, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(host, client, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.DevPlanRequested):
+ {
+ var context = item.ToGithubContext();
+ var plan = await CreatePlan(item.Data["input"]);
+ var data = context.ToData();
+ data["result"] = plan;
+ await PublishEvent(Consts.PubSub,Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.DevPlanGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+ break;
+ case nameof(GithubFlowEventType.DevPlanChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var latestPlan = state.History.Last().Message;
+ var data = context.ToData();
+ data["plan"] = latestPlan;
+ await PublishEvent(Consts.PubSub,Consts.MainTopic, new Event
+ {
+ Type = nameof(GithubFlowEventType.DevPlanCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ public async Task CreatePlan(string ask)
+ {
+ try
+ {
+ // TODO: Ask the architect for the existing high level architecture
+ // as well as the file structure
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask) };
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf", context);
+ return await CallFunction(DevLeadSkills.Plan, enhancedContext);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating development plan");
+ return default;
+ }
+ }
+}
+
+public class DevLeadPlanResponse
+{
+ public List steps { get; set; }
+}
+
+public class Step
+{
+ public string description { get; set; }
+ public string step { get; set; }
+ public List subtasks { get; set; }
+}
+
+public class Subtask
+{
+ public string subtask { get; set; }
+ public string prompt { get; set; }
+}
+
+public class DeveloperLeadState
+{
+ public string Plan { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Hubber.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Hubber.cs
new file mode 100644
index 0000000000..902ab210cc
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Hubber.cs
@@ -0,0 +1,100 @@
+using System.Text.Json;
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public class Hubber : Agent, IDaprAgent
+{
+ private readonly IManageGithub _ghService;
+
+ public Hubber(ActorHost host, DaprClient client, IManageGithub ghService) :base(host, client)
+ {
+ _ghService = ghService;
+ }
+
+ public override async Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.NewAsk):
+ {
+ var context = item.ToGithubContext();
+ var pmIssue = await CreateIssue(context.Org, context.Repo , item.Data["input"], "PM.Readme", context.IssueNumber);
+ var devLeadIssue = await CreateIssue(context.Org, context.Repo , item.Data["input"], "DevLead.Plan", context.IssueNumber);
+ await PostComment(context.Org, context.Repo, context.IssueNumber, $" - #{pmIssue} - tracks PM.Readme");
+ await PostComment(context.Org, context.Repo, context.IssueNumber, $" - #{devLeadIssue} - tracks DevLead.Plan");
+ await CreateBranch(context.Org, context.Repo, $"sk-{context.IssueNumber}");
+ }
+ break;
+ case nameof(GithubFlowEventType.ReadmeGenerated):
+ case nameof(GithubFlowEventType.DevPlanGenerated):
+ case nameof(GithubFlowEventType.CodeGenerated):
+ {
+ var context = item.ToGithubContext();
+ var result = item.Data["result"];
+ var contents = string.IsNullOrEmpty(result)? "Sorry, I got tired, can you try again please? ": result;
+ await PostComment(context.Org,context.Repo, context.IssueNumber, contents);
+ }
+
+ break;
+ case nameof(GithubFlowEventType.DevPlanCreated):
+ {
+ var context = item.ToGithubContext();
+ var plan = JsonSerializer.Deserialize(item.Data["plan"]);
+ var prompts = plan.steps.SelectMany(s => s.subtasks.Select(st => st.prompt));
+
+ foreach (var prompt in prompts)
+ {
+ var functionName = "Developer.Implement";
+ var issue = await CreateIssue(context.Org, context.Repo, prompt, functionName, context.ParentNumber.Value);
+ var commentBody = $" - #{issue} - tracks {functionName}";
+ await PostComment(context.Org, context.Repo, context.ParentNumber.Value, commentBody);
+ }
+ }
+ break;
+ case nameof(GithubFlowEventType.ReadmeStored):
+ {
+ var context = item.ToGithubContext();
+ var branch = $"sk-{context.ParentNumber}";
+ await CommitToBranch(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber, "output", branch);
+ await CreatePullRequest(context.Org, context.Repo, context.ParentNumber.Value, branch);
+ }
+ break;
+ case nameof(GithubFlowEventType.SandboxRunFinished):
+ {
+ var context = item.ToGithubContext();
+ var branch = $"sk-{context.ParentNumber}";
+ await CommitToBranch(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber, "output", branch);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task CreateIssue(string org, string repo, string input, string function, long parentNumber)
+ {
+ return await _ghService.CreateIssue(org, repo, input, function, parentNumber);
+ }
+ public async Task PostComment(string org, string repo, long issueNumber, string comment)
+ {
+ await _ghService.PostComment(org, repo, issueNumber, comment);
+ }
+ public async Task CreateBranch(string org, string repo, string branch)
+ {
+ await _ghService.CreateBranch(org, repo, branch);
+ }
+ public async Task CreatePullRequest(string org, string repo, long issueNumber, string branch)
+ {
+ await _ghService.CreatePR(org, repo, issueNumber, branch);
+ }
+ public async Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch)
+ {
+ await _ghService.CommitToBranch(org, repo, parentNumber, issueNumber, rootDir, branch);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/PMPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/PMPrompts.cs
new file mode 100644
index 0000000000..a6b727a1bd
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/PMPrompts.cs
@@ -0,0 +1,34 @@
+namespace Microsoft.AI.DevTeam.Dapr;
+public static class PMSkills
+{
+public static string BootstrapProject = """
+ Please write a bash script with the commands that would be required to generate applications as described in the following input.
+ You may add comments to the script and the generated output but do not add any other text except the bash script.
+ You may include commands to build the applications but do not run them.
+ Do not include any git commands.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+ public static string Readme = """
+ You are a program manager on a software development team. You are working on an app described below.
+ Based on the input below, and any dialog or other context, please output a raw README.MD markdown file documenting the main features of the app and the architecture or code organization.
+ Do not describe how to create the application.
+ Write the README as if it were documenting the features and architecture of the application. You may include instructions for how to run the application.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are a Product Manager.
+ Please explain the code that is in the input below. You can include references or documentation links in your explanation.
+ Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ example:
+ Keywords: Azure, networking, security, authentication
+
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+
+ --
+ Input: {{$input}}
+ """;
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/ProductManager.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/ProductManager.cs
new file mode 100644
index 0000000000..ce08c1d1aa
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/ProductManager/ProductManager.cs
@@ -0,0 +1,78 @@
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public class ProductManager : AiAgent, IDaprAgent
+{
+ private readonly ILogger _logger;
+
+ public ProductManager(ActorHost host, DaprClient client, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(host, client, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.ReadmeRequested):
+ {
+ var context = item.ToGithubContext();
+ var readme = await CreateReadme(item.Data["input"]);
+ var data = context.ToData();
+ data["result"]=readme;
+ await PublishEvent(Consts.PubSub,Consts.MainTopic, new Event {
+ Type = nameof(GithubFlowEventType.ReadmeGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+ break;
+ case nameof(GithubFlowEventType.ReadmeChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var lastReadme = state.History.Last().Message;
+ var data = context.ToData();
+ data["readme"] = lastReadme;
+ await PublishEvent(Consts.PubSub,Consts.MainTopic, new Event {
+ Type = nameof(GithubFlowEventType.ReadmeCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task CreateReadme(string ask)
+ {
+ try
+ {
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask) };
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf", context);
+ return await CallFunction(PMSkills.Readme, enhancedContext);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating readme");
+ return default;
+ }
+ }
+}
+
+public class ProductManagerState
+{
+ public string Capabilities { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Sandbox.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Sandbox.cs
new file mode 100644
index 0000000000..e5b3649789
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Agents/Sandbox.cs
@@ -0,0 +1,106 @@
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class Sandbox : Agent, IDaprAgent, IRemindable
+{
+ private const string ReminderName = "SandboxRunReminder";
+ public string StateStore = "agents-statestore";
+ private readonly IManageAzure _azService;
+
+ public Sandbox(ActorHost host, DaprClient client, IManageAzure azService) : base(host, client)
+ {
+ _azService = azService;
+ }
+
+ public override async Task HandleEvent(Event item)
+ {
+ switch(item.Type)
+ {
+ case nameof(GithubFlowEventType.SandboxRunCreated):
+ {
+ var context = item.ToGithubContext();
+ await ScheduleCommitSandboxRun(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ public async Task ScheduleCommitSandboxRun(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ await StoreState(org, repo, parentIssueNumber, issueNumber);
+ await this.RegisterReminderAsync(
+ ReminderName,
+ null,
+ TimeSpan.Zero,
+ TimeSpan.FromMinutes(1));
+ }
+
+ private async Task StoreState(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ var state = new SandboxMetadata {
+ Org = org,
+ Repo = repo,
+ IssueNumber = issueNumber,
+ ParentIssueNumber = parentIssueNumber,
+ IsCompleted = false
+ };
+ await StateManager.SetStateAsync(
+ StateStore,
+ state);
+ }
+ private async Task Cleanup()
+ {
+ var agentState = await StateManager.GetStateAsync(StateStore);
+ agentState.IsCompleted = true;
+ await UnregisterReminderAsync(ReminderName);
+ await StateManager.SetStateAsync(
+ StateStore,
+ agentState);
+ }
+
+ public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
+ {
+ var agentState = await StateManager.GetStateAsync(StateStore);
+ if (!agentState.IsCompleted)
+ {
+ var sandboxId = $"sk-sandbox-{agentState.Org}-{agentState.Repo}-{agentState.ParentIssueNumber}-{agentState.IssueNumber}";
+ if (await _azService.IsSandboxCompleted(sandboxId))
+ {
+ await _azService.DeleteSandbox(sandboxId);
+ var data = new Dictionary {
+ { "org", agentState.Org },
+ { "repo", agentState.Repo },
+ { "issueNumber", agentState.IssueNumber.ToString() },
+ { "parentNumber", agentState.ParentIssueNumber.ToString() }
+ };
+ var subject = $"{agentState.Org}-{agentState.Repo}-{agentState.IssueNumber}";
+ await PublishEvent(Consts.PubSub,Consts.MainTopic, new Event {
+ Type = nameof(GithubFlowEventType.SandboxRunFinished),
+ Subject = subject,
+ Data = data
+ });
+ await Cleanup();
+ }
+ }
+ else
+ {
+ await Cleanup();
+ }
+ }
+}
+
+public class SandboxMetadata
+{
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public long ParentIssueNumber { get; set; }
+ public long IssueNumber { get; set; }
+ public bool IsCompleted { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Dockerfile b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Dockerfile
new file mode 100644
index 0000000000..94041c3fab
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Dockerfile
@@ -0,0 +1,23 @@
+FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
+WORKDIR /app
+EXPOSE 5274
+EXPOSE 11111
+EXPOSE 30000
+
+ENV ASPNETCORE_URLS=http://+:5274
+
+FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+ARG configuration=Release
+COPY . .
+RUN dotnet restore "src/apps/gh-flow/gh-flow.csproj"
+WORKDIR "/src/apps/gh-flow"
+RUN dotnet build "gh-flow.csproj" -c $configuration -o /app/build
+
+FROM build AS publish
+ARG configuration=Release
+RUN dotnet publish "gh-flow.csproj" -c $configuration -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "gh-flow.dll"]
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Events/GithubFlowEventType.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Events/GithubFlowEventType.cs
new file mode 100644
index 0000000000..24b165711f
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Events/GithubFlowEventType.cs
@@ -0,0 +1,69 @@
+using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
+using Microsoft.AI.Agents.Abstractions;
+
+namespace Microsoft.AI.DevTeam.Dapr.Events
+{
+ public enum GithubFlowEventType
+ {
+ NewAsk,
+ ReadmeChainClosed,
+ CodeChainClosed,
+ CodeGenerationRequested,
+ DevPlanRequested,
+ ReadmeGenerated,
+ DevPlanGenerated,
+ CodeGenerated,
+ DevPlanChainClosed,
+ ReadmeRequested,
+ ReadmeStored,
+ SandboxRunFinished,
+ ReadmeCreated,
+ CodeCreated,
+ DevPlanCreated,
+ SandboxRunCreated
+ }
+
+ public static class EventExtensions
+ {
+ public static GithubContext ToGithubContext(this Event evt)
+ {
+ return new GithubContext
+ {
+ Org = evt.Data["org"],
+ Repo = evt.Data["repo"],
+ IssueNumber = long.Parse(evt.Data["issueNumber"]),
+ ParentNumber = string.IsNullOrEmpty(evt.Data["parentNumber"]) ? default : long.Parse(evt.Data["parentNumber"])
+ };
+ }
+
+ public static Dictionary ToData(this GithubContext context)
+ {
+ return new Dictionary {
+ { "org", context.Org },
+ { "repo", context.Repo },
+ { "issueNumber", $"{context.IssueNumber}" },
+ { "parentNumber", context.ParentNumber.HasValue? context.ParentNumber.ToString(): default }
+ };
+ }
+
+
+ }
+
+ public class GithubContext
+ {
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public long IssueNumber { get; set; }
+ public long? ParentNumber { get; set; }
+
+ public string Subject => $"{Org}-{Repo}-{IssueNumber}";
+ }
+
+ [DataContract]
+ public class EventEnvelope
+ {
+ [JsonPropertyName("data")]
+ public Event Data { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Microsoft.AI.DevTeam.Dapr.csproj b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Microsoft.AI.DevTeam.Dapr.csproj
new file mode 100644
index 0000000000..fb26c2709c
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Microsoft.AI.DevTeam.Dapr.csproj
@@ -0,0 +1,43 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+ true
+ c073c86e-8483-4956-942f-331fd09172d4
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/AzureOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/AzureOptions.cs
new file mode 100644
index 0000000000..2fcbcab789
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/AzureOptions.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class AzureOptions
+{
+ [Required]
+ public string SubscriptionId { get; set; }
+ [Required]
+ public string Location { get; set; }
+ [Required]
+ public string ContainerInstancesResourceGroup { get; set; }
+ [Required]
+ public string FilesShareName { get; set; }
+ [Required]
+ public string FilesAccountName { get; set; }
+ [Required]
+ public string FilesAccountKey { get; set; }
+ [Required]
+ public string SandboxImage { get; set; }
+ public string ManagedIdentity { get; set; }
+ public string CosmosConnectionString { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/Consts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/Consts.cs
new file mode 100644
index 0000000000..2531cbdc63
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/Consts.cs
@@ -0,0 +1,8 @@
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public static class Consts
+{
+ public const string MainTopic = "DevPersonas";
+ public const string PubSub = "agents-pubsub";
+ public const string AppId = "dev-agents";
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/GithubOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/GithubOptions.cs
new file mode 100644
index 0000000000..a88480538a
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/GithubOptions.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class GithubOptions
+{
+ [Required]
+ public string AppKey { get; set; }
+ [Required]
+ public int AppId { get; set; }
+ [Required]
+ public long InstallationId { get; set; }
+ [Required]
+ public string WebhookSecret { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/OpenAIOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/OpenAIOptions.cs
new file mode 100644
index 0000000000..e69ebf59f2
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/OpenAIOptions.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class OpenAIOptions
+{
+ [Required]
+ public string ServiceType { get; set; }
+ [Required]
+ public string ServiceId { get; set; }
+ [Required]
+ public string DeploymentOrModelId { get; set; }
+ [Required]
+ public string EmbeddingDeploymentOrModelId { get; set; }
+ [Required]
+ public string Endpoint { get; set; }
+ [Required]
+ public string ApiKey { get; set; }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/QdrantOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/QdrantOptions.cs
new file mode 100644
index 0000000000..ea79a9557a
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/QdrantOptions.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class QdrantOptions
+{
+ [Required]
+ public string Endpoint { get; set; }
+ [Required]
+ public int VectorSize { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/ServiceOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/ServiceOptions.cs
new file mode 100644
index 0000000000..8c3b09c768
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Options/ServiceOptions.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class ServiceOptions
+{
+ private string _ingesterUrl;
+
+ [Required]
+ public string IngesterUrl { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Program.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Program.cs
new file mode 100644
index 0000000000..14a610c7c2
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Program.cs
@@ -0,0 +1,205 @@
+using System.Text.Json;
+using Azure;
+using Azure.AI.OpenAI;
+using Microsoft.Extensions.Options;
+using Microsoft.SemanticKernel;
+using Octokit.Webhooks;
+using Octokit.Webhooks.AspNetCore;
+using Azure.Identity;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Http.Resilience;
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel.Connectors.Qdrant;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Dapr;
+using Dapr.Actors.Client;
+using Dapr.Actors;
+using Microsoft.AI.DevTeam.Dapr;
+using Microsoft.AI.DevTeam.Dapr.Events;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddSingleton();
+builder.Services.AddTransient(CreateKernel);
+builder.Services.AddTransient(CreateMemory);
+builder.Services.AddHttpClient();
+
+builder.Services.AddSingleton(s =>
+{
+ var ghOptions = s.GetService>();
+ var logger = s.GetService>();
+ var ghService = new GithubAuthService(ghOptions, logger);
+ var client = ghService.GetGitHubClient();
+ return client;
+});
+
+
+builder.Services.AddAzureClients(clientBuilder =>
+{
+ clientBuilder.UseCredential(new DefaultAzureCredential());
+ clientBuilder.AddArmClient(default);
+});
+
+builder.Services.AddDaprClient();
+
+builder.Services.AddActors(
+ options =>
+ {
+ options.UseJsonSerialization = true;
+ options.JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
+ options.ReentrancyConfig = new ActorReentrancyConfig {
+ Enabled = true
+ };
+ options.Actors.RegisterActor();
+ options.Actors.RegisterActor();
+ options.Actors.RegisterActor();
+ options.Actors.RegisterActor();
+ options.Actors.RegisterActor();
+ options.Actors.RegisterActor();
+ });
+
+builder.Services.AddSingleton();
+
+builder.Services.AddApplicationInsightsTelemetry();
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(GithubOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(AzureOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(OpenAIOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(QdrantOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(ServiceOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+
+
+builder.Services.Configure(options =>
+{
+ options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+});
+var app = builder.Build();
+
+app.UseRouting()
+ .UseEndpoints(endpoints =>
+{
+ var ghOptions = app.Services.GetService>().Value;
+ endpoints.MapGitHubWebhooks(secret: ghOptions.WebhookSecret);
+ endpoints.MapActorsHandlers();
+ endpoints.MapSubscribeHandler();
+});
+
+app.UseCloudEvents();
+
+app.MapPost("/developers", [Topic(Consts.PubSub, Consts.MainTopic,
+ $"(event.type ==\"{nameof(GithubFlowEventType.CodeGenerationRequested)}\") || (event.type ==\"{nameof(GithubFlowEventType.CodeGenerationRequested)}\")", 1)]
+ async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory,nameof(Dev), nameof(Dev.HandleEvent), evt));
+
+app.MapPost("/devleads", [Topic(Consts.PubSub, Consts.MainTopic,
+$"(event.type ==\"{nameof(GithubFlowEventType.DevPlanRequested)}\") || (event.type ==\"{nameof(GithubFlowEventType.DevPlanChainClosed)}\")", 2)]
+async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory, nameof(DeveloperLead), nameof(DeveloperLead.HandleEvent), evt));
+
+app.MapPost("/productmanagers", [Topic(Consts.PubSub, Consts.MainTopic,
+$"(event.type ==\"{nameof(GithubFlowEventType.ReadmeRequested)}\") || (event.type ==\"{nameof(GithubFlowEventType.ReadmeChainClosed)}\")", 3)]
+async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory, nameof(ProductManager), nameof(ProductManager.HandleEvent), evt));
+
+app.MapPost("/hubbers", [Topic(Consts.PubSub, Consts.MainTopic,
+ $"(event.type ==\"{nameof(GithubFlowEventType.NewAsk)}\") || (event.type ==\"{nameof(GithubFlowEventType.ReadmeGenerated)}\") || (event.type ==\"{nameof(GithubFlowEventType.DevPlanGenerated)}\") || (event.type ==\"{nameof(GithubFlowEventType.CodeGenerated)}\") || (event.type ==\"{nameof(GithubFlowEventType.DevPlanCreated)}\") || (event.type ==\"{nameof(GithubFlowEventType.ReadmeStored)}\") || (event.type ==\"{nameof(GithubFlowEventType.SandboxRunFinished)}\")", 4)]
+ async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory, nameof(Hubber), nameof(Hubber.HandleEvent), evt));
+
+app.MapPost("/azuregenies", [Topic(Consts.PubSub, Consts.MainTopic,
+$"(event.type ==\"{nameof(GithubFlowEventType.ReadmeCreated)}\") || (event.type ==\"{nameof(GithubFlowEventType.CodeCreated)}\")", 5)]
+async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory, nameof(AzureGenie), nameof(AzureGenie.HandleEvent), evt));
+
+app.MapPost("/sandboxes", [Topic(Consts.PubSub, Consts.MainTopic,$"(event.type ==\"{nameof(GithubFlowEventType.SandboxRunCreated)}\")", 6)]
+async (IActorProxyFactory proxyFactory, EventEnvelope evt) => await HandleEvent(proxyFactory, nameof(Sandbox), nameof(Sandbox.HandleEvent), evt));
+
+app.Run();
+
+static async Task HandleEvent(IActorProxyFactory proxyFactory, string type, string method, EventEnvelope evt)
+{
+ try
+ {
+ var proxyOptions = new ActorProxyOptions
+ {
+ RequestTimeout = Timeout.InfiniteTimeSpan
+ };
+ var proxy = proxyFactory.Create(new ActorId(evt.Data.Subject), type, proxyOptions);
+ await proxy.InvokeMethodAsync(method, evt.Data);
+ }
+ catch (Exception ex)
+ {
+ throw;
+ }
+}
+
+static ISemanticTextMemory CreateMemory(IServiceProvider provider)
+{
+ var openAiConfig = provider.GetService>().Value;
+ var qdrantConfig = provider.GetService>().Value;
+
+ var loggerFactory = LoggerFactory.Create(builder =>
+ {
+ builder
+ .SetMinimumLevel(LogLevel.Debug)
+ .AddConsole()
+ .AddDebug();
+ });
+
+ var memoryBuilder = new MemoryBuilder();
+ return memoryBuilder.WithLoggerFactory(loggerFactory)
+ .WithQdrantMemoryStore(qdrantConfig.Endpoint, qdrantConfig.VectorSize)
+ .WithAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingDeploymentOrModelId, openAiConfig.Endpoint, openAiConfig.ApiKey)
+ .Build();
+}
+
+static Kernel CreateKernel(IServiceProvider provider)
+{
+ var openAiConfig = provider.GetService>().Value;
+ var clientOptions = new OpenAIClientOptions();
+ clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5);
+ var openAIClient = new OpenAIClient(new Uri(openAiConfig.Endpoint), new AzureKeyCredential(openAiConfig.ApiKey), clientOptions);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddLogging(c => c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug));
+ builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.DeploymentOrModelId, openAIClient);
+ builder.Services.ConfigureHttpClientDefaults(c =>
+ {
+ c.AddStandardResilienceHandler().Configure(o =>
+ {
+ o.Retry.MaxRetryAttempts = 5;
+ o.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
+ });
+ });
+ return builder.Build();
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Properties/launchSettings.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Properties/launchSettings.json
new file mode 100644
index 0000000000..373d72522f
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:59668",
+ "sslPort": 44354
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5244",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7227;http://localhost:5244",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/AzureService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/AzureService.cs
new file mode 100644
index 0000000000..5eef10dc28
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/AzureService.cs
@@ -0,0 +1,160 @@
+using System.Text;
+using Azure;
+using Azure.Core;
+using Azure.ResourceManager;
+using Azure.ResourceManager.ContainerInstance;
+using Azure.ResourceManager.ContainerInstance.Models;
+using Azure.ResourceManager.Resources;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Options;
+
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public class AzureService : IManageAzure
+{
+ private readonly AzureOptions _azSettings;
+ private readonly ILogger _logger;
+ private readonly ArmClient _client;
+
+ public AzureService(IOptions azOptions, ILogger logger, ArmClient client)
+ {
+ _azSettings = azOptions.Value;
+ _logger = logger;
+ _client = client;
+ }
+
+ public async Task DeleteSandbox(string sandboxId)
+ {
+ try
+ {
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ await containerGroup.Value.DeleteAsync(WaitUntil.Started);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error deleting sandbox");
+ throw;
+ }
+
+ }
+
+ public async Task IsSandboxCompleted(string sandboxId)
+ {
+ try
+ {
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ return containerGroup.Value.Data.ProvisioningState == "Succeeded"
+ && containerGroup.Value.Data.Containers.First().InstanceView.CurrentState.State == "Terminated";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error checking sandbox status");
+ throw;
+ }
+ }
+
+ public async Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ try
+ {
+ var runId = $"sk-sandbox-{org}-{repo}-{parentIssueNumber}-{issueNumber}";
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+ var scriptPath = $"/azfiles/output/{org}-{repo}/{parentIssueNumber}/{issueNumber}/run.sh";
+ var collection = resourceGroupResource.GetContainerGroups();
+ var data = new ContainerGroupData(new AzureLocation(_azSettings.Location), new ContainerInstanceContainer[]
+ {
+ new ContainerInstanceContainer(runId,_azSettings.SandboxImage,new ContainerResourceRequirements(new ContainerResourceRequestsContent(1.5,1)))
+ {
+ Command = { "/bin/bash", $"{scriptPath}" },
+ VolumeMounts =
+ {
+ new ContainerVolumeMount("azfiles","/azfiles/")
+ {
+ IsReadOnly = false,
+ }
+ },
+ }}, ContainerInstanceOperatingSystemType.Linux)
+ {
+ Volumes =
+ {
+ new ContainerVolume("azfiles")
+ {
+ AzureFile = new ContainerInstanceAzureFileVolume(_azSettings.FilesShareName,_azSettings.FilesAccountName)
+ {
+ StorageAccountKey = _azSettings.FilesAccountKey
+ },
+ },
+ },
+ RestartPolicy = ContainerGroupRestartPolicy.Never,
+ Sku = ContainerGroupSku.Standard,
+ Priority = ContainerGroupPriority.Regular
+ };
+ await collection.CreateOrUpdateAsync(WaitUntil.Completed, runId, data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error running sandbox");
+ throw;
+ }
+
+ }
+
+ public async Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output)
+ {
+ try
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+ var parentDirName = $"{dir}/{org}-{repo}";
+
+ var fileName = $"{filename}.{extension}";
+
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ await share.CreateIfNotExistsAsync();
+ await share.GetDirectoryClient($"{dir}").CreateIfNotExistsAsync(); ;
+
+ var parentDir = share.GetDirectoryClient(parentDirName);
+ await parentDir.CreateIfNotExistsAsync();
+
+ var parentIssueDir = parentDir.GetSubdirectoryClient($"{parentIssueNumber}");
+ await parentIssueDir.CreateIfNotExistsAsync();
+
+ var directory = parentIssueDir.GetSubdirectoryClient($"{issueNumber}");
+ await directory.CreateIfNotExistsAsync();
+
+ var file = directory.GetFileClient(fileName);
+ // hack to enable script to save files in the same directory
+ var cwdHack = "#!/bin/bash\n cd $(dirname $0)";
+ var contents = extension == "sh" ? output.Replace("#!/bin/bash", cwdHack) : output;
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents)))
+ {
+ await file.CreateAsync(stream.Length);
+ await file.UploadRangeAsync(
+ new HttpRange(0, stream.Length),
+ stream);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error storing output");
+ throw;
+ }
+ }
+}
+
+public interface IManageAzure
+{
+ Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output);
+ Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber);
+ Task IsSandboxCompleted(string sandboxId);
+ Task DeleteSandbox(string sandboxId);
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/CodeAnalyzer.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/CodeAnalyzer.cs
new file mode 100644
index 0000000000..392d441373
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/CodeAnalyzer.cs
@@ -0,0 +1,53 @@
+using System.Text;
+using System.Text.Json;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public interface IAnalyzeCode
+{
+ Task> Analyze(string content);
+}
+public class CodeAnalyzer : IAnalyzeCode
+{
+ private readonly ServiceOptions _serviceOptions;
+ private readonly HttpClient _httpClient;
+ private readonly ILogger _logger;
+
+ public CodeAnalyzer(IOptions serviceOptions, HttpClient httpClient, ILogger logger)
+ {
+ _serviceOptions = serviceOptions.Value;
+ _httpClient = httpClient;
+ _logger = logger;
+ _httpClient.BaseAddress = new Uri(_serviceOptions.IngesterUrl);
+
+ }
+ public async Task> Analyze(string content)
+ {
+ try
+ {
+ var request = new CodeAnalysisRequest { Content = content };
+ var body = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
+ var response = await _httpClient.PostAsync("api/AnalyzeCode", body);
+ var stringResult = await response.Content.ReadAsStringAsync();
+ var result = JsonSerializer.Deserialize>(stringResult);
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error analyzing code");
+ return Enumerable.Empty();
+ }
+ }
+}
+
+public class CodeAnalysisRequest
+{
+ public string Content { get; set; }
+}
+
+public class CodeAnalysis
+{
+ public string Meaning { get; set; }
+ public string CodeBlock { get; set; }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubAuthService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubAuthService.cs
new file mode 100644
index 0000000000..12168ace2f
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubAuthService.cs
@@ -0,0 +1,68 @@
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Security.Cryptography;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using Octokit;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public class GithubAuthService
+{
+ private readonly GithubOptions _githubSettings;
+ private readonly ILogger _logger;
+
+ public GithubAuthService(IOptions ghOptions, ILogger logger)
+ {
+ _githubSettings = ghOptions.Value;
+ _logger = logger;
+ }
+
+ public string GenerateJwtToken(string appId, string appKey, int minutes)
+ {
+ using var rsa = RSA.Create();
+ rsa.ImportFromPem(appKey);
+ var securityKey = new RsaSecurityKey(rsa);
+
+ var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);
+
+ var now = DateTime.UtcNow;
+ var iat = new DateTimeOffset(now).ToUnixTimeSeconds();
+ var exp = new DateTimeOffset(now.AddMinutes(minutes)).ToUnixTimeSeconds();
+
+ var claims = new[] {
+ new Claim(JwtRegisteredClaimNames.Iat, iat.ToString(), ClaimValueTypes.Integer64),
+ new Claim(JwtRegisteredClaimNames.Exp, exp.ToString(), ClaimValueTypes.Integer64)
+ };
+
+ var token = new JwtSecurityToken(
+ issuer: appId,
+ claims: claims,
+ expires: DateTime.Now.AddMinutes(10),
+ signingCredentials: credentials
+ );
+
+ return new JwtSecurityTokenHandler().WriteToken(token);
+ }
+
+ public GitHubClient GetGitHubClient()
+ {
+ try
+ {
+ var jwtToken = GenerateJwtToken(_githubSettings.AppId.ToString(), _githubSettings.AppKey, 10);
+ var appClient = new GitHubClient(new ProductHeaderValue("SK-DEV-APP"))
+ {
+ Credentials = new Credentials(jwtToken, AuthenticationType.Bearer)
+ };
+ var response = appClient.GitHubApps.CreateInstallationToken(_githubSettings.InstallationId).Result;
+ return new GitHubClient(new ProductHeaderValue($"SK-DEV-APP-Installation{_githubSettings.InstallationId}"))
+ {
+ Credentials = new Credentials(response.Token)
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting GitHub client");
+ throw;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubService.cs
new file mode 100644
index 0000000000..70853fe259
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubService.cs
@@ -0,0 +1,227 @@
+using System.Text;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Options;
+using Octokit;
+using Octokit.Helpers;
+
+
+namespace Microsoft.AI.DevTeam.Dapr;
+
+public class GithubService : IManageGithub
+{
+ private readonly GitHubClient _ghClient;
+ private readonly AzureOptions _azSettings;
+ private readonly ILogger _logger;
+ private readonly HttpClient _httpClient;
+
+ public GithubService(IOptions azOptions, GitHubClient ghClient, ILogger logger, HttpClient httpClient)
+ {
+ _ghClient = ghClient;
+ _azSettings = azOptions.Value;
+ _logger = logger;
+ _httpClient = httpClient;
+ }
+
+ public async Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch)
+ {
+ try
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+
+ var dirName = $"{rootDir}/{org}-{repo}/{parentNumber}/{issueNumber}";
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ var directory = share.GetDirectoryClient(dirName);
+
+ var remaining = new Queue();
+ remaining.Enqueue(directory);
+ while (remaining.Count > 0)
+ {
+ var dir = remaining.Dequeue();
+ await foreach (var item in dir.GetFilesAndDirectoriesAsync())
+ {
+ if (!item.IsDirectory && item.Name != "run.sh") // we don't want the generated script in the PR
+ {
+ try
+ {
+ var file = dir.GetFileClient(item.Name);
+ var filePath = file.Path.Replace($"{_azSettings.FilesShareName}/", "")
+ .Replace($"{dirName}/", "");
+ var fileStream = await file.OpenReadAsync();
+ using (var reader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ var value = reader.ReadToEnd();
+
+ await _ghClient.Repository.Content.CreateFile(
+ org, repo, filePath,
+ new CreateFileRequest($"Commit message", value, branch)); // TODO: add more meaningfull commit message
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"Error while uploading file {item.Name}");
+ }
+ }
+ else if (item.IsDirectory)
+ {
+ remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error committing to branch");
+ throw;
+ }
+ }
+
+ public async Task CreateBranch(string org, string repo, string branch)
+ {
+ try
+ {
+ var ghRepo = await _ghClient.Repository.Get(org, repo);
+ if (ghRepo.Size == 0)
+ {
+ // Create a new file and commit it to the repository
+ var createChangeSet = await _ghClient.Repository.Content.CreateFile(
+ org,
+ repo,
+ "README.md",
+ new CreateFileRequest("Initial commit", "# Readme")
+ );
+ }
+
+ await _ghClient.Git.Reference.CreateBranch(org, repo, branch, ghRepo.DefaultBranch);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating branch");
+ throw;
+ }
+ }
+
+ public async Task GetMainLanguage(string org, string repo)
+ {
+ try
+ {
+ var languages = await _ghClient.Repository.GetAllLanguages(org, repo);
+ var mainLanguage = languages.OrderByDescending(l => l.NumberOfBytes).First();
+ return mainLanguage.Name;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting main language");
+ throw;
+ }
+ }
+
+ public async Task CreateIssue(string org, string repo, string input, string function, long parentNumber)
+ {
+ try
+ {
+ var newIssue = new NewIssue($"{function} chain for #{parentNumber}")
+ {
+ Body = input,
+ };
+ newIssue.Labels.Add(function);
+ newIssue.Labels.Add($"Parent.{parentNumber}");
+ var issue = await _ghClient.Issue.Create(org, repo, newIssue);
+ return issue.Number;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating issue");
+ throw;
+ }
+ }
+
+ public async Task CreatePR(string org, string repo, long number, string branch)
+ {
+ try
+ {
+ var ghRepo = await _ghClient.Repository.Get(org, repo);
+ await _ghClient.PullRequest.Create(org, repo, new NewPullRequest($"New app #{number}", branch, ghRepo.DefaultBranch));
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating PR");
+ throw;
+ }
+ }
+
+ public async Task PostComment(string org, string repo, long issueNumber, string comment)
+ {
+ try
+ {
+ await _ghClient.Issue.Comment.Create(org, repo, (int)issueNumber, comment);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error posting comment");
+ throw;
+ }
+ }
+
+ public async Task> GetFiles(string org, string repo, string branch, Func filter)
+ {
+ try
+ {
+ var items = await _ghClient.Repository.Content.GetAllContentsByRef(org, repo, branch);
+ return await CollectFiles(org, repo, branch, items, filter);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting files");
+ throw;
+ }
+ }
+
+ private async Task> CollectFiles(string org, string repo, string branch, IReadOnlyList items, Func filter)
+ {
+ try
+ {
+ var result = new List();
+ foreach (var item in items)
+ {
+ if (item.Type == ContentType.File && filter(item))
+ {
+ var content = await _httpClient.GetStringAsync(item.DownloadUrl);
+ result.Add(new FileResponse
+ {
+ Name = item.Name,
+ Content = content
+ });
+ }
+ else if (item.Type == ContentType.Dir)
+ {
+ var subItems = await _ghClient.Repository.Content.GetAllContentsByRef(org, repo, item.Path, branch);
+ result.AddRange(await CollectFiles(org, repo, branch, subItems, filter));
+ }
+ }
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error collecting files");
+ throw;
+ }
+ }
+}
+
+public class FileResponse
+{
+ public string Name { get; set; }
+ public string Content { get; set; }
+}
+
+public interface IManageGithub
+{
+ Task CreateIssue(string org, string repo, string input, string function, long parentNumber);
+ Task CreatePR(string org, string repo, long number, string branch);
+ Task CreateBranch(string org, string repo, string branch);
+ Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch);
+
+ Task PostComment(string org, string repo, long issueNumber, string comment);
+ Task> GetFiles(string org, string repo, string branch, Func filter);
+ Task GetMainLanguage(string org, string repo);
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubWebHookProcessor.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubWebHookProcessor.cs
new file mode 100644
index 0000000000..0bff68a51d
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/Services/GithubWebHookProcessor.cs
@@ -0,0 +1,169 @@
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.DevTeam.Dapr.Events;
+using Octokit.Webhooks;
+using Octokit.Webhooks.Events;
+using Octokit.Webhooks.Events.IssueComment;
+using Octokit.Webhooks.Events.Issues;
+using Octokit.Webhooks.Models;
+
+namespace Microsoft.AI.DevTeam.Dapr;
+public sealed class GithubWebHookProcessor : WebhookEventProcessor
+{
+ private readonly DaprClient _daprClient;
+ private readonly ILogger _logger;
+
+ public GithubWebHookProcessor(DaprClient daprClient, ILogger logger)
+ {
+ _daprClient = daprClient;
+ _logger = logger;
+ }
+ protected override async Task ProcessIssuesWebhookAsync(WebhookHeaders headers, IssuesEvent issuesEvent, IssuesAction action)
+ {
+ try
+ {
+ _logger.LogInformation("Processing issue event");
+ var org = issuesEvent.Repository.Owner.Login;
+ var repo = issuesEvent.Repository.Name;
+ var issueNumber = issuesEvent.Issue.Number;
+ var input = issuesEvent.Issue.Body;
+ // Assumes the label follows the following convention: Skill.Function example: PM.Readme
+ // Also, we've introduced the Parent label, that ties the sub-issue with the parent issue
+ var labels = issuesEvent.Issue.Labels
+ .Select(l => l.Name.Split('.'))
+ .Where(parts => parts.Length == 2)
+ .ToDictionary(parts => parts[0], parts => parts[1]);
+ var skillName = labels.Keys.Where(k => k != "Parent").FirstOrDefault();
+ long? parentNumber = labels.ContainsKey("Parent") ? long.Parse(labels["Parent"]) : null;
+
+ var suffix = $"{org}-{repo}";
+ if (issuesEvent.Action == IssuesAction.Opened)
+ {
+ _logger.LogInformation("Processing HandleNewAsk");
+ await HandleNewAsk(issueNumber, parentNumber, skillName, labels[skillName], input, org, repo);
+ }
+ else if (issuesEvent.Action == IssuesAction.Closed && issuesEvent.Issue.User.Type.Value == UserType.Bot)
+ {
+ _logger.LogInformation("Processing HandleClosingIssue");
+ await HandleClosingIssue(issueNumber, parentNumber, skillName, labels[skillName], org, repo);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Processing issue event");
+ throw;
+ }
+ }
+
+ protected override async Task ProcessIssueCommentWebhookAsync(
+ WebhookHeaders headers,
+ IssueCommentEvent issueCommentEvent,
+ IssueCommentAction action)
+ {
+ try
+ {
+ _logger.LogInformation("Processing issue comment event");
+ var org = issueCommentEvent.Repository.Owner.Login;
+ var repo = issueCommentEvent.Repository.Name;
+ var issueNumber = issueCommentEvent.Issue.Number;
+ var input = issueCommentEvent.Comment.Body;
+ // Assumes the label follows the following convention: Skill.Function example: PM.Readme
+ var labels = issueCommentEvent.Issue.Labels
+ .Select(l => l.Name.Split('.'))
+ .Where(parts => parts.Length == 2)
+ .ToDictionary(parts => parts[0], parts => parts[1]);
+ var skillName = labels.Keys.Where(k => k != "Parent").FirstOrDefault();
+ long? parentNumber = labels.ContainsKey("Parent") ? long.Parse(labels["Parent"]) : null;
+ var suffix = $"{org}-{repo}";
+ // we only respond to non-bot comments
+ if (issueCommentEvent.Sender.Type.Value != UserType.Bot)
+ {
+ await HandleNewAsk(issueNumber, parentNumber, skillName, labels[skillName], input, org, repo);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Processing issue comment event");
+ throw;
+ }
+
+ }
+
+ private async Task HandleClosingIssue(long issueNumber, long? parentNumber, string skillName, string functionName, string org, string repo)
+ {
+ var subject = $"{org}-{repo}-{issueNumber}";
+ var eventType = (skillName, functionName) switch
+ {
+ ("PM", "Readme") => nameof(GithubFlowEventType.ReadmeChainClosed),
+ ("DevLead", "Plan") => nameof(GithubFlowEventType.DevPlanChainClosed),
+ ("Developer", "Implement") => nameof(GithubFlowEventType.CodeChainClosed),
+ _ => nameof(GithubFlowEventType.NewAsk)
+ };
+ var data = new Dictionary
+ {
+ { "org", org },
+ { "repo", repo },
+ { "issueNumber", issueNumber.ToString() },
+ { "parentNumber", parentNumber?.ToString()}
+ };
+
+ var evt = new Event
+ {
+ Type = eventType,
+ Subject = subject,
+ Data = data
+ };
+ await PublishEvent(evt);
+ }
+
+ private async Task HandleNewAsk(long issueNumber, long? parentNumber, string skillName, string functionName, string input, string org, string repo)
+ {
+ try
+ {
+ _logger.LogInformation("Handling new ask");
+ var subject = $"{org}-{repo}-{issueNumber}";
+ var eventType = (skillName, functionName) switch
+ {
+ ("Do", "It") => nameof(GithubFlowEventType.NewAsk),
+ ("PM", "Readme") => nameof(GithubFlowEventType.ReadmeRequested),
+ ("DevLead", "Plan") => nameof(GithubFlowEventType.DevPlanRequested),
+ ("Developer", "Implement") => nameof(GithubFlowEventType.CodeGenerationRequested),
+ _ => nameof(GithubFlowEventType.NewAsk)
+ };
+ var data = new Dictionary
+ {
+ { "org", org },
+ { "repo", repo },
+ { "issueNumber", issueNumber.ToString() },
+ { "parentNumber", parentNumber?.ToString()},
+ { "input" , input}
+ };
+ var evt = new Event
+ {
+ Type = eventType,
+ Subject = subject,
+ Data = data
+ };
+ await PublishEvent(evt);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Handling new ask");
+ throw;
+ }
+ }
+
+ private async Task PublishEvent(Event evt)
+ {
+ var metadata = new Dictionary() {
+ { "cloudevent.Type", evt.Type },
+ { "cloudevent.Subject", evt.Subject },
+ { "cloudevent.id", Guid.NewGuid().ToString()}
+ };
+
+ await _daprClient.PublishEventAsync(Consts.PubSub, Consts.MainTopic, evt, metadata);
+ }
+}
+
+
+
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.azure.template.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.azure.template.json
new file mode 100644
index 0000000000..26563297ae
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.azure.template.json
@@ -0,0 +1,45 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Information",
+ "Orleans.Streams": "Information"
+ }
+ },
+ "ApplicationInsights": {
+ "ConnectionString": ""
+ },
+ "AllowedHosts": "*",
+ "SANDBOX_IMAGE" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "GithubOptions" : {
+ "AppKey": "",
+ "AppId": "",
+ "InstallationId": "",
+ "WebhookSecret": ""
+ },
+ "AzureOptions" : {
+ "SubscriptionId":"",
+ "Location":"",
+ "ContainerInstancesResourceGroup":"",
+ "FilesShareName":"",
+ "FilesAccountName":"",
+ "FilesAccountKey":"",
+ "SandboxImage" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "ManagedIdentity": ""
+ },
+ "OpenAIOptions" : {
+ "ServiceType":"AzureOpenAI",
+ "ServiceId":"gpt-4",
+ "DeploymentOrModelId":"gpt-4",
+ "EmbeddingDeploymentOrModelId":"text-embedding-ada-002",
+ "Endpoint":"",
+ "ApiKey":""
+ },
+ "QdrantOptions" : {
+ "Endpoint" : "http://qdrant:6333",
+ "VectorSize" : "1536"
+ },
+ "ServiceOptions" : {
+ "IngesterUrl" : "http://localhost:7071"
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.local.template.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.local.template.json
new file mode 100644
index 0000000000..26563297ae
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam.Dapr/appsettings.local.template.json
@@ -0,0 +1,45 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Information",
+ "Orleans.Streams": "Information"
+ }
+ },
+ "ApplicationInsights": {
+ "ConnectionString": ""
+ },
+ "AllowedHosts": "*",
+ "SANDBOX_IMAGE" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "GithubOptions" : {
+ "AppKey": "",
+ "AppId": "",
+ "InstallationId": "",
+ "WebhookSecret": ""
+ },
+ "AzureOptions" : {
+ "SubscriptionId":"",
+ "Location":"",
+ "ContainerInstancesResourceGroup":"",
+ "FilesShareName":"",
+ "FilesAccountName":"",
+ "FilesAccountKey":"",
+ "SandboxImage" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "ManagedIdentity": ""
+ },
+ "OpenAIOptions" : {
+ "ServiceType":"AzureOpenAI",
+ "ServiceId":"gpt-4",
+ "DeploymentOrModelId":"gpt-4",
+ "EmbeddingDeploymentOrModelId":"text-embedding-ada-002",
+ "Endpoint":"",
+ "ApiKey":""
+ },
+ "QdrantOptions" : {
+ "Endpoint" : "http://qdrant:6333",
+ "VectorSize" : "1536"
+ },
+ "ServiceOptions" : {
+ "IngesterUrl" : "http://localhost:7071"
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Architect/Architect.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Architect/Architect.cs
new file mode 100644
index 0000000000..5fa20dc5c4
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Architect/Architect.cs
@@ -0,0 +1,33 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.DevTeam;
+
+
+// The architect has Org+Repo scope and is holding the knowledge of the high level architecture of the project
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class Architect : AiAgent
+{
+ protected override string Namespace => Consts.MainNamespace;
+ public Architect([PersistentState("state", "messages")] IPersistentState> state, ISemanticTextMemory memory, Kernel kernel)
+ : base(state, memory, kernel)
+ {
+ }
+
+ public override Task HandleEvent(Event item)
+ {
+ return Task.CompletedTask;
+ }
+}
+
+[GenerateSerializer]
+public class ArchitectState
+{
+ [Id(0)]
+ public string FilesTree { get; set; }
+ [Id(1)]
+ public string HighLevelArchitecture { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/AzureGenie.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/AzureGenie.cs
new file mode 100644
index 0000000000..4becca3e8b
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/AzureGenie.cs
@@ -0,0 +1,70 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+using Microsoft.AI.DevTeam.Extensions;
+
+namespace Microsoft.AI.DevTeam;
+
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class AzureGenie : Agent
+{
+ protected override string Namespace => Consts.MainNamespace;
+ private readonly IManageAzure _azureService;
+
+ public AzureGenie(IManageAzure azureService)
+ {
+ _azureService = azureService;
+ }
+
+ public override async Task HandleEvent(Event item)
+ {
+ if (item?.Type is null)
+ {
+ throw new ArgumentNullException(nameof(item));
+ }
+
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.ReadmeCreated):
+ {
+ var context = item.ToGithubContext();
+ await Store(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber, "readme", "md", "output", item.Data["readme"]);
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.ReadmeStored),
+ Subject = context.Subject,
+ Data = context.ToData()
+ });
+ break;
+ }
+
+
+ case nameof(GithubFlowEventType.CodeCreated):
+ {
+ var context = item.ToGithubContext();
+ await Store(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber, "run", "sh", "output", item.Data["code"]);
+ await RunInSandbox(context.Org,context.Repo, context.ParentNumber.Value, context.IssueNumber);
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.SandboxRunCreated),
+ Subject = context.Subject,
+ Data = context.ToData()
+ });
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ public async Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output)
+ {
+ await _azureService.Store(org, repo, parentIssueNumber, issueNumber, filename, extension, dir, output);
+ }
+
+ public async Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ await _azureService.RunInSandbox(org, repo, parentIssueNumber, issueNumber);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/Developer.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/Developer.cs
new file mode 100644
index 0000000000..40254e0540
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/Developer.cs
@@ -0,0 +1,99 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.DevTeam;
+
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class Dev : AiAgent, IDevelopApps
+{
+ protected override string Namespace => Consts.MainNamespace;
+
+ private readonly ILogger _logger;
+
+ public Dev([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.CodeGenerationRequested):
+ {
+ var context = item.ToGithubContext();
+ var code = await GenerateCode(item.Data["input"]);
+ var data = context.ToData();
+ data["result"] = code;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.CodeGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ case nameof(GithubFlowEventType.CodeChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var lastCode = _state.State.History.Last().Message;
+ var data = context.ToData();
+ data["code"] = lastCode;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.CodeCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task GenerateCode(string ask)
+ {
+ try
+ {
+ // TODO: ask the architect for the high level architecture as well as the files structure of the project
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask) };
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf", context);
+ return await CallFunction(DeveloperSkills.Implement, enhancedContext);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error generating code");
+ return default;
+ }
+ }
+}
+
+[GenerateSerializer]
+public class DeveloperState
+{
+ [Id(0)]
+ public string Understanding { get; set; }
+}
+
+public interface IDevelopApps
+{
+ public Task GenerateCode(string ask);
+}
+
+[GenerateSerializer]
+public class UnderstandingResult
+{
+ [Id(0)]
+ public string NewUnderstanding { get; set; }
+ [Id(1)]
+ public string Explanation { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/DeveloperPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/DeveloperPrompts.cs
new file mode 100644
index 0000000000..d9d6660207
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Developer/DeveloperPrompts.cs
@@ -0,0 +1,56 @@
+
+namespace Microsoft.AI.DevTeam;
+public static class DeveloperSkills {
+ public static string Implement = """
+ You are a Developer for an application.
+ Please output the code required to accomplish the task assigned to you below and wrap it in a bash script that creates the files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Improve = """
+ You are a Developer for an application. Your job is to imrove the code that you are given in the input below.
+ Please output a new version of code that fixes any problems with this version.
+ If there is an error message in the input you should fix that error in the code.
+ Wrap the code output up in a bash script that creates the necessary files by overwriting any previous files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are an experienced software developer, with strong experience in Azure and Microsoft technologies.
+ Extract the key features and capabilities of the code file below, with the intent to build an understanding of an entire code repository.
+ You can include references or documentation links in your explanation. Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ Example:
+ Keywords: Azure, networking, security, authentication
+
+ ===code===
+ {{$input}}
+ ===end-code===
+ Only include the points in a bullet point format and DON'T add anything outside of the bulleted list.
+ Be short and concise.
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+ """;
+
+ public static string ConsolidateUnderstanding = """
+ You are an experienced software developer, with strong experience in Azure and Microsoft technologies.
+ You are trying to build an understanding of the codebase from code files. This is the current understanding of the project:
+ ===current-understanding===
+ {{$input}}
+ ===end-current-understanding===
+ and this is the new information that surfaced
+ ===new-understanding===
+ {{$newUnderstanding}}
+ ===end-new-understanding===
+ Your job is to update your current understanding with the new information.
+ Only include the points in a bullet point format and DON'T add anything outside of the bulleted list.
+ Be short and concise.
+ """;
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DevLeadPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DevLeadPrompts.cs
new file mode 100644
index 0000000000..2c20812a57
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DevLeadPrompts.cs
@@ -0,0 +1,51 @@
+namespace Microsoft.AI.DevTeam;
+public static class DevLeadSkills {
+ public static string Plan = """
+ You are a Dev Lead for an application team, building the application described below.
+ Please break down the steps and modules required to develop the complete application, describe each step in detail.
+ Make prescriptive architecture, language, and frameowrk choices, do not provide a range of choices.
+ For each step or module then break down the steps or subtasks required to complete that step or module.
+ For each subtask write an LLM prompt that would be used to tell a model to write the coee that will accomplish that subtask. If the subtask involves taking action/running commands tell the model to write the script that will run those commands.
+ In each LLM prompt restrict the model from outputting other text that is not in the form of code or code comments.
+ Please output a JSON array data structure, in the precise schema shown below, with a list of steps and a description of each step, and the steps or subtasks that each requires, and the LLM prompts for each subtask.
+ Example:
+ {
+ "steps": [
+ {
+ "step": "1",
+ "description": "This is the first step",
+ "subtasks": [
+ {
+ "subtask": "Subtask 1",
+ "description": "This is the first subtask",
+ "prompt": "Write the code to do the first subtask"
+ },
+ {
+ "subtask": "Subtask 2",
+ "description": "This is the second subtask",
+ "prompt": "Write the code to do the second subtask"
+ }
+ ]
+ }
+ ]
+ }
+ Do not output any other text.
+ Do not wrap the JSON in any other text, output the JSON format described above, making sure it's a valid JSON.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are a Dev Lead.
+ Please explain the code that is in the input below. You can include references or documentation links in your explanation.
+ Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ example:
+ Keywords: Azure, networking, security, authentication
+
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+
+ --
+ Input: {{$input}}
+ """;
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DeveloperLead.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DeveloperLead.cs
new file mode 100644
index 0000000000..bb87db69cb
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/DeveloperLead/DeveloperLead.cs
@@ -0,0 +1,120 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.DevTeam;
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class DeveloperLead : AiAgent, ILeadDevelopers
+{
+ protected override string Namespace => Consts.MainNamespace;
+ private readonly ILogger _logger;
+
+ public DeveloperLead([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.DevPlanRequested):
+ {
+ var context = item.ToGithubContext();
+ var plan = await CreatePlan(item.Data["input"]);
+ var data = context.ToData();
+ data["result"] = plan;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.DevPlanGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ case nameof(GithubFlowEventType.DevPlanChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var latestPlan = _state.State.History.Last().Message;
+ var data = context.ToData();
+ data["plan"] = latestPlan;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.DevPlanCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ public async Task CreatePlan(string ask)
+ {
+ try
+ {
+ // TODO: Ask the architect for the existing high level architecture
+ // as well as the file structure
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask) };
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf", context);
+ var settings = new OpenAIPromptExecutionSettings{
+ ResponseFormat = "json_object",
+ MaxTokens = 4096,
+ Temperature = 0.8,
+ TopP = 1
+ };
+ return await CallFunction(DevLeadSkills.Plan, enhancedContext, settings);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating development plan");
+ return default;
+ }
+ }
+}
+
+public interface ILeadDevelopers
+{
+ public Task CreatePlan(string ask);
+}
+
+[GenerateSerializer]
+public class DevLeadPlanResponse
+{
+ [Id(0)]
+ public List steps { get; set; }
+}
+
+[GenerateSerializer]
+public class Step
+{
+ [Id(0)]
+ public string description { get; set; }
+ [Id(1)]
+ public string step { get; set; }
+ [Id(2)]
+ public List subtasks { get; set; }
+}
+
+[GenerateSerializer]
+public class Subtask
+{
+ [Id(0)]
+ public string subtask { get; set; }
+ [Id(1)]
+ public string prompt { get; set; }
+}
+
+public class DeveloperLeadState
+{
+ public string Plan { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Hubber.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Hubber.cs
new file mode 100644
index 0000000000..4737c8aee2
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Hubber.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Text.Json;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+
+namespace Microsoft.AI.DevTeam;
+
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class Hubber : Agent
+{
+ protected override string Namespace => Consts.MainNamespace;
+ private readonly IManageGithub _ghService;
+
+ public Hubber(IManageGithub ghService)
+ {
+ _ghService = ghService;
+ }
+
+ public override async Task HandleEvent(Event item)
+ {
+ ArgumentNullException.ThrowIfNull(item);
+ ArgumentNullException.ThrowIfNull(item.Data);
+
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.NewAsk):
+ {
+ var context = item.ToGithubContext();
+ var pmIssue = await CreateIssue(context.Org, context.Repo , item.Data["input"], "PM.Readme", context.IssueNumber);
+ var devLeadIssue = await CreateIssue(context.Org, context.Repo , item.Data["input"], "DevLead.Plan", context.IssueNumber);
+ await PostComment(context.Org, context.Repo, context.IssueNumber, $" - #{pmIssue} - tracks PM.Readme");
+ await PostComment(context.Org, context.Repo, context.IssueNumber, $" - #{devLeadIssue} - tracks DevLead.Plan");
+ await CreateBranch(context.Org, context.Repo, $"sk-{context.IssueNumber}");
+ }
+ break;
+ case nameof(GithubFlowEventType.ReadmeGenerated):
+ case nameof(GithubFlowEventType.DevPlanGenerated):
+ case nameof(GithubFlowEventType.CodeGenerated):
+ {
+ var context = item.ToGithubContext();
+ var result = item.Data["result"];
+ var contents = string.IsNullOrEmpty(result)? "Sorry, I got tired, can you try again please? ": result;
+ await PostComment(context.Org,context.Repo, context.IssueNumber, contents);
+ }
+ break;
+ case nameof(GithubFlowEventType.DevPlanCreated):
+ {
+ var context = item.ToGithubContext();
+ var plan = JsonSerializer.Deserialize(item.Data["plan"]);
+ var prompts = plan.steps.SelectMany(s => s.subtasks.Select(st => st.prompt));
+
+ foreach (var prompt in prompts)
+ {
+ var functionName = "Developer.Implement";
+ var issue = await CreateIssue(context.Org, context.Repo, prompt, functionName, context.ParentNumber.Value);
+ var commentBody = $" - #{issue} - tracks {functionName}";
+ await PostComment(context.Org, context.Repo, context.ParentNumber.Value, commentBody);
+ }
+ }
+ break;
+ case nameof(GithubFlowEventType.ReadmeStored):
+ {
+ var context = item.ToGithubContext();
+ var branch = $"sk-{context.ParentNumber}";
+ await CommitToBranch(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber, "output", branch);
+ await CreatePullRequest(context.Org, context.Repo, context.ParentNumber.Value, branch);
+ }
+ break;
+ case nameof(GithubFlowEventType.SandboxRunFinished):
+ {
+ var context = item.ToGithubContext();
+ var branch = $"sk-{context.ParentNumber}";
+ await CommitToBranch(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber, "output", branch);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task CreateIssue(string org, string repo, string input, string function, long parentNumber)
+ {
+ return await _ghService.CreateIssue(org, repo, input, function, parentNumber);
+ }
+ public async Task PostComment(string org, string repo, long issueNumber, string comment)
+ {
+ await _ghService.PostComment(org, repo, issueNumber, comment);
+ }
+ public async Task CreateBranch(string org, string repo, string branch)
+ {
+ await _ghService.CreateBranch(org, repo, branch);
+ }
+ public async Task CreatePullRequest(string org, string repo, long issueNumber, string branch)
+ {
+ await _ghService.CreatePR(org, repo, issueNumber, branch);
+ }
+ public async Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch)
+ {
+ await _ghService.CommitToBranch(org, repo, parentNumber, issueNumber, rootDir, branch);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/PMPrompts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/PMPrompts.cs
new file mode 100644
index 0000000000..7683010e41
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/PMPrompts.cs
@@ -0,0 +1,34 @@
+namespace Microsoft.AI.DevTeam;
+public static class PMSkills
+{
+public static string BootstrapProject = """
+ Please write a bash script with the commands that would be required to generate applications as described in the following input.
+ You may add comments to the script and the generated output but do not add any other text except the bash script.
+ You may include commands to build the applications but do not run them.
+ Do not include any git commands.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+ public static string Readme = """
+ You are a program manager on a software development team. You are working on an app described below.
+ Based on the input below, and any dialog or other context, please output a raw README.MD markdown file documenting the main features of the app and the architecture or code organization.
+ Do not describe how to create the application.
+ Write the README as if it were documenting the features and architecture of the application. You may include instructions for how to run the application.
+ Input: {{$input}}
+ {{$waf}}
+ """;
+
+ public static string Explain = """
+ You are a Product Manager.
+ Please explain the code that is in the input below. You can include references or documentation links in your explanation.
+ Also where appropriate please output a list of keywords to describe the code or its capabilities.
+ example:
+ Keywords: Azure, networking, security, authentication
+
+ If the code's purpose is not clear output an error:
+ Error: The model could not determine the purpose of the code.
+
+ --
+ Input: {{$input}}
+ """;
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/ProductManager.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/ProductManager.cs
new file mode 100644
index 0000000000..3ffbc8a59c
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/ProductManager/ProductManager.cs
@@ -0,0 +1,86 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.DevTeam;
+
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class ProductManager : AiAgent, IManageProducts
+{
+ protected override string Namespace => Consts.MainNamespace;
+ private readonly ILogger _logger;
+
+ public ProductManager([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.ReadmeRequested):
+ {
+ var context = item.ToGithubContext();
+ var readme = await CreateReadme(item.Data["input"]);
+ var data = context.ToData();
+ data["result"]=readme;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event {
+ Type = nameof(GithubFlowEventType.ReadmeGenerated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ case nameof(GithubFlowEventType.ReadmeChainClosed):
+ {
+ var context = item.ToGithubContext();
+ var lastReadme = _state.State.History.Last().Message;
+ var data = context.ToData();
+ data["readme"] = lastReadme;
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event {
+ Type = nameof(GithubFlowEventType.ReadmeCreated),
+ Subject = context.Subject,
+ Data = data
+ });
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task CreateReadme(string ask)
+ {
+ try
+ {
+ var context = new KernelArguments { ["input"] = AppendChatHistory(ask)};
+ var instruction = "Consider the following architectural guidelines:!waf!";
+ var enhancedContext = await AddKnowledge(instruction, "waf",context);
+ return await CallFunction(PMSkills.Readme, enhancedContext);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating readme");
+ return default;
+ }
+ }
+}
+
+public interface IManageProducts
+{
+ public Task CreateReadme(string ask);
+}
+
+[GenerateSerializer]
+public class ProductManagerState
+{
+ [Id(0)]
+ public string Capabilities { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Sandbox.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Sandbox.cs
new file mode 100644
index 0000000000..4802c3baf3
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Agents/Sandbox.cs
@@ -0,0 +1,108 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.AI.DevTeam.Events;
+using Orleans.Runtime;
+using Orleans.Timers;
+
+namespace Microsoft.AI.DevTeam;
+[ImplicitStreamSubscription(Consts.MainNamespace)]
+public class Sandbox : Agent, IRemindable
+{
+ protected override string Namespace => Consts.MainNamespace;
+ private const string ReminderName = "SandboxRunReminder";
+ private readonly IManageAzure _azService;
+ private readonly IReminderRegistry _reminderRegistry;
+ private IGrainReminder? _reminder;
+
+ protected readonly IPersistentState _state;
+
+ public Sandbox([PersistentState("state", "messages")] IPersistentState state,
+ IReminderRegistry reminderRegistry, IManageAzure azService)
+ {
+ _reminderRegistry = reminderRegistry;
+ _azService = azService;
+ _state = state;
+ }
+ public override async Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(GithubFlowEventType.SandboxRunCreated):
+ {
+ var context = item.ToGithubContext();
+ await ScheduleCommitSandboxRun(context.Org, context.Repo, context.ParentNumber.Value, context.IssueNumber);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ public async Task ScheduleCommitSandboxRun(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ await StoreState(org, repo, parentIssueNumber, issueNumber);
+ _reminder = await _reminderRegistry.RegisterOrUpdateReminder(
+ callingGrainId: this.GetGrainId(),
+ reminderName: ReminderName,
+ dueTime: TimeSpan.Zero,
+ period: TimeSpan.FromMinutes(1));
+ }
+
+ async Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
+ {
+ if (!_state.State.IsCompleted)
+ {
+ var sandboxId = $"sk-sandbox-{_state.State.Org}-{_state.State.Repo}-{_state.State.ParentIssueNumber}-{_state.State.IssueNumber}".ToLower();
+
+ if (await _azService.IsSandboxCompleted(sandboxId))
+ {
+ await _azService.DeleteSandbox(sandboxId);
+ await PublishEvent(Consts.MainNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(GithubFlowEventType.SandboxRunFinished),
+ Data = new Dictionary {
+ { "org", _state.State.Org },
+ { "repo", _state.State.Repo },
+ { "issueNumber", _state.State.IssueNumber.ToString() },
+ { "parentNumber", _state.State.ParentIssueNumber.ToString() }
+ }
+ });
+ await Cleanup();
+ }
+ }
+ else
+ {
+ await Cleanup();
+ }
+ }
+
+ private async Task StoreState(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ _state.State.Org = org;
+ _state.State.Repo = repo;
+ _state.State.ParentIssueNumber = parentIssueNumber;
+ _state.State.IssueNumber = issueNumber;
+ _state.State.IsCompleted = false;
+ await _state.WriteStateAsync();
+ }
+
+ private async Task Cleanup()
+ {
+ _state.State.IsCompleted = true;
+ await _reminderRegistry.UnregisterReminder(
+ this.GetGrainId(), _reminder);
+ await _state.WriteStateAsync();
+ }
+
+
+}
+
+
+public class SandboxMetadata
+{
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public long ParentIssueNumber { get; set; }
+ public long IssueNumber { get; set; }
+ public bool IsCompleted { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Dockerfile b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Dockerfile
new file mode 100644
index 0000000000..094d150169
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Dockerfile
@@ -0,0 +1,23 @@
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5274
+EXPOSE 11111
+EXPOSE 30000
+
+ENV ASPNETCORE_URLS=http://+:5274
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+ARG configuration=Release
+COPY . .
+RUN dotnet restore "samples/gh-flow/src/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj"
+WORKDIR "samples/gh-flow/src/Microsoft.AI.DevTeam"
+RUN dotnet build "Microsoft.AI.DevTeam.csproj" -c $configuration -o /app/build
+
+FROM build AS publish
+ARG configuration=Release
+RUN dotnet publish "Microsoft.AI.DevTeam.csproj" -c $configuration -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Microsoft.AI.DevTeam.dll"]
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Events/GithubFlowEventType.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Events/GithubFlowEventType.cs
new file mode 100644
index 0000000000..3aec523bc0
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Events/GithubFlowEventType.cs
@@ -0,0 +1,66 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.DevTeam.Extensions;
+using System.Globalization;
+
+namespace Microsoft.AI.DevTeam.Events
+{
+ public enum GithubFlowEventType
+ {
+ NewAsk,
+ ReadmeChainClosed,
+ CodeChainClosed,
+ CodeGenerationRequested,
+ DevPlanRequested,
+ ReadmeGenerated,
+ DevPlanGenerated,
+ CodeGenerated,
+ DevPlanChainClosed,
+ ReadmeRequested,
+ ReadmeStored,
+ SandboxRunFinished,
+ ReadmeCreated,
+ CodeCreated,
+ DevPlanCreated,
+ SandboxRunCreated
+ }
+
+ public static class EventExtensions
+ {
+ public static GithubContext ToGithubContext(this Event evt)
+ {
+ ArgumentNullException.ThrowIfNull(evt);
+
+ return new GithubContext
+ {
+ Org = evt.Data["org"],
+ Repo = evt.Data["repo"],
+ IssueNumber = evt.Data.TryParseLong("issueNumber"),
+ ParentNumber = evt.Data.TryParseLong("parentNumber")
+ };
+ }
+
+ public static Dictionary ToData(this GithubContext context)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+
+ return new Dictionary {
+ { "org", context.Org },
+ { "repo", context.Repo },
+ { "issueNumber", $"{context.IssueNumber}" },
+ { "parentNumber", context.ParentNumber.HasValue ? Convert.ToString(context.ParentNumber, CultureInfo.InvariantCulture) : string.Empty }
+ };
+ }
+ }
+
+ public class GithubContext
+ {
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public long IssueNumber { get; set; }
+ public long? ParentNumber { get; set; }
+
+ public string Subject => $"{Org}/{Repo}/{IssueNumber}";
+ }
+}
+
+
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Extensions/ParseExtensions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Extensions/ParseExtensions.cs
new file mode 100644
index 0000000000..8c618c1a42
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Extensions/ParseExtensions.cs
@@ -0,0 +1,16 @@
+namespace Microsoft.AI.DevTeam.Extensions
+{
+ public static class ParseExtensions
+ {
+ public static long TryParseLong(this Dictionary data, string key)
+ {
+ ArgumentNullException.ThrowIfNull(data);
+
+ if (data.TryGetValue(key, out string? value) && !string.IsNullOrEmpty(value) && long.TryParse(value, out var result))
+ {
+ return result;
+ }
+ return default;
+ }
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj
new file mode 100644
index 0000000000..d299007ee6
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj
@@ -0,0 +1,49 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+ true
+ c073c86e-8483-4956-942f-331fd09172d4
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/AzureOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/AzureOptions.cs
new file mode 100644
index 0000000000..4f29ed8b77
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/AzureOptions.cs
@@ -0,0 +1,23 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam;
+
+public class AzureOptions
+{
+ [Required]
+ public string SubscriptionId { get; set; }
+ [Required]
+ public string Location { get; set; }
+ [Required]
+ public string ContainerInstancesResourceGroup { get; set; }
+ [Required]
+ public string FilesShareName { get; set; }
+ [Required]
+ public string FilesAccountName { get; set; }
+ [Required]
+ public string FilesAccountKey { get; set; }
+ [Required]
+ public string SandboxImage { get; set; }
+ public string ManagedIdentity { get; set; }
+ public string CosmosConnectionString { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/Consts.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/Consts.cs
new file mode 100644
index 0000000000..d8575e38ee
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/Consts.cs
@@ -0,0 +1,6 @@
+namespace Microsoft.AI.DevTeam;
+
+public static class Consts
+{
+ public const string MainNamespace = "DevPersonas";
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/GithubOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/GithubOptions.cs
new file mode 100644
index 0000000000..c13fc1e674
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/GithubOptions.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam;
+public class GithubOptions
+{
+ [Required]
+ public string AppKey { get; set; }
+ [Required]
+ public int AppId { get; set; }
+ [Required]
+ public long InstallationId { get; set; }
+ [Required]
+ public string WebhookSecret { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/OpenAIOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/OpenAIOptions.cs
new file mode 100644
index 0000000000..1b251c1fbe
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/OpenAIOptions.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam;
+public class OpenAIOptions
+{
+ [Required]
+ public string ServiceType { get; set; }
+ [Required]
+ public string ServiceId { get; set; }
+ [Required]
+ public string DeploymentOrModelId { get; set; }
+ [Required]
+ public string EmbeddingDeploymentOrModelId { get; set; }
+ [Required]
+ public string Endpoint { get; set; }
+ [Required]
+ public string ApiKey { get; set; }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/QdrantOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/QdrantOptions.cs
new file mode 100644
index 0000000000..da292ce625
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/QdrantOptions.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam;
+public class QdrantOptions
+{
+ [Required]
+ public string Endpoint { get; set; }
+ [Required]
+ public int VectorSize { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/ServiceOptions.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/ServiceOptions.cs
new file mode 100644
index 0000000000..33228424e1
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Options/ServiceOptions.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Microsoft.AI.DevTeam;
+public class ServiceOptions
+{
+ private string _ingesterUrl;
+
+ [Required]
+ public string IngesterUrl { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Program.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Program.cs
new file mode 100644
index 0000000000..00e9ae586a
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Program.cs
@@ -0,0 +1,205 @@
+using System.Text.Json;
+using Azure;
+using Azure.AI.OpenAI;
+using Microsoft.AI.DevTeam;
+using Microsoft.Extensions.Options;
+using Microsoft.SemanticKernel;
+using Octokit.Webhooks;
+using Octokit.Webhooks.AspNetCore;
+using Azure.Identity;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Http.Resilience;
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel.Connectors.Qdrant;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Orleans.Configuration;
+using Orleans.Serialization;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddSingleton();
+builder.Services.AddTransient(CreateKernel);
+builder.Services.AddTransient(CreateMemory);
+builder.Services.AddHttpClient();
+
+
+builder.Services.AddTransient(s =>
+{
+ var ghOptions = s.GetService>();
+ var logger = s.GetService>();
+ var ghService = new GithubAuthService(ghOptions, logger);
+ var client = ghService.GetGitHubClient();
+ return client;
+});
+
+builder.Services.AddAzureClients(clientBuilder =>
+{
+ clientBuilder.AddArmClient(default);
+ clientBuilder.UseCredential(new DefaultAzureCredential());
+});
+
+builder.Services.AddSingleton();
+
+builder.Services.AddApplicationInsightsTelemetry();
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(GithubOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(AzureOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(OpenAIOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(QdrantOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(ServiceOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+
+builder.Host.UseOrleans(siloBuilder =>
+{
+ siloBuilder.UseDashboard(x => x.HostSelf = true);
+ if (builder.Environment.IsDevelopment())
+ {
+ siloBuilder.UseLocalhostClustering()
+ .AddMemoryStreams("StreamProvider")
+ .AddMemoryGrainStorage("PubSubStore")
+ .AddMemoryGrainStorage("messages");
+
+ siloBuilder.UseInMemoryReminderService();
+ siloBuilder.UseDashboard(x => x.HostSelf = true);
+
+ siloBuilder.UseInMemoryReminderService();
+ }
+ else
+ {
+ var cosmosDbconnectionString = builder.Configuration.GetValue("AzureOptions:CosmosConnectionString");
+ siloBuilder.Configure(options =>
+ {
+ options.ClusterId = "ai-dev-cluster";
+ options.ServiceId = "ai-dev-cluster";
+ });
+ siloBuilder.Configure(options =>
+ {
+ options.ResponseTimeout = TimeSpan.FromMinutes(3);
+ options.SystemResponseTimeout = TimeSpan.FromMinutes(3);
+ });
+ siloBuilder.Configure(options =>
+ {
+ options.ResponseTimeout = TimeSpan.FromMinutes(3);
+ });
+ siloBuilder.UseCosmosClustering(o =>
+ {
+ o.ConfigureCosmosClient(cosmosDbconnectionString);
+ o.ContainerName = "devteam";
+ o.DatabaseName = "clustering";
+ o.IsResourceCreationEnabled = true;
+ });
+
+ siloBuilder.UseCosmosReminderService(o =>
+ {
+ o.ConfigureCosmosClient(cosmosDbconnectionString);
+ o.ContainerName = "devteam";
+ o.DatabaseName = "reminders";
+ o.IsResourceCreationEnabled = true;
+ });
+ siloBuilder.AddCosmosGrainStorage(
+ name: "messages",
+ configureOptions: o =>
+ {
+ o.ConfigureCosmosClient(cosmosDbconnectionString);
+ o.ContainerName = "devteam";
+ o.DatabaseName = "persistence";
+ o.IsResourceCreationEnabled = true;
+ });
+ //TODO: replace with EventHub
+ siloBuilder
+ .AddMemoryStreams("StreamProvider")
+ .AddMemoryGrainStorage("PubSubStore");
+ }
+});
+
+builder.Services.Configure(options =>
+{
+ options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+});
+var app = builder.Build();
+
+app.UseRouting()
+ .UseEndpoints(endpoints =>
+{
+ var ghOptions = app.Services.GetService>().Value;
+ endpoints.MapGitHubWebhooks(secret: ghOptions.WebhookSecret);
+});
+
+app.Map("/dashboard", x => x.UseOrleansDashboard());
+
+app.Run();
+
+static ISemanticTextMemory CreateMemory(IServiceProvider provider)
+{
+ var openAiConfig = provider.GetService>().Value;
+ var qdrantConfig = provider.GetService>().Value;
+
+ var loggerFactory = LoggerFactory.Create(builder =>
+ {
+ builder
+ .SetMinimumLevel(LogLevel.Debug)
+ .AddConsole()
+ .AddDebug();
+ });
+
+ var memoryBuilder = new MemoryBuilder();
+ return memoryBuilder.WithLoggerFactory(loggerFactory)
+ .WithQdrantMemoryStore(qdrantConfig.Endpoint, qdrantConfig.VectorSize)
+ .WithAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingDeploymentOrModelId, openAiConfig.Endpoint, openAiConfig.ApiKey)
+ .Build();
+}
+
+static Kernel CreateKernel(IServiceProvider provider)
+{
+ var openAiConfig = provider.GetService>().Value;
+ var clientOptions = new OpenAIClientOptions();
+ clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5);
+ var openAIClient = new OpenAIClient(new Uri(openAiConfig.Endpoint), new AzureKeyCredential(openAiConfig.ApiKey), clientOptions);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddLogging(c => c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug));
+ builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.DeploymentOrModelId, openAIClient);
+ builder.Services.ConfigureHttpClientDefaults(c =>
+ {
+ c.AddStandardResilienceHandler().Configure(o =>
+ {
+ o.Retry.MaxRetryAttempts = 5;
+ o.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
+ });
+ });
+ return builder.Build();
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Properties/launchSettings.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Properties/launchSettings.json
new file mode 100644
index 0000000000..373d72522f
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:59668",
+ "sslPort": 44354
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5244",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7227;http://localhost:5244",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/AzureService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/AzureService.cs
new file mode 100644
index 0000000000..4ebead697a
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/AzureService.cs
@@ -0,0 +1,160 @@
+using System.Text;
+using Azure;
+using Azure.Core;
+using Azure.ResourceManager;
+using Azure.ResourceManager.ContainerInstance;
+using Azure.ResourceManager.ContainerInstance.Models;
+using Azure.ResourceManager.Resources;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Options;
+
+
+namespace Microsoft.AI.DevTeam;
+
+public class AzureService : IManageAzure
+{
+ private readonly AzureOptions _azSettings;
+ private readonly ILogger _logger;
+ private readonly ArmClient _client;
+
+ public AzureService(IOptions azOptions, ILogger logger, ArmClient client)
+ {
+ _azSettings = azOptions.Value;
+ _logger = logger;
+ _client = client;
+ }
+
+ public async Task DeleteSandbox(string sandboxId)
+ {
+ try
+ {
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ await containerGroup.Value.DeleteAsync(WaitUntil.Started);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error deleting sandbox");
+ throw;
+ }
+
+ }
+
+ public async Task IsSandboxCompleted(string sandboxId)
+ {
+ try
+ {
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ return containerGroup.Value.Data.ProvisioningState == "Succeeded"
+ && containerGroup.Value.Data.Containers.First().InstanceView.CurrentState.State == "Terminated";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error checking sandbox status");
+ throw;
+ }
+ }
+
+ public async Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber)
+ {
+ try
+ {
+ var runId = $"sk-sandbox-{org}-{repo}-{parentIssueNumber}-{issueNumber}".ToLower();
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = _client.GetResourceGroupResource(resourceGroupResourceId);
+ var scriptPath = $"/azfiles/output/{org}-{repo}/{parentIssueNumber}/{issueNumber}/run.sh";
+ var collection = resourceGroupResource.GetContainerGroups();
+ var data = new ContainerGroupData(new AzureLocation(_azSettings.Location), new ContainerInstanceContainer[]
+ {
+ new ContainerInstanceContainer(runId,_azSettings.SandboxImage,new ContainerResourceRequirements(new ContainerResourceRequestsContent(1.5,1)))
+ {
+ Command = { "/bin/bash", $"{scriptPath}" },
+ VolumeMounts =
+ {
+ new ContainerVolumeMount("azfiles","/azfiles/")
+ {
+ IsReadOnly = false,
+ }
+ },
+ }}, ContainerInstanceOperatingSystemType.Linux)
+ {
+ Volumes =
+ {
+ new ContainerVolume("azfiles")
+ {
+ AzureFile = new ContainerInstanceAzureFileVolume(_azSettings.FilesShareName,_azSettings.FilesAccountName)
+ {
+ StorageAccountKey = _azSettings.FilesAccountKey
+ },
+ },
+ },
+ RestartPolicy = ContainerGroupRestartPolicy.Never,
+ Sku = ContainerGroupSku.Standard,
+ Priority = ContainerGroupPriority.Regular
+ };
+ await collection.CreateOrUpdateAsync(WaitUntil.Completed, runId, data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error running sandbox");
+ throw;
+ }
+
+ }
+
+ public async Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output)
+ {
+ try
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+ var parentDirName = $"{dir}/{org}-{repo}";
+
+ var fileName = $"{filename}.{extension}";
+
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ await share.CreateIfNotExistsAsync();
+ await share.GetDirectoryClient($"{dir}").CreateIfNotExistsAsync(); ;
+
+ var parentDir = share.GetDirectoryClient(parentDirName);
+ await parentDir.CreateIfNotExistsAsync();
+
+ var parentIssueDir = parentDir.GetSubdirectoryClient($"{parentIssueNumber}");
+ await parentIssueDir.CreateIfNotExistsAsync();
+
+ var directory = parentIssueDir.GetSubdirectoryClient($"{issueNumber}");
+ await directory.CreateIfNotExistsAsync();
+
+ var file = directory.GetFileClient(fileName);
+ // hack to enable script to save files in the same directory
+ var cwdHack = "#!/bin/bash\n cd $(dirname $0)";
+ var contents = extension == "sh" ? output.Replace("#!/bin/bash", cwdHack) : output;
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents)))
+ {
+ await file.CreateAsync(stream.Length);
+ await file.UploadRangeAsync(
+ new HttpRange(0, stream.Length),
+ stream);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error storing output");
+ throw;
+ }
+ }
+}
+
+public interface IManageAzure
+{
+ Task Store(string org, string repo, long parentIssueNumber, long issueNumber, string filename, string extension, string dir, string output);
+ Task RunInSandbox(string org, string repo, long parentIssueNumber, long issueNumber);
+ Task IsSandboxCompleted(string sandboxId);
+ Task DeleteSandbox(string sandboxId);
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs
new file mode 100644
index 0000000000..a56e9f5e5e
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs
@@ -0,0 +1,53 @@
+using System.Text;
+using System.Text.Json;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AI.DevTeam;
+
+public interface IAnalyzeCode
+{
+ Task> Analyze(string content);
+}
+public class CodeAnalyzer : IAnalyzeCode
+{
+ private readonly ServiceOptions _serviceOptions;
+ private readonly HttpClient _httpClient;
+ private readonly ILogger _logger;
+
+ public CodeAnalyzer(IOptions serviceOptions, HttpClient httpClient, ILogger logger)
+ {
+ _serviceOptions = serviceOptions.Value;
+ _httpClient = httpClient;
+ _logger = logger;
+ _httpClient.BaseAddress = new Uri(_serviceOptions.IngesterUrl);
+
+ }
+ public async Task> Analyze(string content)
+ {
+ try
+ {
+ var request = new CodeAnalysisRequest { Content = content };
+ var body = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
+ var response = await _httpClient.PostAsync("api/AnalyzeCode", body);
+ var stringResult = await response.Content.ReadAsStringAsync();
+ var result = JsonSerializer.Deserialize>(stringResult);
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error analyzing code");
+ return Enumerable.Empty();
+ }
+ }
+}
+
+public class CodeAnalysisRequest
+{
+ public string Content { get; set; }
+}
+
+public class CodeAnalysis
+{
+ public string Meaning { get; set; }
+ public string CodeBlock { get; set; }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubAuthService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubAuthService.cs
new file mode 100644
index 0000000000..0c964d9dba
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubAuthService.cs
@@ -0,0 +1,68 @@
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Security.Cryptography;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using Octokit;
+
+namespace Microsoft.AI.DevTeam;
+public class GithubAuthService
+{
+ private readonly GithubOptions _githubSettings;
+ private readonly ILogger _logger;
+
+ public GithubAuthService(IOptions ghOptions, ILogger logger)
+ {
+ _githubSettings = ghOptions.Value;
+ _logger = logger;
+ }
+
+ public string GenerateJwtToken(string appId, string appKey, int minutes)
+ {
+ using var rsa = RSA.Create();
+ rsa.ImportFromPem(appKey);
+ var securityKey = new RsaSecurityKey(rsa);
+
+ var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);
+
+ var now = DateTime.UtcNow;
+ var iat = new DateTimeOffset(now).ToUnixTimeSeconds();
+ var exp = new DateTimeOffset(now.AddMinutes(minutes)).ToUnixTimeSeconds();
+
+ var claims = new[] {
+ new Claim(JwtRegisteredClaimNames.Iat, iat.ToString(), ClaimValueTypes.Integer64),
+ new Claim(JwtRegisteredClaimNames.Exp, exp.ToString(), ClaimValueTypes.Integer64)
+ };
+
+ var token = new JwtSecurityToken(
+ issuer: appId,
+ claims: claims,
+ expires: DateTime.Now.AddMinutes(10),
+ signingCredentials: credentials
+ );
+
+ return new JwtSecurityTokenHandler().WriteToken(token);
+ }
+
+ public GitHubClient GetGitHubClient()
+ {
+ try
+ {
+ var jwtToken = GenerateJwtToken(_githubSettings.AppId.ToString(), _githubSettings.AppKey, 10);
+ var appClient = new GitHubClient(new ProductHeaderValue("SK-DEV-APP"))
+ {
+ Credentials = new Credentials(jwtToken, AuthenticationType.Bearer)
+ };
+ var response = appClient.GitHubApps.CreateInstallationToken(_githubSettings.InstallationId).Result;
+ return new GitHubClient(new ProductHeaderValue($"SK-DEV-APP-Installation{_githubSettings.InstallationId}"))
+ {
+ Credentials = new Credentials(response.Token)
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting GitHub client");
+ throw;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubService.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubService.cs
new file mode 100644
index 0000000000..7fba648091
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubService.cs
@@ -0,0 +1,245 @@
+using System.Text;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Options;
+using Octokit;
+using Octokit.Helpers;
+
+
+namespace Microsoft.AI.DevTeam;
+
+public class GithubService : IManageGithub
+{
+ private readonly GitHubClient _ghClient;
+ private readonly AzureOptions _azSettings;
+ private readonly ILogger _logger;
+ private readonly HttpClient _httpClient;
+
+ public GithubService(IOptions azOptions, GitHubClient ghClient, ILogger logger, HttpClient httpClient)
+ {
+ _ghClient = ghClient;
+ _azSettings = azOptions.Value;
+ _logger = logger;
+ _httpClient = httpClient;
+ }
+
+ public async Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch)
+ {
+ try
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+
+ var dirName = $"{rootDir}/{org}-{repo}/{parentNumber}/{issueNumber}";
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ var directory = share.GetDirectoryClient(dirName);
+
+ var remaining = new Queue();
+ remaining.Enqueue(directory);
+ while (remaining.Count > 0)
+ {
+ var dir = remaining.Dequeue();
+ await foreach (var item in dir.GetFilesAndDirectoriesAsync())
+ {
+ if (!item.IsDirectory && item.Name != "run.sh") // we don't want the generated script in the PR
+ {
+ try
+ {
+ var file = dir.GetFileClient(item.Name);
+ var filePath = file.Path.Replace($"{_azSettings.FilesShareName}/", "")
+ .Replace($"{dirName}/", "");
+ var fileStream = await file.OpenReadAsync();
+ using (var reader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ var value = reader.ReadToEnd();
+
+ try
+ {
+ // Check if the file exists
+ var existingFiles = await _ghClient.Repository.Content.GetAllContentsByRef(org, repo, filePath, branch);
+ var existingFile = existingFiles.First();
+ // If the file exists, update it
+ var updateChangeSet = await _ghClient.Repository.Content.UpdateFile(
+ org, repo, filePath,
+ new UpdateFileRequest("Updated file via AI", value, existingFile.Sha, branch)); // TODO: add more meaningful commit message
+ }
+ catch (NotFoundException)
+ {
+ // If the file doesn't exist, create it
+ var createChangeSet = await _ghClient.Repository.Content.CreateFile(
+ org, repo, filePath,
+ new CreateFileRequest("Created file via AI", value, branch)); // TODO: add more meaningful commit message
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"Error while uploading file {item.Name}");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"Error while uploading file {item.Name}");
+ }
+ }
+ else if (item.IsDirectory)
+ {
+ remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error committing to branch");
+ throw;
+ }
+ }
+
+ public async Task CreateBranch(string org, string repo, string branch)
+ {
+ try
+ {
+ var ghRepo = await _ghClient.Repository.Get(org, repo);
+ var contents = await _ghClient.Repository.Content.GetAllContents(org, repo);
+ if (!contents.Any())
+ {
+ // Create a new file and commit it to the repository
+ var createChangeSet = await _ghClient.Repository.Content.CreateFile(
+ org,
+ repo,
+ "README.md",
+ new CreateFileRequest("Initial commit", "# Readme")
+ );
+ }
+ await _ghClient.Git.Reference.CreateBranch(org, repo, branch, ghRepo.DefaultBranch);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating branch");
+ throw;
+ }
+ }
+
+ public async Task GetMainLanguage(string org, string repo)
+ {
+ try
+ {
+ var languages = await _ghClient.Repository.GetAllLanguages(org, repo);
+ var mainLanguage = languages.OrderByDescending(l => l.NumberOfBytes).First();
+ return mainLanguage.Name;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting main language");
+ throw;
+ }
+ }
+
+ public async Task CreateIssue(string org, string repo, string input, string function, long parentNumber)
+ {
+ try
+ {
+ var newIssue = new NewIssue($"{function} chain for #{parentNumber}")
+ {
+ Body = input,
+ };
+ newIssue.Labels.Add(function);
+ newIssue.Labels.Add($"Parent.{parentNumber}");
+ var issue = await _ghClient.Issue.Create(org, repo, newIssue);
+ return issue.Number;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating issue");
+ throw;
+ }
+ }
+
+ public async Task CreatePR(string org, string repo, long number, string branch)
+ {
+ try
+ {
+ var ghRepo = await _ghClient.Repository.Get(org, repo);
+ await _ghClient.PullRequest.Create(org, repo, new NewPullRequest($"New app #{number}", branch, ghRepo.DefaultBranch));
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error creating PR");
+ throw;
+ }
+ }
+
+ public async Task PostComment(string org, string repo, long issueNumber, string comment)
+ {
+ try
+ {
+ await _ghClient.Issue.Comment.Create(org, repo, (int)issueNumber, comment);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error posting comment");
+ throw;
+ }
+ }
+
+ public async Task> GetFiles(string org, string repo, string branch, Func filter)
+ {
+ try
+ {
+ var items = await _ghClient.Repository.Content.GetAllContentsByRef(org, repo, branch);
+ return await CollectFiles(org, repo, branch, items, filter);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting files");
+ throw;
+ }
+ }
+
+ private async Task> CollectFiles(string org, string repo, string branch, IReadOnlyList items, Func filter)
+ {
+ try
+ {
+ var result = new List();
+ foreach (var item in items)
+ {
+ if (item.Type == ContentType.File && filter(item))
+ {
+ var content = await _httpClient.GetStringAsync(item.DownloadUrl);
+ result.Add(new FileResponse
+ {
+ Name = item.Name,
+ Content = content
+ });
+ }
+ else if (item.Type == ContentType.Dir)
+ {
+ var subItems = await _ghClient.Repository.Content.GetAllContentsByRef(org, repo, item.Path, branch);
+ result.AddRange(await CollectFiles(org, repo, branch, subItems, filter));
+ }
+ }
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error collecting files");
+ throw;
+ }
+ }
+}
+
+public class FileResponse
+{
+ public string Name { get; set; }
+ public string Content { get; set; }
+}
+
+public interface IManageGithub
+{
+ Task CreateIssue(string org, string repo, string input, string function, long parentNumber);
+ Task CreatePR(string org, string repo, long number, string branch);
+ Task CreateBranch(string org, string repo, string branch);
+ Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch);
+
+ Task PostComment(string org, string repo, long issueNumber, string comment);
+ Task> GetFiles(string org, string repo, string branch, Func filter);
+ Task GetMainLanguage(string org, string repo);
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubWebHookProcessor.cs b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubWebHookProcessor.cs
new file mode 100644
index 0000000000..4cda392496
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/Services/GithubWebHookProcessor.cs
@@ -0,0 +1,180 @@
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.DevTeam.Events;
+using Octokit.Webhooks;
+using Octokit.Webhooks.Events;
+using Octokit.Webhooks.Events.IssueComment;
+using Octokit.Webhooks.Events.Issues;
+using Octokit.Webhooks.Models;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.DevTeam;
+public sealed class GithubWebHookProcessor : WebhookEventProcessor
+{
+ private readonly ILogger _logger;
+ private readonly IClusterClient _client;
+
+ public GithubWebHookProcessor(ILogger logger,
+ IClusterClient client, IManageGithub ghService, IManageAzure azService)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _client = client ?? throw new ArgumentNullException(nameof(client));
+ }
+
+ protected override async Task ProcessIssuesWebhookAsync(WebhookHeaders headers, IssuesEvent issuesEvent, IssuesAction action)
+ {
+ try
+ {
+ ArgumentNullException.ThrowIfNull(headers, nameof(headers));
+ ArgumentNullException.ThrowIfNull(issuesEvent, nameof(issuesEvent));
+ ArgumentNullException.ThrowIfNull(action, nameof(action));
+
+ _logger.LogInformation("Processing issue event");
+ var org = issuesEvent.Repository?.Owner.Login ?? throw new InvalidOperationException("Repository owner login is null");
+ var repo = issuesEvent.Repository?.Name ?? throw new InvalidOperationException("Repository name is null");
+ var issueNumber = issuesEvent.Issue?.Number ?? throw new InvalidOperationException("Issue number is null");
+ var input = issuesEvent.Issue?.Body ?? string.Empty;
+ // Assumes the label follows the following convention: Skill.Function example: PM.Readme
+ // Also, we've introduced the Parent label, that ties the sub-issue with the parent issue
+ var labels = issuesEvent.Issue?.Labels
+ .Select(l => l.Name.Split('.'))
+ .Where(parts => parts.Length == 2)
+ .ToDictionary(parts => parts[0], parts => parts[1]);
+ if (labels == null || labels.Count == 0)
+ {
+ _logger.LogWarning("No labels found in issue. Skipping processing.");
+ return;
+ }
+
+ long? parentNumber = labels.TryGetValue("Parent", out string? value) ? long.Parse(value) : null;
+ var skillName = labels.Keys.Where(k => k != "Parent").FirstOrDefault();
+
+ if (skillName == null)
+ {
+ _logger.LogWarning("No skill name found in issue. Skipping processing.");
+ return;
+ }
+
+ var suffix = $"{org}-{repo}";
+ if (issuesEvent.Action == IssuesAction.Opened)
+ {
+ _logger.LogInformation("Processing HandleNewAsk");
+ await HandleNewAsk(issueNumber, parentNumber, skillName, labels[skillName], suffix, input, org, repo);
+ }
+ else if (issuesEvent.Action == IssuesAction.Closed && issuesEvent.Issue?.User.Type.Value == UserType.Bot)
+ {
+ _logger.LogInformation("Processing HandleClosingIssue");
+ await HandleClosingIssue(issueNumber, parentNumber, skillName, labels[skillName], suffix, org, repo);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Processing issue event");
+ throw;
+ }
+ }
+
+ protected override async Task ProcessIssueCommentWebhookAsync(
+ WebhookHeaders headers,
+ IssueCommentEvent issueCommentEvent,
+ IssueCommentAction action)
+ {
+ try
+ {
+ _logger.LogInformation("Processing issue comment event");
+ var org = issueCommentEvent.Repository.Owner.Login;
+ var repo = issueCommentEvent.Repository.Name;
+ var issueNumber = issueCommentEvent.Issue.Number;
+ var input = issueCommentEvent.Comment.Body;
+ // Assumes the label follows the following convention: Skill.Function example: PM.Readme
+ var labels = issueCommentEvent.Issue.Labels
+ .Select(l => l.Name.Split('.'))
+ .Where(parts => parts.Length == 2)
+ .ToDictionary(parts => parts[0], parts => parts[1]);
+ var skillName = labels.Keys.Where(k => k != "Parent").FirstOrDefault();
+ long? parentNumber = labels.ContainsKey("Parent") ? long.Parse(labels["Parent"]) : null;
+ var suffix = $"{org}-{repo}";
+ // we only respond to non-bot comments
+ if (issueCommentEvent.Sender.Type.Value != UserType.Bot)
+ {
+ await HandleNewAsk(issueNumber, parentNumber, skillName, labels[skillName], suffix, input, org, repo);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Processing issue comment event");
+ throw;
+ }
+
+ }
+
+ private async Task HandleClosingIssue(long issueNumber, long? parentNumber, string skillName, string functionName, string suffix, string org, string repo)
+ {
+ var subject = suffix+issueNumber.ToString();
+ var streamProvider = _client.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Consts.MainNamespace, subject);
+ var stream = streamProvider.GetStream(streamId);
+ var eventType = (skillName, functionName) switch
+ {
+ ("PM", "Readme") => nameof(GithubFlowEventType.ReadmeChainClosed),
+ ("DevLead", "Plan") => nameof(GithubFlowEventType.DevPlanChainClosed),
+ ("Developer", "Implement") => nameof(GithubFlowEventType.CodeChainClosed),
+ _ => nameof(GithubFlowEventType.NewAsk)
+ };
+ var data = new Dictionary
+ {
+ { "org", org },
+ { "repo", repo },
+ { "issueNumber", issueNumber.ToString() },
+ { "parentNumber", parentNumber?.ToString()}
+ };
+
+ await stream.OnNextAsync(new Event
+ {
+ Type = eventType,
+ Subject = subject,
+ Data = data
+ });
+ }
+
+ private async Task HandleNewAsk(long issueNumber, long? parentNumber, string skillName, string functionName, string suffix, string input, string org, string repo)
+ {
+ try
+ {
+ _logger.LogInformation("Handling new ask");
+ var subject = suffix+issueNumber.ToString();
+ var streamProvider = _client.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Consts.MainNamespace, subject);
+ var stream = streamProvider.GetStream(streamId);
+
+ var eventType = (skillName, functionName) switch
+ {
+ ("Do", "It") => nameof(GithubFlowEventType.NewAsk),
+ ("PM", "Readme") => nameof(GithubFlowEventType.ReadmeRequested),
+ ("DevLead", "Plan") => nameof(GithubFlowEventType.DevPlanRequested),
+ ("Developer", "Implement") => nameof(GithubFlowEventType.CodeGenerationRequested),
+ _ => nameof(GithubFlowEventType.NewAsk)
+ };
+ var data = new Dictionary
+ {
+ { "org", org },
+ { "repo", repo },
+ { "issueNumber", issueNumber.ToString() },
+ { "parentNumber", parentNumber?.ToString()},
+ { "input", input}
+
+ };
+ await stream.OnNextAsync(new Event
+ {
+ Type = eventType,
+ Subject = subject,
+ Data = data
+ });
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Handling new ask");
+ throw;
+ }
+ }
+}
+
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.azure.template.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.azure.template.json
new file mode 100644
index 0000000000..5ba1103512
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.azure.template.json
@@ -0,0 +1,46 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Information",
+ "Orleans.Streams": "Information"
+ }
+ },
+ "ApplicationInsights": {
+ "ConnectionString": ""
+ },
+ "AllowedHosts": "*",
+ "SANDBOX_IMAGE" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "GithubOptions" : {
+ "AppKey": "",
+ "AppId": "",
+ "InstallationId": "",
+ "WebhookSecret": ""
+ },
+ "AzureOptions" : {
+ "SubscriptionId":"",
+ "Location":"",
+ "ContainerInstancesResourceGroup":"",
+ "FilesShareName":"",
+ "FilesAccountName":"",
+ "FilesAccountKey":"",
+ "SandboxImage" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "ManagedIdentity": "",
+ "CosmosConnectionString":""
+ },
+ "OpenAIOptions" : {
+ "ServiceType":"AzureOpenAI",
+ "ServiceId":"gpt-4",
+ "DeploymentOrModelId":"gpt-4",
+ "EmbeddingDeploymentOrModelId":"text-embedding-ada-002",
+ "Endpoint":"",
+ "ApiKey":""
+ },
+ "QdrantOptions" : {
+ "Endpoint" : "http://qdrant:6333",
+ "VectorSize" : "1536"
+ },
+ "ServiceOptions" : {
+ "IngesterUrl" : "http://localhost:7071"
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.local.template.json b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.local.template.json
new file mode 100644
index 0000000000..26563297ae
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/Microsoft.AI.DevTeam/appsettings.local.template.json
@@ -0,0 +1,45 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Information",
+ "Orleans.Streams": "Information"
+ }
+ },
+ "ApplicationInsights": {
+ "ConnectionString": ""
+ },
+ "AllowedHosts": "*",
+ "SANDBOX_IMAGE" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "GithubOptions" : {
+ "AppKey": "",
+ "AppId": "",
+ "InstallationId": "",
+ "WebhookSecret": ""
+ },
+ "AzureOptions" : {
+ "SubscriptionId":"",
+ "Location":"",
+ "ContainerInstancesResourceGroup":"",
+ "FilesShareName":"",
+ "FilesAccountName":"",
+ "FilesAccountKey":"",
+ "SandboxImage" : "mcr.microsoft.com/dotnet/sdk:7.0",
+ "ManagedIdentity": ""
+ },
+ "OpenAIOptions" : {
+ "ServiceType":"AzureOpenAI",
+ "ServiceId":"gpt-4",
+ "DeploymentOrModelId":"gpt-4",
+ "EmbeddingDeploymentOrModelId":"text-embedding-ada-002",
+ "Endpoint":"",
+ "ApiKey":""
+ },
+ "QdrantOptions" : {
+ "Endpoint" : "http://qdrant:6333",
+ "VectorSize" : "1536"
+ },
+ "ServiceOptions" : {
+ "IngesterUrl" : "http://localhost:7071"
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/seed-memory/Dockerfile b/dotnet/samples/gh-flow/src/seed-memory/Dockerfile
new file mode 100644
index 0000000000..dab5c94abb
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base
+WORKDIR /app
+
+FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+WORKDIR /src
+COPY ["util/seed-memory/seed-memory.csproj", "util/seed-memory/"]
+RUN dotnet restore "util/seed-memory/seed-memory.csproj"
+COPY . .
+WORKDIR "/src/util/seed-memory"
+RUN dotnet build "seed-memory.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "seed-memory.csproj" -c Release -o /app/publish /p:UseAppHost=false
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "seed-memory.dll"]
diff --git a/dotnet/samples/gh-flow/src/seed-memory/Program.cs b/dotnet/samples/gh-flow/src/seed-memory/Program.cs
new file mode 100644
index 0000000000..1a557aaafb
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/Program.cs
@@ -0,0 +1,57 @@
+using System.Reflection;
+using Microsoft.Extensions.Logging;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.Connectors.Qdrant;
+using Microsoft.SemanticKernel.Memory;
+using UglyToad.PdfPig;
+using UglyToad.PdfPig.DocumentLayoutAnalysis.TextExtractor;
+
+class Program
+{
+ static string WafFileName = "azure-well-architected.pdf";
+ static async Task Main(string[] args)
+ {
+ var kernelSettings = KernelSettings.LoadSettings();
+
+ using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
+ {
+ builder
+ .SetMinimumLevel(kernelSettings.LogLevel ?? LogLevel.Warning)
+ .AddConsole()
+ .AddDebug();
+ });
+
+ var memoryBuilder = new MemoryBuilder();
+ var memory = memoryBuilder.WithLoggerFactory(loggerFactory)
+ .WithQdrantMemoryStore(kernelSettings.QdrantEndpoint, 1536)
+ .WithAzureOpenAITextEmbeddingGeneration(kernelSettings.EmbeddingDeploymentOrModelId,kernelSettings.Endpoint, kernelSettings.ApiKey)
+ .Build();
+
+ await ImportDocumentAsync(memory, WafFileName);
+ }
+
+ public static async Task ImportDocumentAsync(ISemanticTextMemory memory, string filename)
+ {
+ var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ var filePath = Path.Combine(currentDirectory, filename);
+ using var pdfDocument = PdfDocument.Open(File.OpenRead(filePath));
+ var pages = pdfDocument.GetPages();
+ foreach (var page in pages)
+ {
+ try
+ {
+ var text = ContentOrderTextExtractor.GetText(page);
+ var descr = text.Take(100);
+ await memory.SaveInformationAsync(
+ collection: "waf",
+ text: text,
+ id: $"{Guid.NewGuid()}",
+ description: $"Document: {descr}");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/seed-memory/README.md b/dotnet/samples/gh-flow/src/seed-memory/README.md
new file mode 100644
index 0000000000..f87f5c14cb
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/README.md
@@ -0,0 +1 @@
+# TODO
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/seed-memory/azure-well-architected.pdf b/dotnet/samples/gh-flow/src/seed-memory/azure-well-architected.pdf
new file mode 100644
index 0000000000..25dfc501a5
Binary files /dev/null and b/dotnet/samples/gh-flow/src/seed-memory/azure-well-architected.pdf differ
diff --git a/dotnet/samples/gh-flow/src/seed-memory/config/KernelSettings.cs b/dotnet/samples/gh-flow/src/seed-memory/config/KernelSettings.cs
new file mode 100644
index 0000000000..18f956f50c
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/config/KernelSettings.cs
@@ -0,0 +1,97 @@
+using System.Text.Json.Serialization;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+internal class KernelSettings
+{
+ public const string DefaultConfigFile = "config/appsettings.json";
+ public const string OpenAI = "OPENAI";
+ public const string AzureOpenAI = "AZUREOPENAI";
+ public const string Qdrant = "QDRANT";
+
+ [JsonPropertyName("serviceType")]
+ public string ServiceType { get; set; } = string.Empty;
+
+ [JsonPropertyName("serviceId")]
+ public string ServiceId { get; set; } = string.Empty;
+
+ [JsonPropertyName("deploymentOrModelId")]
+ public string DeploymentOrModelId { get; set; } = string.Empty;
+ [JsonPropertyName("embeddingDeploymentOrModelId")]
+ public string EmbeddingDeploymentOrModelId { get; set; } = string.Empty;
+
+ [JsonPropertyName("endpoint")]
+ public string Endpoint { get; set; } = string.Empty;
+
+ [JsonPropertyName("apiKey")]
+ public string ApiKey { get; set; } = string.Empty;
+
+ [JsonPropertyName("orgId")]
+ public string OrgId { get; set; } = string.Empty;
+
+ [JsonPropertyName("qdrantEndpoint")]
+ public string QdrantEndpoint { get; set; } = string.Empty;
+
+ [JsonPropertyName("logLevel")]
+ public LogLevel? LogLevel { get; set; }
+
+ ///
+ /// Load the kernel settings from settings.json if the file exists and if not attempt to use user secrets.
+ ///
+ internal static KernelSettings LoadSettings()
+ {
+ try
+ {
+ if (File.Exists(DefaultConfigFile))
+ {
+ return FromFile(DefaultConfigFile);
+ }
+
+ Console.WriteLine($"Semantic kernel settings '{DefaultConfigFile}' not found, attempting to load configuration from user secrets.");
+
+ return FromUserSecrets();
+ }
+ catch (InvalidDataException ide)
+ {
+ Console.Error.WriteLine(
+ "Unable to load semantic kernel settings, please provide configuration settings using instructions in the README.\n" +
+ "Please refer to: https://github.com/microsoft/semantic-kernel-starters/blob/main/sk-csharp-hello-world/README.md#configuring-the-starter"
+ );
+ throw new InvalidOperationException(ide.Message);
+ }
+ }
+
+ ///
+ /// Load the kernel settings from the specified configuration file if it exists.
+ ///
+ internal static KernelSettings FromFile(string configFile = DefaultConfigFile)
+ {
+ if (!File.Exists(configFile))
+ {
+ throw new FileNotFoundException($"Configuration not found: {configFile}");
+ }
+
+ var configuration = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile(configFile, optional: true, reloadOnChange: true)
+ .AddEnvironmentVariables()
+ .Build();
+
+ return configuration.Get()
+ ?? throw new InvalidDataException($"Invalid semantic kernel settings in '{configFile}', please provide configuration settings using instructions in the README.");
+ }
+
+ ///
+ /// Load the kernel settings from user secrets.
+ ///
+ internal static KernelSettings FromUserSecrets()
+ {
+ var configuration = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+ return configuration.Get()
+ ?? throw new InvalidDataException("Invalid semantic kernel settings in user secrets, please provide configuration settings using instructions in the README.");
+ }
+}
diff --git a/dotnet/samples/gh-flow/src/seed-memory/config/appsettings.template.json b/dotnet/samples/gh-flow/src/seed-memory/config/appsettings.template.json
new file mode 100644
index 0000000000..a25ebd41a4
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/config/appsettings.template.json
@@ -0,0 +1,9 @@
+{
+ "serviceType": "AzureOpenAI",
+ "serviceId": "",
+ "deploymentOrModelId": "",
+ "embeddingDeploymentOrModelId": "",
+ "endpoint": "",
+ "apiKey": "",
+ "qdrantEndpoint": ""
+}
\ No newline at end of file
diff --git a/dotnet/samples/gh-flow/src/seed-memory/seed-memory.csproj b/dotnet/samples/gh-flow/src/seed-memory/seed-memory.csproj
new file mode 100644
index 0000000000..0b4a7046b4
--- /dev/null
+++ b/dotnet/samples/gh-flow/src/seed-memory/seed-memory.csproj
@@ -0,0 +1,30 @@
+
+
+
+ Exe
+ net8.0
+ waf_import
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
diff --git a/dotnet/samples/marketing/.gitignore b/dotnet/samples/marketing/.gitignore
new file mode 100644
index 0000000000..8e84380248
--- /dev/null
+++ b/dotnet/samples/marketing/.gitignore
@@ -0,0 +1 @@
+.azure
diff --git a/dotnet/samples/marketing/README.md b/dotnet/samples/marketing/README.md
new file mode 100644
index 0000000000..37e9baaf60
--- /dev/null
+++ b/dotnet/samples/marketing/README.md
@@ -0,0 +1,40 @@
+# [In progress] Marketing Saple application
+
+This is a demo application that showcase the different features of the AI Agent framework.
+There are five agents in this application that control the different areas of the UI autonomously.
+
+The agents are designed to be able to interact with each other and the user to achieve their goals.
+To do that each agent has
+
+![Agents](readme-media/screenshot.png)
+
+![Agents](readme-media/agents.png)
+
+## Requirements to run locally
+### Frontend
+The latest version of Node.js and npm
+
+### Backend
+Visual Studio or Visual Studio code and the latest version of dotnet
+
+## Running with azd
+To run the application with azd, you need to have the azd cli installed. You can install it following the instructions here:
+
+https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd?tabs=winget-windows%2Cbrew-mac%2Cscript-linux
+
+
+
+Then you can run the following command to start the application:
+```powers
+
+## How to run the application locally
+
+Execute Run.ps1. IF you are missing the config file the script will create an empty one for you and ask you to fill it out.
+```
+.\run.ps1
+```
+
+## How to debug the application locally
+To debug the backend, you can simply open the solution in Visual Studio, and press F5 to start debugging.
+Remember to copy `appsettings.local.template.json` to `appsettings.json` and fill out the values.
+The frontend is a NodeJS React application. You can debug it using Visual Studio code.
\ No newline at end of file
diff --git a/dotnet/samples/marketing/azure.yaml b/dotnet/samples/marketing/azure.yaml
new file mode 100644
index 0000000000..5f5888574d
--- /dev/null
+++ b/dotnet/samples/marketing/azure.yaml
@@ -0,0 +1,20 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
+
+name: marketing
+metadata:
+ template: azd-init@1.8.2
+services:
+ backend:
+ project: "src/backend"
+ host: containerapp
+ language: dotnet
+ docker:
+ path: Dockerfile
+ context: ../../../../
+ frontend:
+ project: "src/frontend"
+ host: containerapp
+ language: ts
+ dist: build
+ docker:
+ path: Dockerfile
diff --git a/dotnet/samples/marketing/infra/abbreviations.json b/dotnet/samples/marketing/infra/abbreviations.json
new file mode 100644
index 0000000000..dc62141f9d
--- /dev/null
+++ b/dotnet/samples/marketing/infra/abbreviations.json
@@ -0,0 +1,135 @@
+{
+ "analysisServicesServers": "as",
+ "apiManagementService": "apim-",
+ "appConfigurationStores": "appcs-",
+ "appManagedEnvironments": "cae-",
+ "appContainerApps": "ca-",
+ "authorizationPolicyDefinitions": "policy-",
+ "automationAutomationAccounts": "aa-",
+ "blueprintBlueprints": "bp-",
+ "blueprintBlueprintsArtifacts": "bpa-",
+ "cacheRedis": "redis-",
+ "cdnProfiles": "cdnp-",
+ "cdnProfilesEndpoints": "cdne-",
+ "cognitiveServicesAccounts": "cog-",
+ "cognitiveServicesFormRecognizer": "cog-fr-",
+ "cognitiveServicesTextAnalytics": "cog-ta-",
+ "computeAvailabilitySets": "avail-",
+ "computeCloudServices": "cld-",
+ "computeDiskEncryptionSets": "des",
+ "computeDisks": "disk",
+ "computeDisksOs": "osdisk",
+ "computeGalleries": "gal",
+ "computeSnapshots": "snap-",
+ "computeVirtualMachines": "vm",
+ "computeVirtualMachineScaleSets": "vmss-",
+ "containerInstanceContainerGroups": "ci",
+ "containerRegistryRegistries": "cr",
+ "containerServiceManagedClusters": "aks-",
+ "databricksWorkspaces": "dbw-",
+ "dataFactoryFactories": "adf-",
+ "dataLakeAnalyticsAccounts": "dla",
+ "dataLakeStoreAccounts": "dls",
+ "dataMigrationServices": "dms-",
+ "dBforMySQLServers": "mysql-",
+ "dBforPostgreSQLServers": "psql-",
+ "devicesIotHubs": "iot-",
+ "devicesProvisioningServices": "provs-",
+ "devicesProvisioningServicesCertificates": "pcert-",
+ "documentDBDatabaseAccounts": "cosmos-",
+ "eventGridDomains": "evgd-",
+ "eventGridDomainsTopics": "evgt-",
+ "eventGridEventSubscriptions": "evgs-",
+ "eventHubNamespaces": "evhns-",
+ "eventHubNamespacesEventHubs": "evh-",
+ "hdInsightClustersHadoop": "hadoop-",
+ "hdInsightClustersHbase": "hbase-",
+ "hdInsightClustersKafka": "kafka-",
+ "hdInsightClustersMl": "mls-",
+ "hdInsightClustersSpark": "spark-",
+ "hdInsightClustersStorm": "storm-",
+ "hybridComputeMachines": "arcs-",
+ "insightsActionGroups": "ag-",
+ "insightsComponents": "appi-",
+ "keyVaultVaults": "kv-",
+ "kubernetesConnectedClusters": "arck",
+ "kustoClusters": "dec",
+ "kustoClustersDatabases": "dedb",
+ "logicIntegrationAccounts": "ia-",
+ "logicWorkflows": "logic-",
+ "machineLearningServicesWorkspaces": "mlw-",
+ "managedIdentityUserAssignedIdentities": "id-",
+ "managementManagementGroups": "mg-",
+ "migrateAssessmentProjects": "migr-",
+ "networkApplicationGateways": "agw-",
+ "networkApplicationSecurityGroups": "asg-",
+ "networkAzureFirewalls": "afw-",
+ "networkBastionHosts": "bas-",
+ "networkConnections": "con-",
+ "networkDnsZones": "dnsz-",
+ "networkExpressRouteCircuits": "erc-",
+ "networkFirewallPolicies": "afwp-",
+ "networkFirewallPoliciesWebApplication": "waf",
+ "networkFirewallPoliciesRuleGroups": "wafrg",
+ "networkFrontDoors": "fd-",
+ "networkFrontdoorWebApplicationFirewallPolicies": "fdfp-",
+ "networkLoadBalancersExternal": "lbe-",
+ "networkLoadBalancersInternal": "lbi-",
+ "networkLoadBalancersInboundNatRules": "rule-",
+ "networkLocalNetworkGateways": "lgw-",
+ "networkNatGateways": "ng-",
+ "networkNetworkInterfaces": "nic-",
+ "networkNetworkSecurityGroups": "nsg-",
+ "networkNetworkSecurityGroupsSecurityRules": "nsgsr-",
+ "networkNetworkWatchers": "nw-",
+ "networkPrivateDnsZones": "pdnsz-",
+ "networkPrivateLinkServices": "pl-",
+ "networkPublicIPAddresses": "pip-",
+ "networkPublicIPPrefixes": "ippre-",
+ "networkRouteFilters": "rf-",
+ "networkRouteTables": "rt-",
+ "networkRouteTablesRoutes": "udr-",
+ "networkTrafficManagerProfiles": "traf-",
+ "networkVirtualNetworkGateways": "vgw-",
+ "networkVirtualNetworks": "vnet-",
+ "networkVirtualNetworksSubnets": "snet-",
+ "networkVirtualNetworksVirtualNetworkPeerings": "peer-",
+ "networkVirtualWans": "vwan-",
+ "networkVpnGateways": "vpng-",
+ "networkVpnGatewaysVpnConnections": "vcn-",
+ "networkVpnGatewaysVpnSites": "vst-",
+ "notificationHubsNamespaces": "ntfns-",
+ "notificationHubsNamespacesNotificationHubs": "ntf-",
+ "operationalInsightsWorkspaces": "log-",
+ "portalDashboards": "dash-",
+ "powerBIDedicatedCapacities": "pbi-",
+ "purviewAccounts": "pview-",
+ "recoveryServicesVaults": "rsv-",
+ "resourcesResourceGroups": "rg-",
+ "searchSearchServices": "srch-",
+ "serviceBusNamespaces": "sb-",
+ "serviceBusNamespacesQueues": "sbq-",
+ "serviceBusNamespacesTopics": "sbt-",
+ "serviceEndPointPolicies": "se-",
+ "serviceFabricClusters": "sf-",
+ "signalRServiceSignalR": "sigr",
+ "sqlManagedInstances": "sqlmi-",
+ "sqlServers": "sql-",
+ "sqlServersDataWarehouse": "sqldw-",
+ "sqlServersDatabases": "sqldb-",
+ "sqlServersDatabasesStretch": "sqlstrdb-",
+ "storageStorageAccounts": "st",
+ "storageStorageAccountsVm": "stvm",
+ "storSimpleManagers": "ssimp",
+ "streamAnalyticsCluster": "asa-",
+ "synapseWorkspaces": "syn",
+ "synapseWorkspacesAnalyticsWorkspaces": "synw",
+ "synapseWorkspacesSqlPoolsDedicated": "syndp",
+ "synapseWorkspacesSqlPoolsSpark": "synsp",
+ "timeSeriesInsightsEnvironments": "tsi-",
+ "webServerFarms": "plan-",
+ "webSitesAppService": "app-",
+ "webSitesAppServiceEnvironment": "ase-",
+ "webSitesFunctions": "func-",
+ "webStaticSites": "stapp-"
+}
diff --git a/dotnet/samples/marketing/infra/app/backend.bicep b/dotnet/samples/marketing/infra/app/backend.bicep
new file mode 100644
index 0000000000..8f36a473a3
--- /dev/null
+++ b/dotnet/samples/marketing/infra/app/backend.bicep
@@ -0,0 +1,133 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param identityName string
+param containerRegistryName string
+param containerAppsEnvironmentName string
+param applicationInsightsName string
+param allowedOrigins array
+param exists bool
+@secure()
+param appDefinition object
+
+var appSettingsArray = filter(array(appDefinition.settings), i => i.name != '')
+var secrets = map(filter(appSettingsArray, i => i.?secret != null), i => {
+ name: i.name
+ value: i.value
+ secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32)
+})
+var env = map(filter(appSettingsArray, i => i.?secret == null), i => {
+ name: i.name
+ value: i.value
+})
+
+resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
+ name: identityName
+ location: location
+}
+
+resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = {
+ name: containerRegistryName
+}
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' existing = {
+ name: containerAppsEnvironmentName
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
+ name: applicationInsightsName
+}
+
+resource acrPullRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: containerRegistry
+ name: guid(subscription().id, resourceGroup().id, identity.id, 'acrPullRole')
+ properties: {
+ roleDefinitionId: subscriptionResourceId(
+ 'Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
+ principalType: 'ServicePrincipal'
+ principalId: identity.properties.principalId
+ }
+}
+
+module fetchLatestImage '../modules/fetch-container-image.bicep' = {
+ name: '${name}-fetch-image'
+ params: {
+ exists: exists
+ name: name
+ }
+}
+
+resource app 'Microsoft.App/containerApps@2023-05-02-preview' = {
+ name: name
+ location: location
+ tags: union(tags, {'azd-service-name': 'backend' })
+ dependsOn: [ acrPullRole ]
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: { '${identity.id}': {} }
+ }
+ properties: {
+ managedEnvironmentId: containerAppsEnvironment.id
+ configuration: {
+ ingress: {
+ external: true
+ targetPort: 5244
+ transport: 'auto'
+ corsPolicy: {
+ allowedOrigins: union(allowedOrigins, [
+ // define additional allowed origins here
+ ])
+ }
+ }
+ registries: [
+ {
+ server: '${containerRegistryName}.azurecr.io'
+ identity: identity.id
+ }
+ ]
+ secrets: union([
+ ],
+ map(secrets, secret => {
+ name: secret.secretRef
+ value: secret.value
+ }))
+ }
+ template: {
+ containers: [
+ {
+ image: fetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
+ name: 'main'
+ env: union([
+ {
+ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
+ value: applicationInsights.properties.ConnectionString
+ }
+ {
+ name: 'PORT'
+ value: '5244'
+ }
+ ],
+ env,
+ map(secrets, secret => {
+ name: secret.name
+ secretRef: secret.secretRef
+ }))
+ resources: {
+ cpu: json('1.0')
+ memory: '2.0Gi'
+ }
+ }
+ ]
+ scale: {
+ minReplicas: 1
+ maxReplicas: 10
+ }
+ }
+ }
+}
+
+output defaultDomain string = containerAppsEnvironment.properties.defaultDomain
+output name string = app.name
+output uri string = 'https://${app.properties.configuration.ingress.fqdn}'
+output id string = app.id
diff --git a/dotnet/samples/marketing/infra/app/frontend.bicep b/dotnet/samples/marketing/infra/app/frontend.bicep
new file mode 100644
index 0000000000..a872c23cfd
--- /dev/null
+++ b/dotnet/samples/marketing/infra/app/frontend.bicep
@@ -0,0 +1,132 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param identityName string
+param containerRegistryName string
+param containerAppsEnvironmentName string
+param applicationInsightsName string
+param apiUrls array
+param exists bool
+@secure()
+param appDefinition object
+
+var appSettingsArray = filter(array(appDefinition.settings), i => i.name != '')
+var secrets = map(filter(appSettingsArray, i => i.?secret != null), i => {
+ name: i.name
+ value: i.value
+ secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32)
+})
+var env = map(filter(appSettingsArray, i => i.?secret == null), i => {
+ name: i.name
+ value: i.value
+})
+
+resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
+ name: identityName
+ location: location
+}
+
+resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = {
+ name: containerRegistryName
+}
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' existing = {
+ name: containerAppsEnvironmentName
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
+ name: applicationInsightsName
+}
+
+resource acrPullRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: containerRegistry
+ name: guid(subscription().id, resourceGroup().id, identity.id, 'acrPullRole')
+ properties: {
+ roleDefinitionId: subscriptionResourceId(
+ 'Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
+ principalType: 'ServicePrincipal'
+ principalId: identity.properties.principalId
+ }
+}
+
+module fetchLatestImage '../modules/fetch-container-image.bicep' = {
+ name: '${name}-fetch-image'
+ params: {
+ exists: exists
+ name: name
+ }
+}
+
+resource app 'Microsoft.App/containerApps@2023-05-02-preview' = {
+ name: name
+ location: location
+ tags: union(tags, {'azd-service-name': 'frontend' })
+ dependsOn: [ acrPullRole ]
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: { '${identity.id}': {} }
+ }
+ properties: {
+ managedEnvironmentId: containerAppsEnvironment.id
+ configuration: {
+ ingress: {
+ external: true
+ targetPort: 3000
+ transport: 'auto'
+ }
+ registries: [
+ {
+ server: '${containerRegistryName}.azurecr.io'
+ identity: identity.id
+ }
+ ]
+ secrets: union([
+ ],
+ map(secrets, secret => {
+ name: secret.secretRef
+ value: secret.value
+ }))
+ }
+ template: {
+ containers: [
+ {
+ image: fetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
+ name: 'main'
+ env: union([
+ {
+ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
+ value: applicationInsights.properties.ConnectionString
+ }
+ {
+ name: 'BACKEND_BASE_URL'
+ value: apiUrls[0]
+ }
+ {
+ name: 'PORT'
+ value: '3000'
+ }
+ ],
+ env,
+ map(secrets, secret => {
+ name: secret.name
+ secretRef: secret.secretRef
+ }))
+ resources: {
+ cpu: json('1.0')
+ memory: '2.0Gi'
+ }
+ }
+ ]
+ scale: {
+ minReplicas: 1
+ maxReplicas: 10
+ }
+ }
+ }
+}
+
+output defaultDomain string = containerAppsEnvironment.properties.defaultDomain
+output name string = app.name
+output uri string = 'https://${app.properties.configuration.ingress.fqdn}'
+output id string = app.id
diff --git a/dotnet/samples/marketing/infra/main.bicep b/dotnet/samples/marketing/infra/main.bicep
new file mode 100644
index 0000000000..578f9c1201
--- /dev/null
+++ b/dotnet/samples/marketing/infra/main.bicep
@@ -0,0 +1,135 @@
+targetScope = 'subscription'
+
+@minLength(1)
+@maxLength(64)
+@description('Name of the environment that can be used as part of naming resource convention')
+param environmentName string
+
+@minLength(1)
+@description('Primary location for all resources')
+param location string
+
+param backendExists bool
+@secure()
+param backendDefinition object
+param frontendExists bool
+@secure()
+param frontendDefinition object
+
+@description('Id of the user or app to assign application roles')
+param principalId string
+
+// Tags that should be applied to all resources.
+//
+// Note that 'azd-service-name' tags should be applied separately to service host resources.
+// Example usage:
+// tags: union(tags, { 'azd-service-name': })
+var tags = {
+ 'azd-env-name': environmentName
+}
+
+var abbrs = loadJsonContent('./abbreviations.json')
+var resourceToken = toLower(uniqueString(subscription().id, environmentName, location))
+
+resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = {
+ name: 'rg-${environmentName}'
+ location: location
+ tags: tags
+}
+
+module monitoring './shared/monitoring.bicep' = {
+ name: 'monitoring'
+ params: {
+ location: location
+ tags: tags
+ logAnalyticsName: '${abbrs.operationalInsightsWorkspaces}${resourceToken}'
+ applicationInsightsName: '${abbrs.insightsComponents}${resourceToken}'
+ }
+ scope: rg
+}
+
+module dashboard './shared/dashboard-web.bicep' = {
+ name: 'dashboard'
+ params: {
+ name: '${abbrs.portalDashboards}${resourceToken}'
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ location: location
+ tags: tags
+ }
+ scope: rg
+}
+
+module registry './shared/registry.bicep' = {
+ name: 'registry'
+ params: {
+ location: location
+ tags: tags
+ name: '${abbrs.containerRegistryRegistries}${resourceToken}'
+ }
+ scope: rg
+}
+
+module keyVault './shared/keyvault.bicep' = {
+ name: 'keyvault'
+ params: {
+ location: location
+ tags: tags
+ name: '${abbrs.keyVaultVaults}${resourceToken}'
+ principalId: principalId
+ }
+ scope: rg
+}
+
+module appsEnv './shared/apps-env.bicep' = {
+ name: 'apps-env'
+ params: {
+ name: '${abbrs.appManagedEnvironments}${resourceToken}'
+ location: location
+ tags: tags
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ logAnalyticsWorkspaceName: monitoring.outputs.logAnalyticsWorkspaceName
+ }
+ scope: rg
+}
+
+module backend './app/backend.bicep' = {
+ name: 'backend'
+ params: {
+ name: '${abbrs.appContainerApps}backend-${resourceToken}'
+ location: location
+ tags: tags
+ identityName: '${abbrs.managedIdentityUserAssignedIdentities}backend-${resourceToken}'
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ containerAppsEnvironmentName: appsEnv.outputs.name
+ containerRegistryName: registry.outputs.name
+ exists: backendExists
+ appDefinition: backendDefinition
+ allowedOrigins: [
+ 'https://${abbrs.appContainerApps}frontend-${resourceToken}.${appsEnv.outputs.domain}'
+ ]
+ }
+ scope: rg
+}
+
+module frontend './app/frontend.bicep' = {
+ name: 'frontend'
+ params: {
+ name: '${abbrs.appContainerApps}frontend-${resourceToken}'
+ location: location
+ tags: tags
+ identityName: '${abbrs.managedIdentityUserAssignedIdentities}frontend-${resourceToken}'
+ applicationInsightsName: monitoring.outputs.applicationInsightsName
+ containerAppsEnvironmentName: appsEnv.outputs.name
+ containerRegistryName: registry.outputs.name
+ exists: frontendExists
+ appDefinition: frontendDefinition
+ apiUrls: [
+ backend.outputs.uri
+ ]
+ }
+ scope: rg
+}
+
+output AZURE_CONTAINER_REGISTRY_ENDPOINT string = registry.outputs.loginServer
+output AZURE_KEY_VAULT_NAME string = keyVault.outputs.name
+output AZURE_KEY_VAULT_ENDPOINT string = keyVault.outputs.endpoint
diff --git a/dotnet/samples/marketing/infra/main.parameters.json b/dotnet/samples/marketing/infra/main.parameters.json
new file mode 100644
index 0000000000..c7fc26a4a1
--- /dev/null
+++ b/dotnet/samples/marketing/infra/main.parameters.json
@@ -0,0 +1,59 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "environmentName": {
+ "value": "${AZURE_ENV_NAME}"
+ },
+ "location": {
+ "value": "${AZURE_LOCATION}"
+ },
+ "backendExists": {
+ "value": "${SERVICE_BACKEND_RESOURCE_EXISTS=false}"
+ },
+ "backendDefinition": {
+ "value": {
+ "settings": [
+ {
+ "name": "",
+ "value": "${VAR}",
+ "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
+ "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment."
+ },
+ {
+ "name": "",
+ "value": "${VAR_S}",
+ "secret": true,
+ "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
+ "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment."
+ }
+ ]
+ }
+ },
+ "frontendExists": {
+ "value": "${SERVICE_FRONTEND_RESOURCE_EXISTS=false}"
+ },
+ "frontendDefinition": {
+ "value": {
+ "settings": [
+ {
+ "name": "",
+ "value": "${VAR}",
+ "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
+ "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment."
+ },
+ {
+ "name": "",
+ "value": "${VAR_S}",
+ "secret": true,
+ "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
+ "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment."
+ }
+ ]
+ }
+ },
+ "principalId": {
+ "value": "${AZURE_PRINCIPAL_ID}"
+ }
+ }
+}
diff --git a/dotnet/samples/marketing/infra/modules/fetch-container-image.bicep b/dotnet/samples/marketing/infra/modules/fetch-container-image.bicep
new file mode 100644
index 0000000000..78d1e7eeb5
--- /dev/null
+++ b/dotnet/samples/marketing/infra/modules/fetch-container-image.bicep
@@ -0,0 +1,8 @@
+param exists bool
+param name string
+
+resource existingApp 'Microsoft.App/containerApps@2023-05-02-preview' existing = if (exists) {
+ name: name
+}
+
+output containers array = exists ? existingApp.properties.template.containers : []
diff --git a/dotnet/samples/marketing/infra/shared/apps-env.bicep b/dotnet/samples/marketing/infra/shared/apps-env.bicep
new file mode 100644
index 0000000000..030b823313
--- /dev/null
+++ b/dotnet/samples/marketing/infra/shared/apps-env.bicep
@@ -0,0 +1,33 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param logAnalyticsWorkspaceName string
+param applicationInsightsName string = ''
+
+resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-10-01' = {
+ name: name
+ location: location
+ tags: tags
+ properties: {
+ appLogsConfiguration: {
+ destination: 'log-analytics'
+ logAnalyticsConfiguration: {
+ customerId: logAnalyticsWorkspace.properties.customerId
+ sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
+ }
+ }
+ daprAIConnectionString: applicationInsights.properties.ConnectionString
+ }
+}
+
+resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
+ name: logAnalyticsWorkspaceName
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
+ name: applicationInsightsName
+}
+
+output name string = containerAppsEnvironment.name
+output domain string = containerAppsEnvironment.properties.defaultDomain
diff --git a/dotnet/samples/marketing/infra/shared/dashboard-web.bicep b/dotnet/samples/marketing/infra/shared/dashboard-web.bicep
new file mode 100644
index 0000000000..eccce0dbf6
--- /dev/null
+++ b/dotnet/samples/marketing/infra/shared/dashboard-web.bicep
@@ -0,0 +1,1231 @@
+param name string
+param applicationInsightsName string
+param location string = resourceGroup().location
+param tags object = {}
+
+// 2020-09-01-preview because that is the latest valid version
+resource applicationInsightsDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ properties: {
+ lenses: [
+ {
+ order: 0
+ parts: [
+ {
+ position: {
+ x: 0
+ y: 0
+ colSpan: 2
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'id'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart'
+ asset: {
+ idInputName: 'id'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'overview'
+ }
+ }
+ {
+ position: {
+ x: 2
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'ProactiveDetection'
+ }
+ }
+ {
+ position: {
+ x: 3
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-04T01:20:33.345Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 5
+ y: 0
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-08T18:47:35.237Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'ConfigurationId'
+ value: '78ce933e-e864-4b05-a27b-71fd55a6afad'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/AppMapButtonPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Usage'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 3
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ endTime: null
+ createdTime: '2018-05-04T01:22:35.782Z'
+ isInitialTime: true
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Reliability'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 7
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ {
+ name: 'DataModel'
+ value: {
+ version: '1.0.0'
+ timeContext: {
+ durationMs: 86400000
+ createdTime: '2018-05-04T23:42:40.072Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ isOptional: true
+ }
+ {
+ name: 'ConfigurationId'
+ value: '8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart'
+ isAdapter: true
+ asset: {
+ idInputName: 'ResourceId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'failures'
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Responsiveness\r\n'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 11
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ResourceId'
+ value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ {
+ name: 'DataModel'
+ value: {
+ version: '1.0.0'
+ timeContext: {
+ durationMs: 86400000
+ createdTime: '2018-05-04T23:43:37.804Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ isOptional: true
+ }
+ {
+ name: 'ConfigurationId'
+ value: '2a8ede4f-2bee-4b9c-aed9-2db0e8a01865'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart'
+ isAdapter: true
+ asset: {
+ idInputName: 'ResourceId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'performance'
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 1
+ colSpan: 3
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: '# Browser'
+ title: ''
+ subtitle: ''
+ }
+ }
+ }
+ }
+ }
+ {
+ position: {
+ x: 15
+ y: 1
+ colSpan: 1
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'ComponentId'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'MetricsExplorerJsonDefinitionId'
+ value: 'BrowserPerformanceTimelineMetrics'
+ }
+ {
+ name: 'TimeContext'
+ value: {
+ durationMs: 86400000
+ createdTime: '2018-05-08T12:16:27.534Z'
+ isInitialTime: false
+ grain: 1
+ useDashboardTimeRange: false
+ }
+ }
+ {
+ name: 'CurrentFilter'
+ value: {
+ eventTypes: [
+ 4
+ 1
+ 3
+ 5
+ 2
+ 6
+ 13
+ ]
+ typeFacets: {}
+ isPermissive: false
+ }
+ }
+ {
+ name: 'id'
+ value: {
+ Name: applicationInsightsName
+ SubscriptionId: subscription().subscriptionId
+ ResourceGroup: resourceGroup().name
+ }
+ }
+ {
+ name: 'Version'
+ value: '1.0'
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart'
+ asset: {
+ idInputName: 'ComponentId'
+ type: 'ApplicationInsights'
+ }
+ defaultMenuItemId: 'browser'
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'sessions/count'
+ aggregationType: 5
+ namespace: 'microsoft.insights/components/kusto'
+ metricVisualization: {
+ displayName: 'Sessions'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'users/count'
+ aggregationType: 5
+ namespace: 'microsoft.insights/components/kusto'
+ metricVisualization: {
+ displayName: 'Users'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Unique sessions and users'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ menuid: 'segmentationUsers'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'requests/failed'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Failed requests'
+ color: '#EC008C'
+ }
+ }
+ ]
+ title: 'Failed requests'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ menuid: 'failures'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'requests/duration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Server response time'
+ color: '#00BCF2'
+ }
+ }
+ ]
+ title: 'Server response time'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ menuid: 'performance'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 2
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'browserTimings/networkDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Page load network connect time'
+ color: '#7E58FF'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'browserTimings/processingDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Client processing time'
+ color: '#44F1C8'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'browserTimings/sendDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Send request time'
+ color: '#EB9371'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'browserTimings/receiveDuration'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Receiving response time'
+ color: '#0672F1'
+ }
+ }
+ ]
+ title: 'Average page load time breakdown'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'availabilityResults/availabilityPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Availability'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average availability'
+ visualization: {
+ chartType: 3
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ openBladeOnClick: {
+ openBlade: true
+ destinationBlade: {
+ extensionName: 'HubsExtension'
+ bladeName: 'ResourceMenuBlade'
+ parameters: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ menuid: 'availability'
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'exceptions/server'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Server exceptions'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'dependencies/failed'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Dependency failures'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Server exceptions and Dependency failures'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'performanceCounters/processorCpuPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Processor time'
+ color: '#47BDF5'
+ }
+ }
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'performanceCounters/processCpuPercentage'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Process CPU'
+ color: '#7E58FF'
+ }
+ }
+ ]
+ title: 'Average processor and process CPU utilization'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 12
+ y: 5
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'exceptions/browser'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Browser exceptions'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Browser exceptions'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'availabilityResults/count'
+ aggregationType: 7
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Availability test results count'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Availability test results count'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 4
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'performanceCounters/processIOBytesPerSecond'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Process IO rate'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average process I/O rate'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 8
+ colSpan: 4
+ rowSpan: 3
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'options'
+ value: {
+ chart: {
+ metrics: [
+ {
+ resourceMetadata: {
+ id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsightsName}'
+ }
+ name: 'performanceCounters/memoryAvailableBytes'
+ aggregationType: 4
+ namespace: 'microsoft.insights/components'
+ metricVisualization: {
+ displayName: 'Available memory'
+ color: '#47BDF5'
+ }
+ }
+ ]
+ title: 'Average available memory'
+ visualization: {
+ chartType: 2
+ legendVisualization: {
+ isVisible: true
+ position: 2
+ hideSubtitle: false
+ }
+ axisVisualization: {
+ x: {
+ isVisible: true
+ axisType: 2
+ }
+ y: {
+ isVisible: true
+ axisType: 1
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ name: 'sharedTimeRange'
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/MonitorChartPart'
+ settings: {}
+ }
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/dotnet/samples/marketing/infra/shared/keyvault.bicep b/dotnet/samples/marketing/infra/shared/keyvault.bicep
new file mode 100644
index 0000000000..f84f7508dd
--- /dev/null
+++ b/dotnet/samples/marketing/infra/shared/keyvault.bicep
@@ -0,0 +1,31 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+@description('Service principal that should be granted read access to the KeyVault. If unset, no service principal is granted access by default')
+param principalId string = ''
+
+var defaultAccessPolicies = !empty(principalId) ? [
+ {
+ objectId: principalId
+ permissions: { secrets: [ 'get', 'list' ] }
+ tenantId: subscription().tenantId
+ }
+] : []
+
+resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
+ name: name
+ location: location
+ tags: tags
+ properties: {
+ tenantId: subscription().tenantId
+ sku: { family: 'A', name: 'standard' }
+ enabledForTemplateDeployment: true
+ accessPolicies: union(defaultAccessPolicies, [
+ // define access policies here
+ ])
+ }
+}
+
+output endpoint string = keyVault.properties.vaultUri
+output name string = keyVault.name
diff --git a/dotnet/samples/marketing/infra/shared/monitoring.bicep b/dotnet/samples/marketing/infra/shared/monitoring.bicep
new file mode 100644
index 0000000000..4ae9796cc3
--- /dev/null
+++ b/dotnet/samples/marketing/infra/shared/monitoring.bicep
@@ -0,0 +1,34 @@
+param logAnalyticsName string
+param applicationInsightsName string
+param location string = resourceGroup().location
+param tags object = {}
+
+resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
+ name: logAnalyticsName
+ location: location
+ tags: tags
+ properties: any({
+ retentionInDays: 30
+ features: {
+ searchVersion: 1
+ }
+ sku: {
+ name: 'PerGB2018'
+ }
+ })
+}
+
+resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
+ name: applicationInsightsName
+ location: location
+ tags: tags
+ kind: 'web'
+ properties: {
+ Application_Type: 'web'
+ WorkspaceResourceId: logAnalytics.id
+ }
+}
+
+output applicationInsightsName string = applicationInsights.name
+output logAnalyticsWorkspaceId string = logAnalytics.id
+output logAnalyticsWorkspaceName string = logAnalytics.name
diff --git a/dotnet/samples/marketing/infra/shared/registry.bicep b/dotnet/samples/marketing/infra/shared/registry.bicep
new file mode 100644
index 0000000000..d6629f8620
--- /dev/null
+++ b/dotnet/samples/marketing/infra/shared/registry.bicep
@@ -0,0 +1,36 @@
+param name string
+param location string = resourceGroup().location
+param tags object = {}
+
+param adminUserEnabled bool = true
+param anonymousPullEnabled bool = false
+param dataEndpointEnabled bool = false
+param encryption object = {
+ status: 'disabled'
+}
+param networkRuleBypassOptions string = 'AzureServices'
+param publicNetworkAccess string = 'Enabled'
+param sku object = {
+ name: 'Standard'
+}
+param zoneRedundancy string = 'Disabled'
+
+// 2023-01-01-preview needed for anonymousPullEnabled
+resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = {
+ name: name
+ location: location
+ tags: tags
+ sku: sku
+ properties: {
+ adminUserEnabled: adminUserEnabled
+ anonymousPullEnabled: anonymousPullEnabled
+ dataEndpointEnabled: dataEndpointEnabled
+ encryption: encryption
+ networkRuleBypassOptions: networkRuleBypassOptions
+ publicNetworkAccess: publicNetworkAccess
+ zoneRedundancy: zoneRedundancy
+ }
+}
+
+output loginServer string = containerRegistry.properties.loginServer
+output name string = containerRegistry.name
diff --git a/dotnet/samples/marketing/next-steps.md b/dotnet/samples/marketing/next-steps.md
new file mode 100644
index 0000000000..daae170782
--- /dev/null
+++ b/dotnet/samples/marketing/next-steps.md
@@ -0,0 +1,96 @@
+# Next Steps after `azd init`
+
+## Table of Contents
+
+1. [Next Steps](#next-steps)
+2. [What was added](#what-was-added)
+3. [Billing](#billing)
+4. [Troubleshooting](#troubleshooting)
+
+## Next Steps
+
+### Define environment variables for running services
+
+1. Modify or add environment variables to configure the running application. Environment variables can be configured by updating the `settings` node(s) for each service in [main.parameters.json](./infra/main.parameters.json).
+2. For services using a database, environment variables have been pre-configured under the `env` node in the following files to allow connection to the database. Modify the name of these variables as needed to match your application.
+ - [app/backend.bicep](./infra/app/backend.bicep)
+ - [app/frontend.bicep](./infra/app/frontend.bicep)
+3. For services using Redis, environment variables will not show up under `env` explicitly, but are available as: `REDIS_ENDPOINT`, `REDIS_HOST`, `REDIS_PASSWORD`, and `REDIS_PORT`.
+
+### Provision infrastructure and deploy application code
+
+Run `azd up` to provision your infrastructure and deploy to Azure in one step (or run `azd provision` then `azd deploy` to accomplish the tasks separately). Visit the service endpoints listed to see your application up-and-running!
+
+To troubleshoot any issues, see [troubleshooting](#troubleshooting).
+
+### Configure CI/CD pipeline
+
+1. Create a workflow pipeline file locally. The following starters are available:
+ - [Deploy with GitHub Actions](https://github.com/Azure-Samples/azd-starter-bicep/blob/main/.github/workflows/azure-dev.yml)
+ - [Deploy with Azure Pipelines](https://github.com/Azure-Samples/azd-starter-bicep/blob/main/.azdo/pipelines/azure-dev.yml)
+2. Run `azd pipeline config -e ` to configure the deployment pipeline to connect securely to Azure. An environment name is specified here to configure the pipeline with a different environment for isolation purposes. Run `azd env list` and `azd env set` to reselect the default environment after this step.
+
+## What was added
+
+### Infrastructure configuration
+
+To describe the infrastructure and application, `azure.yaml` along with Infrastructure as Code files using Bicep were added with the following directory structure:
+
+```yaml
+- azure.yaml # azd project configuration
+- infra/ # Infrastructure as Code (bicep) files
+ - main.bicep # main deployment module
+ - app/ # Application resource modules
+ - shared/ # Shared resource modules
+ - modules/ # Library modules
+```
+
+Each bicep file declares resources to be provisioned. The resources are provisioned when running `azd up` or `azd provision`.
+
+- [app/backend.bicep](./infra/app/backend.bicep) - Azure Container Apps resources to host the 'backend' service.
+- [app/frontend.bicep](./infra/app/frontend.bicep) - Azure Container Apps resources to host the 'frontend' service.
+- [shared/keyvault.bicep](./infra/shared/keyvault.bicep) - Azure KeyVault to store secrets.
+- [shared/monitoring.bicep](./infra/shared/monitoring.bicep) - Azure Log Analytics workspace and Application Insights to log and store instrumentation logs.
+- [shared/registry.bicep](./infra/shared/registry.bicep) - Azure Container Registry to store docker images.
+
+More information about [Bicep](https://aka.ms/bicep) language.
+
+### Build from source (no Dockerfile)
+
+#### Build with Buildpacks using Oryx
+
+If your project does not contain a Dockerfile, we will use [Buildpacks](https://buildpacks.io/) using [Oryx](https://github.com/microsoft/Oryx/blob/main/doc/README.md) to create an image for the services in `azure.yaml` and get your containerized app onto Azure.
+
+To produce and run the docker image locally:
+
+1. Run `azd package` to build the image.
+2. Copy the *Image Tag* shown.
+3. Run `docker run -it ` to run the image locally.
+
+#### Exposed port
+
+Oryx will automatically set `PORT` to a default value of `80`. Additionally, it will auto-configure supported web servers such as `gunicorn` and `ASP .NET Core` to listen to the target `PORT`. If your application already listens to the port specified by the `PORT` variable, the application will work out-of-the-box. Otherwise, you may need to perform one of the steps below:
+
+1. Update your application code or configuration to listen to the port specified by the `PORT` variable
+1. (Alternatively) Search for `targetPort` in a .bicep file under the `infra/app` folder, and update the variable to match the port used by the application.
+
+## Billing
+
+Visit the *Cost Management + Billing* page in Azure Portal to track current spend. For more information about how you're billed, and how you can monitor the costs incurred in your Azure subscriptions, visit [billing overview](https://learn.microsoft.com/azure/developer/intro/azure-developer-billing).
+
+## Troubleshooting
+
+Q: I visited the service endpoint listed, and I'm seeing a blank or error page.
+
+A: Your service may have failed to start or misconfigured. To investigate further:
+
+1. Click on the resource group link shown to visit Azure Portal.
+2. Navigate to the specific Azure Container App resource for the service.
+3. Select *Monitoring -> Log stream* under the navigation pane.
+4. Observe the log output to identify any errors.
+5. If there are no errors, ensure that the ingress target port matches the port that your service listens on:
+ 1. Under *Settings -> Ingress*, ensure the *Target port* matches the desired port.
+ 2. After modifying this setting, also update the `targetPort` setting in the .bicep file for the service under `infra/app`.
+6. If logs are written to disk, examine the local logs or debug the application by using the *Console* to connect to a shell within the running container.
+
+For additional information about setting up your `azd` project, visit our official [docs](https://learn.microsoft.com/azure/developer/azure-developer-cli/make-azd-compatible?pivots=azd-convert).
diff --git a/dotnet/samples/marketing/readme-media/agents.png b/dotnet/samples/marketing/readme-media/agents.png
new file mode 100644
index 0000000000..0eb6203c6d
Binary files /dev/null and b/dotnet/samples/marketing/readme-media/agents.png differ
diff --git a/dotnet/samples/marketing/readme-media/screenshot.png b/dotnet/samples/marketing/readme-media/screenshot.png
new file mode 100644
index 0000000000..3829a5b213
Binary files /dev/null and b/dotnet/samples/marketing/readme-media/screenshot.png differ
diff --git a/dotnet/samples/marketing/run.ps1 b/dotnet/samples/marketing/run.ps1
new file mode 100644
index 0000000000..878d004560
--- /dev/null
+++ b/dotnet/samples/marketing/run.ps1
@@ -0,0 +1,13 @@
+if(Test-Path src/backend/appsettings.json) {
+ Write-Verbose "appsettings.json already exists" -Verbose
+} else {
+ Copy-Item src/backend/appsettings.local.template.json src/backend/appsettings.json
+ Write-Verbose "appsettings.json created" -Verbose
+}
+
+if((Get-Content .\src\backend\appsettings.local.template.json -Raw | Select-String "") -ne $null) {
+ Write-Error "Please update the appsettings.json file with the correct values" -ErrorAction Stop
+}
+
+$backendProc = Start-Process powershell -ArgumentList '-NoExit', '-Command cd src/backend/; dotnet run'
+$frontendProc = Start-Process powershell -ArgumentList '-NoExit', '-Command cd src/frontend/; npm run dev'
\ No newline at end of file
diff --git a/dotnet/samples/marketing/run.sh b/dotnet/samples/marketing/run.sh
new file mode 100644
index 0000000000..0052cf859f
--- /dev/null
+++ b/dotnet/samples/marketing/run.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+if [ -f src/backend/appsettings.json ]; then
+ echo "appsettings.json already exists"
+else
+ cp src/backend/appsettings.local.template.json src/backend/appsettings.json
+ echo "appsettings.json created"
+fi
+
+if grep -q "" src/backend/appsettings.local.template.json; then
+ echo "Please update the appsettings.json file with the correct values" >&2
+ exit 1
+fi
+
+gnome-terminal -- bash -c "cd src/backend/ && dotnet run; exec bash"
+gnome-terminal -- bash -c "cd src/frontend/ && npm run dev; exec bash"
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/.gitignore b/dotnet/samples/marketing/src/backend/.gitignore
new file mode 100644
index 0000000000..494561e810
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/.gitignore
@@ -0,0 +1,485 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from `dotnet new gitignore`
+
+# dotenv files
+.env
+appsettings.json
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.idea
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Vim temporary swap files
+*.swp
diff --git a/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManager.cs b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManager.cs
new file mode 100644
index 0000000000..cd2416bf17
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManager.cs
@@ -0,0 +1,72 @@
+using Marketing.Events;
+using Marketing.Options;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Marketing.Agents;
+
+[ImplicitStreamSubscription(Consts.OrleansNamespace)]
+public class CommunityManager : AiAgent
+{
+ protected override string Namespace => Consts.OrleansNamespace;
+
+ private readonly ILogger _logger;
+
+ public CommunityManager([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(EventTypes.UserConnected):
+ // The user reconnected, let's send the last message if we have one
+ string lastMessage = _state.State.History.LastOrDefault()?.Message;
+ if (lastMessage == null)
+ {
+ return;
+ }
+
+ await SendDesignedCreatedEvent(lastMessage, item.Data["UserId"]);
+ break;
+
+ case nameof(EventTypes.ArticleCreated):
+ {
+ var article = item.Data["article"];
+
+ _logger.LogInformation($"[{nameof(GraphicDesigner)}] Event {nameof(EventTypes.ArticleCreated)}. Article: {article}");
+
+ var context = new KernelArguments { ["input"] = AppendChatHistory(article) };
+ string socialMediaPost = await CallFunction(CommunityManagerPrompts.WritePost, context);
+ _state.State.Data.WrittenSocialMediaPost = socialMediaPost;
+ await SendDesignedCreatedEvent(socialMediaPost, item.Data["UserId"]);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ private async Task SendDesignedCreatedEvent(string socialMediaPost, string userId)
+ {
+ await PublishEvent(Consts.OrleansNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(EventTypes.SocialMediaPostCreated),
+ Data = new Dictionary {
+ { "UserId", userId },
+ { nameof(socialMediaPost), socialMediaPost}
+ }
+ });
+ }
+
+ public Task GetArticle()
+ {
+ return Task.FromResult(_state.State.Data.WrittenSocialMediaPost);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerPrompts.cs b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerPrompts.cs
new file mode 100644
index 0000000000..74365103a1
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerPrompts.cs
@@ -0,0 +1,11 @@
+namespace Marketing.Agents;
+
+public static class CommunityManagerPrompts
+{
+ public static string WritePost = """
+ You are a Marketing community manager writer.
+ Write a tweet to promote what it is described bellow.
+ The tweet cannot be longer than 280 characters
+ Input: {{$input}}
+ """;
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerState.cs b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerState.cs
new file mode 100644
index 0000000000..baed2a9737
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/CommunityManager/CommunityManagerState.cs
@@ -0,0 +1,8 @@
+namespace Marketing.Agents;
+
+[GenerateSerializer]
+public class CommunityManagerState
+{
+ [Id(0)]
+ public string WrittenSocialMediaPost { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignedState.cs b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignedState.cs
new file mode 100644
index 0000000000..3add068733
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignedState.cs
@@ -0,0 +1,8 @@
+namespace Marketing.Agents;
+
+[GenerateSerializer]
+public class GraphicDesignerState
+{
+ [Id(0)]
+ public string imageUrl { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesigner.cs b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesigner.cs
new file mode 100644
index 0000000000..8830f6d260
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesigner.cs
@@ -0,0 +1,73 @@
+using Marketing.Events;
+using Marketing.Options;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel.TextToImage;
+using Orleans.Runtime;
+
+namespace Marketing.Agents;
+
+[ImplicitStreamSubscription(Consts.OrleansNamespace)]
+public class GraphicDesigner : AiAgent
+{
+ protected override string Namespace => Consts.OrleansNamespace;
+
+ private readonly ILogger _logger;
+ private readonly IConfiguration _configuration;
+
+ public GraphicDesigner([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger, IConfiguration configuration)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ _configuration = configuration;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ string lastMessage;
+
+ switch (item.Type)
+ {
+ case nameof(EventTypes.UserConnected):
+ // The user reconnected, let's send the last message if we have one
+ lastMessage = _state.State.History.LastOrDefault()?.Message;
+ if (lastMessage == null)
+ {
+ return;
+ }
+
+ await SendDesignedCreatedEvent(lastMessage, item.Data["UserId"]);
+
+ break;
+ case nameof(EventTypes.ArticleCreated):
+ //TODO
+ _logger.LogInformation($"[{nameof(GraphicDesigner)}] Event {nameof(EventTypes.ArticleCreated)}.");
+ var article = item.Data["article"];
+ var dallEService = _kernel.GetRequiredService();
+ var imageUri = await dallEService.GenerateImageAsync(article, 1024, 1024);
+
+ _state.State.Data.imageUrl = imageUri;
+
+ await SendDesignedCreatedEvent(imageUri, item.Data["UserId"]);
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private async Task SendDesignedCreatedEvent(string imageUri, string userId)
+ {
+ await PublishEvent(Consts.OrleansNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(EventTypes.GraphicDesignCreated),
+ Data = new Dictionary {
+ { "UserId", userId },
+ { nameof(imageUri), imageUri}
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignerPrompts.cs b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignerPrompts.cs
new file mode 100644
index 0000000000..d17cf5f72e
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/GraphicDesigner/GraphicDesignerPrompts.cs
@@ -0,0 +1,11 @@
+
+namespace Marketing.Agents;
+public static class GraphicDesignerPrompts
+{
+ public static string GenerateImage = """
+ You are a Marketing community manager graphic designer.
+ Bellow is a campaing that you need to create a image for.
+ Create an image of maximum 500x500 pixels that could be use in social medias as a marketing iamge.
+ Input: {{$input}}
+ """;
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/SignalR/SignalR.cs b/dotnet/samples/marketing/src/backend/Agents/SignalR/SignalR.cs
new file mode 100644
index 0000000000..8d4ee4ea98
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/SignalR/SignalR.cs
@@ -0,0 +1,48 @@
+using Marketing.Events;
+using Marketing.Options;
+using Marketing.SignalRHub;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using System;
+using System.Security.Policy;
+
+namespace Marketing.Agents;
+
+[ImplicitStreamSubscription(Consts.OrleansNamespace)]
+public class SignalR : Agent
+{
+ protected override string Namespace => Consts.OrleansNamespace;
+
+ private readonly ILogger _logger;
+ private readonly ISignalRService _signalRClient;
+
+ public SignalR(ILogger logger, ISignalRService signalRClient)
+ {
+ _logger = logger;
+ _signalRClient = signalRClient;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(EventTypes.ArticleCreated):
+ var writenArticle = item.Data["article"];
+ await _signalRClient.SendMessageToSpecificClient(item.Data["UserId"], writenArticle, AgentTypes.Chat);
+ break;
+
+ case nameof(EventTypes.GraphicDesignCreated):
+ var imageUrl = item.Data["imageUri"];
+ await _signalRClient.SendMessageToSpecificClient(item.Data["UserId"], imageUrl, AgentTypes.GraphicDesigner);
+ break;
+
+ case nameof(EventTypes.SocialMediaPostCreated):
+ var post = item.Data["socialMediaPost"];
+ await _signalRClient.SendMessageToSpecificClient(item.Data["UserId"], post, AgentTypes.CommunityManager);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/Writer/IWritter.cs b/dotnet/samples/marketing/src/backend/Agents/Writer/IWritter.cs
new file mode 100644
index 0000000000..63174839ab
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/Writer/IWritter.cs
@@ -0,0 +1,5 @@
+namespace Marketing.Agents;
+public interface IWriter : IGrainWithStringKey
+{
+ Task GetArticle();
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/Writer/Writer.cs b/dotnet/samples/marketing/src/backend/Agents/Writer/Writer.cs
new file mode 100644
index 0000000000..ba13b15157
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/Writer/Writer.cs
@@ -0,0 +1,74 @@
+using Marketing.Events;
+using Marketing.Options;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AI.Agents.Orleans;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Marketing.Agents;
+
+[ImplicitStreamSubscription(Consts.OrleansNamespace)]
+public class Writer : AiAgent, IWriter
+{
+ protected override string Namespace => Consts.OrleansNamespace;
+
+ private readonly ILogger _logger;
+
+ public Writer([PersistentState("state", "messages")] IPersistentState> state, Kernel kernel, ISemanticTextMemory memory, ILogger logger)
+ : base(state, memory, kernel)
+ {
+ _logger = logger;
+ }
+
+ public async override Task HandleEvent(Event item)
+ {
+ switch (item.Type)
+ {
+ case nameof(EventTypes.UserConnected):
+ // The user reconnected, let's send the last message if we have one
+ string lastMessage = _state.State.History.LastOrDefault()?.Message;
+ if (lastMessage == null)
+ {
+ return;
+ }
+
+ await SendDesignedCreatedEvent(lastMessage, item.Data["UserId"]);
+
+ break;
+
+ case nameof(EventTypes.UserChatInput):
+ {
+ var userMessage = item.Data["userMessage"];
+ _logger.LogInformation($"[{nameof(GraphicDesigner)}] Event {nameof(EventTypes.UserChatInput)}. UserMessage: {userMessage}");
+
+ var context = new KernelArguments { ["input"] = AppendChatHistory(userMessage) };
+ string newArticle = await CallFunction(WriterPrompts.Write, context);
+
+ await SendDesignedCreatedEvent(newArticle, item.Data["UserId"]);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ private async Task SendDesignedCreatedEvent(string article, string userId)
+ {
+ await PublishEvent(Consts.OrleansNamespace, this.GetPrimaryKeyString(), new Event
+ {
+ Type = nameof(EventTypes.ArticleCreated),
+ Data = new Dictionary {
+ { "UserId", userId },
+ { nameof(article), article },
+ }
+ });
+ }
+
+
+ public Task GetArticle()
+ {
+ return Task.FromResult(_state.State.Data.WrittenArticle);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/Writer/WriterPrompts.cs b/dotnet/samples/marketing/src/backend/Agents/Writer/WriterPrompts.cs
new file mode 100644
index 0000000000..a3c54c936c
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/Writer/WriterPrompts.cs
@@ -0,0 +1,12 @@
+
+namespace Marketing.Agents;
+public static class WriterPrompts
+{
+ public static string Write = """
+ You are a Marketing writer.
+ Write up to three paragraphs for a campain to promote what it is described bellow.
+ Bellow are a series of inputs from the user that you can use to create the campain.
+ If the input talks about twitter or images, dismiss it and return the same as before.
+ Input: {{$input}}
+ """;
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Agents/Writer/WriterState.cs b/dotnet/samples/marketing/src/backend/Agents/Writer/WriterState.cs
new file mode 100644
index 0000000000..33f77d53bd
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Agents/Writer/WriterState.cs
@@ -0,0 +1,8 @@
+namespace Marketing.Agents;
+
+[GenerateSerializer]
+public class WriterState
+{
+ [Id(0)]
+ public string WrittenArticle { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Controller/Articles.cs b/dotnet/samples/marketing/src/backend/Controller/Articles.cs
new file mode 100644
index 0000000000..78cd09fc3b
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Controller/Articles.cs
@@ -0,0 +1,63 @@
+using Marketing.Agents;
+using Marketing.Events;
+using Marketing.Options;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AspNetCore.Mvc;
+using Orleans.Runtime;
+
+// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
+
+namespace Marketing.Controller
+{
+
+ [GenerateSerializer]
+ public class Asd
+ {
+ [Id(0)]
+ public string Name { get; set; }
+ }
+
+ [Route("api/[controller]")]
+ [ApiController]
+ public class Articles : ControllerBase
+ {
+ private readonly IClusterClient _client;
+
+ public Articles(IClusterClient client)
+ {
+ _client = client;
+ }
+
+ // GET api//5
+ [HttpGet("{id}")]
+ public async Task Get(string id)
+ {
+ var grain = _client.GetGrain(id);
+ string article = await grain.GetArticle();
+ return article;
+ }
+
+ // PUT api//5
+ [HttpPut("{UserId}")]
+ public async Task Put(string UserId, [FromBody] string userMessage)
+ {
+ var streamProvider = _client.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Consts.OrleansNamespace, UserId);
+ var stream = streamProvider.GetStream(streamId);
+
+ var data = new Dictionary
+ {
+ { nameof(UserId), UserId.ToString() },
+ { nameof(userMessage), userMessage },
+ };
+
+ await stream.OnNextAsync(new Event
+ {
+ Type = nameof(EventTypes.UserChatInput),
+ Data = data
+ });
+
+ return $"Task {UserId} accepted";
+ }
+ }
+}
diff --git a/dotnet/samples/marketing/src/backend/Dockerfile b/dotnet/samples/marketing/src/backend/Dockerfile
new file mode 100644
index 0000000000..c5a5045122
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Dockerfile
@@ -0,0 +1,23 @@
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5274
+EXPOSE 11111
+EXPOSE 30000
+
+ENV ASPNETCORE_URLS=http://+:5274
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+ARG configuration=Release
+COPY . .
+RUN dotnet restore "samples/marketing/src/backend/Marketing.csproj"
+WORKDIR "samples/marketing/src/backend"
+RUN dotnet build "Marketing.csproj" -c $configuration -o /app/build
+
+FROM build AS publish
+ARG configuration=Release
+RUN dotnet publish "Marketing.csproj" -c $configuration -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Marketing.dll"]
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Events/EventTypes.cs b/dotnet/samples/marketing/src/backend/Events/EventTypes.cs
new file mode 100644
index 0000000000..1a645ad6a9
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Events/EventTypes.cs
@@ -0,0 +1,10 @@
+namespace Marketing.Events;
+
+public enum EventTypes
+{
+ UserChatInput,
+ ArticleCreated,
+ UserConnected,
+ GraphicDesignCreated,
+ SocialMediaPostCreated,
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Marketing.csproj b/dotnet/samples/marketing/src/backend/Marketing.csproj
new file mode 100644
index 0000000000..e3c1366c11
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Marketing.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+ net8.0
+ enable
+ enable
+ true
+ true
+ c073c86e-8483-4956-942f-331fd09172d4
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/marketing/src/backend/Marketing.sln b/dotnet/samples/marketing/src/backend/Marketing.sln
new file mode 100644
index 0000000000..032e60cf44
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Marketing.sln
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.002.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing", "Marketing.csproj", "{491A6E2F-A0D0-4723-80A2-B0F60091E39D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AI.Agents.Orleans", "..\..\..\..\src\Microsoft.AI.Agents.Orleans\Microsoft.AI.Agents.Orleans.csproj", "{4C246005-605C-4F7F-8D67-839A5640587A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AI.Agents", "..\..\..\..\src\Microsoft.AI.Agents\Microsoft.AI.Agents.csproj", "{5CB1E5D6-33BF-4E09-BDE3-29F8A24F2158}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {491A6E2F-A0D0-4723-80A2-B0F60091E39D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {491A6E2F-A0D0-4723-80A2-B0F60091E39D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {491A6E2F-A0D0-4723-80A2-B0F60091E39D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {491A6E2F-A0D0-4723-80A2-B0F60091E39D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4C246005-605C-4F7F-8D67-839A5640587A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4C246005-605C-4F7F-8D67-839A5640587A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C246005-605C-4F7F-8D67-839A5640587A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4C246005-605C-4F7F-8D67-839A5640587A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5CB1E5D6-33BF-4E09-BDE3-29F8A24F2158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5CB1E5D6-33BF-4E09-BDE3-29F8A24F2158}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5CB1E5D6-33BF-4E09-BDE3-29F8A24F2158}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5CB1E5D6-33BF-4E09-BDE3-29F8A24F2158}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A6288EF9-5DDB-45A9-AA9A-EB9FDB18D82F}
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/samples/marketing/src/backend/Options/Consts.cs b/dotnet/samples/marketing/src/backend/Options/Consts.cs
new file mode 100644
index 0000000000..7effc35f6a
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Options/Consts.cs
@@ -0,0 +1,6 @@
+namespace Marketing.Options;
+
+public static class Consts
+{
+ public const string OrleansNamespace = "DevPersonas";
+}
diff --git a/dotnet/samples/marketing/src/backend/Options/OpenAIOptions.cs b/dotnet/samples/marketing/src/backend/Options/OpenAIOptions.cs
new file mode 100644
index 0000000000..1c336855e8
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Options/OpenAIOptions.cs
@@ -0,0 +1,30 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Marketing.Options;
+
+public class OpenAIOptions
+{
+ // Embeddings
+ [Required]
+ public string EmbeddingsEndpoint { get; set; }
+ [Required]
+ public string EmbeddingsApiKey { get; set; }
+ [Required]
+ public string EmbeddingsDeploymentOrModelId { get; set; }
+
+ // Chat
+ [Required]
+ public string ChatEndpoint { get; set; }
+ [Required]
+ public string ChatApiKey { get; set; }
+ [Required]
+ public string ChatDeploymentOrModelId { get; set; }
+
+ // TextToImage
+ [Required]
+ public string ImageEndpoint { get; set; }
+ [Required]
+ public string ImageApiKey { get; set; }
+ // When using OpenAI, this is not required.
+ public string ImageDeploymentOrModelId { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Options/QdrantOptions.cs b/dotnet/samples/marketing/src/backend/Options/QdrantOptions.cs
new file mode 100644
index 0000000000..ac1549875f
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Options/QdrantOptions.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Marketing.Options;
+public class QdrantOptions
+{
+ [Required]
+ public string Endpoint { get; set; }
+ [Required]
+ public int VectorSize { get; set; }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Options/Throw.cs b/dotnet/samples/marketing/src/backend/Options/Throw.cs
new file mode 100644
index 0000000000..ff6d672c88
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Options/Throw.cs
@@ -0,0 +1,13 @@
+namespace Marketing
+{
+ public static class Throw
+ {
+ public static void IfNullOrEmpty(string paramName, string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ throw new ArgumentNullException(paramName);
+ }
+ }
+ }
+}
diff --git a/dotnet/samples/marketing/src/backend/Program.cs b/dotnet/samples/marketing/src/backend/Program.cs
new file mode 100644
index 0000000000..2bba0d21ad
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Program.cs
@@ -0,0 +1,161 @@
+using System.Text.Json;
+using Azure;
+using Azure.AI.OpenAI;
+using Microsoft.Extensions.Options;
+using Microsoft.SemanticKernel;
+using Microsoft.Extensions.Http.Resilience;
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel.Connectors.Qdrant;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Marketing.SignalRHub;
+using Marketing.Options;
+using Marketing;
+using Orleans.Serialization;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddTransient(CreateKernel);
+builder.Services.AddTransient(CreateMemory);
+builder.Services.AddHttpClient();
+builder.Services.AddControllers();
+builder.Services.AddApplicationInsightsTelemetry();
+builder.Services.AddSwaggerGen();
+builder.Services.AddSignalR();
+builder.Services.AddSingleton();
+
+
+// Allow any CORS origin if in DEV
+const string AllowDebugOriginPolicy = "AllowDebugOrigin";
+if (builder.Environment.IsDevelopment())
+{
+ builder.Services.AddCors(options =>
+ {
+ options.AddPolicy(AllowDebugOriginPolicy, builder => {
+ builder
+ .WithOrigins("http://localhost:3000") // client url
+ .AllowAnyHeader()
+ .AllowAnyMethod()
+ .AllowCredentials();
+ });
+ });
+}
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(OpenAIOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Services.AddOptions()
+ .Configure((settings, configuration) =>
+ {
+ configuration.GetSection(nameof(QdrantOptions)).Bind(settings);
+ })
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+
+builder.Host.UseOrleans(siloBuilder =>
+{
+ siloBuilder.UseLocalhostClustering()
+ .AddMemoryStreams("StreamProvider")
+ .AddMemoryGrainStorage("PubSubStore")
+ .AddMemoryGrainStorage("messages");
+ siloBuilder.UseInMemoryReminderService();
+ siloBuilder.UseDashboard(x => x.HostSelf = true);
+});
+
+builder.Services.Configure(options =>
+{
+ options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+});
+
+var app = builder.Build();
+
+app.UseRouting();
+app.UseCors(AllowDebugOriginPolicy);
+app.MapControllers();
+
+app.UseSwagger();
+app.UseSwaggerUI(c =>
+{
+ c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
+});
+
+app.Map("/dashboard", x => x.UseOrleansDashboard());
+app.MapHub("/articlehub");
+app.Run();
+
+static ISemanticTextMemory CreateMemory(IServiceProvider provider)
+{
+ OpenAIOptions openAiConfig = provider.GetService>().Value;
+ QdrantOptions qdrantConfig = provider.GetService>().Value;
+
+ var loggerFactory = LoggerFactory.Create(builder =>
+ {
+ builder
+ .SetMinimumLevel(LogLevel.Debug)
+ .AddConsole()
+ .AddDebug();
+ });
+
+ var memoryBuilder = new MemoryBuilder();
+ return memoryBuilder.WithLoggerFactory(loggerFactory)
+ .WithQdrantMemoryStore(qdrantConfig.Endpoint, qdrantConfig.VectorSize)
+ .WithAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAiConfig.EmbeddingsEndpoint, openAiConfig.EmbeddingsApiKey)
+ .Build();
+}
+
+static Kernel CreateKernel(IServiceProvider provider)
+{
+ OpenAIOptions openAiConfig = provider.GetService>().Value;
+ var clientOptions = new OpenAIClientOptions();
+ clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddLogging(c => c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug));
+
+ // Chat
+ var openAIClient = new OpenAIClient(new Uri(openAiConfig.ChatEndpoint), new AzureKeyCredential(openAiConfig.ChatApiKey), clientOptions);
+ if (openAiConfig.ChatEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
+ {
+ builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient);
+ }
+ else
+ {
+
+ builder.Services.AddOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient);
+ }
+
+ // Text to Image
+ openAIClient = new OpenAIClient(new Uri(openAiConfig.ImageEndpoint), new AzureKeyCredential(openAiConfig.ImageApiKey), clientOptions);
+ if (openAiConfig.ImageEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
+ {
+ Throw.IfNullOrEmpty(nameof(openAiConfig.ImageDeploymentOrModelId), openAiConfig.ImageDeploymentOrModelId);
+ builder.Services.AddAzureOpenAITextToImage(openAiConfig.ImageDeploymentOrModelId, openAIClient);
+ }
+ else
+ {
+ builder.Services.AddOpenAITextToImage(openAiConfig.ImageApiKey);
+ }
+
+ // Embeddings
+ openAIClient = new OpenAIClient(new Uri(openAiConfig.EmbeddingsEndpoint), new AzureKeyCredential(openAiConfig.EmbeddingsApiKey), clientOptions);
+ if (openAiConfig.EmbeddingsEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase))
+ {
+ builder.Services.AddAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient);
+ }
+ else
+ {
+ builder.Services.AddOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient);
+ }
+
+ builder.Services.ConfigureHttpClientDefaults(c =>
+ {
+ c.AddStandardResilienceHandler().Configure(o =>
+ {
+ o.Retry.MaxRetryAttempts = 5;
+ o.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
+ });
+ });
+ return builder.Build();
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/Properties/launchSettings.json b/dotnet/samples/marketing/src/backend/Properties/launchSettings.json
new file mode 100644
index 0000000000..d7d94b581b
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/Properties/launchSettings.json
@@ -0,0 +1,33 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:59668",
+ "sslPort": 44354
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5244",
+ "launchUrl": "dashboard",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7227;http://localhost:5244",
+ "launchUrl": "dashboard",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ }
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/AgentTypes.cs b/dotnet/samples/marketing/src/backend/SignalRHub/AgentTypes.cs
new file mode 100644
index 0000000000..0591f59ec6
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/AgentTypes.cs
@@ -0,0 +1,11 @@
+namespace Marketing.SignalRHub;
+
+public enum AgentTypes
+{
+ Chat,
+ CommunityManager,
+ GraphicDesigner,
+ Auditor,
+ Accountant,
+ Librarian
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/ArticleHub.cs b/dotnet/samples/marketing/src/backend/SignalRHub/ArticleHub.cs
new file mode 100644
index 0000000000..f60876a2a6
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/ArticleHub.cs
@@ -0,0 +1,75 @@
+namespace Marketing.SignalRHub;
+
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.AspNetCore.SignalR;
+using Orleans.Runtime;
+using Marketing.Options;
+using Marketing.Events;
+
+public class ArticleHub : Hub
+{
+ public override async Task OnConnectedAsync()
+ {
+ await base.OnConnectedAsync();
+ }
+
+ public override async Task OnDisconnectedAsync(Exception exception)
+ {
+ string removedUserId;
+ SignalRConnectionsDB.ConnectionIdByUser.TryRemove(Context.ConnectionId, out _);
+ await base.OnDisconnectedAsync(exception);
+ }
+
+ ///
+ /// This method is called when a new message from the client arrives.
+ ///
+ ///
+ ///
+ ///
+ public async Task ProcessMessage(FrontEndMessage frontEndMessage, IClusterClient clusterClient)
+ {
+ var streamProvider = clusterClient.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Consts.OrleansNamespace, frontEndMessage.UserId);
+ var stream = streamProvider.GetStream(streamId);
+
+ var data = new Dictionary
+ {
+ { "UserId", frontEndMessage.UserId },
+ { "userMessage", frontEndMessage.Message},
+ };
+
+ await stream.OnNextAsync(new Event
+ {
+ Type = nameof(EventTypes.UserChatInput),
+ Data = data
+ });
+
+ }
+
+ public async Task ConnectToAgent(string UserId, IClusterClient clusterClient)
+ {
+ var frontEndMessage = new FrontEndMessage()
+ {
+ UserId = UserId,
+ Message = "Connected to agents",
+ Agent = AgentTypes.Chat.ToString()
+ };
+
+ SignalRConnectionsDB.ConnectionIdByUser.AddOrUpdate(UserId, Context.ConnectionId, (key, oldValue) => Context.ConnectionId);
+
+ // Notify the agents that a new user got connected.
+ var streamProvider = clusterClient.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Consts.OrleansNamespace, frontEndMessage.UserId);
+ var stream = streamProvider.GetStream(streamId);
+ var data = new Dictionary
+ {
+ { "UserId", frontEndMessage.UserId },
+ { "userMessage", frontEndMessage.Message},
+ };
+ await stream.OnNextAsync(new Event
+ {
+ Type = nameof(EventTypes.UserConnected),
+ Data = data
+ });
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/FrontEndMessage.cs b/dotnet/samples/marketing/src/backend/SignalRHub/FrontEndMessage.cs
new file mode 100644
index 0000000000..7e1debaa7d
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/FrontEndMessage.cs
@@ -0,0 +1,8 @@
+namespace Marketing.SignalRHub;
+
+public class FrontEndMessage
+{
+ public string UserId { get; set; }
+ public string Message { get; set; }
+ public string Agent { get; set; }
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/IArticleHub.cs b/dotnet/samples/marketing/src/backend/SignalRHub/IArticleHub.cs
new file mode 100644
index 0000000000..a9d8a4bb82
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/IArticleHub.cs
@@ -0,0 +1,10 @@
+namespace Marketing.SignalRHub;
+
+public interface IArticleHub
+{
+ public Task ConnectToAgent(string UserId);
+
+ public Task ChatMessage(FrontEndMessage frontEndMessage, IClusterClient clusterClient);
+
+ public Task SendMessageToSpecificClient(string userId, string message);
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/ISignalRService.cs b/dotnet/samples/marketing/src/backend/SignalRHub/ISignalRService.cs
new file mode 100644
index 0000000000..7207e6df71
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/ISignalRService.cs
@@ -0,0 +1,5 @@
+namespace Marketing.SignalRHub;
+public interface ISignalRService
+{
+ Task SendMessageToSpecificClient(string userId, string message, AgentTypes agentType);
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/SignalRConnectionsDB.cs b/dotnet/samples/marketing/src/backend/SignalRHub/SignalRConnectionsDB.cs
new file mode 100644
index 0000000000..172e8959a3
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/SignalRConnectionsDB.cs
@@ -0,0 +1,9 @@
+using System.Collections.Concurrent;
+
+namespace Marketing.SignalRHub;
+public static class SignalRConnectionsDB
+{
+ public static ConcurrentDictionary ConnectionIdByUser { get; } = new ConcurrentDictionary();
+ public static ConcurrentDictionary AllConnections { get; } = new ConcurrentDictionary();
+
+}
diff --git a/dotnet/samples/marketing/src/backend/SignalRHub/SignalRService.cs b/dotnet/samples/marketing/src/backend/SignalRHub/SignalRService.cs
new file mode 100644
index 0000000000..b1b771afc2
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/SignalRHub/SignalRService.cs
@@ -0,0 +1,25 @@
+using Microsoft.AspNetCore.SignalR;
+using System.Collections.Concurrent;
+
+namespace Marketing.SignalRHub;
+
+public class SignalRService : ISignalRService
+{
+ private readonly IHubContext _hubContext;
+ public SignalRService(IHubContext hubContext)
+ {
+ _hubContext = hubContext;
+ }
+
+ public async Task SendMessageToSpecificClient(string userId, string message, AgentTypes agentType)
+ {
+ var connectionId = SignalRConnectionsDB.ConnectionIdByUser[userId];
+ var frontEndMessage = new FrontEndMessage()
+ {
+ UserId = userId,
+ Message = message,
+ Agent = agentType.ToString()
+ };
+ await _hubContext.Clients.Client(connectionId).SendAsync("ReceiveMessage", frontEndMessage);
+ }
+}
diff --git a/dotnet/samples/marketing/src/backend/appsettings.local.template.json b/dotnet/samples/marketing/src/backend/appsettings.local.template.json
new file mode 100644
index 0000000000..68a8effeb0
--- /dev/null
+++ b/dotnet/samples/marketing/src/backend/appsettings.local.template.json
@@ -0,0 +1,34 @@
+{
+
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Information",
+ "Microsoft.AspNetCore.SignalR": "Debug",
+ "Microsoft.AspNetCore.Http.Connections": "Debug"
+ }
+ },
+
+ "ApplicationInsights": {
+ "ConnectionString": "InstrumentationKey=;IngestionEndpoint=https://.applicationinsights.azure.com/"
+ },
+
+ "AllowedHosts": "*",
+
+ "OpenAIOptions": {
+ "ChatDeploymentOrModelId": "gpt-4-32",
+ "ChatEndpoint": "https://.openai.azure.com/",
+ "ChatApiKey": "",
+ "EmbeddingsDeploymentOrModelId": "text-embedding-ada-002",
+ "EmbeddingsEndpoint": "https://.openai.azure.com/",
+ "EmbeddingsApiKey": "",
+ "ImageDeploymentOrModelId":"dalle3",
+ "ImageEndpoint": "https://.openai.azure.com/",
+ "ImageApiKey": ""
+ },
+
+ "QdrantOptions": {
+ "Endpoint": "http://qdrant:6333",
+ "VectorSize": "1536"
+ }
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/.eslintrc.json b/dotnet/samples/marketing/src/frontend/.eslintrc.json
new file mode 100644
index 0000000000..bffb357a71
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/dotnet/samples/marketing/src/frontend/.gitignore b/dotnet/samples/marketing/src/frontend/.gitignore
new file mode 100644
index 0000000000..6055b81e8e
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/.gitignore
@@ -0,0 +1,38 @@
+/.infra/
+
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/.npmrc b/dotnet/samples/marketing/src/frontend/.npmrc
new file mode 100644
index 0000000000..5aec3916e1
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/.npmrc
@@ -0,0 +1,2 @@
+legacy-peer-deps=true
+strict-peer-dependencies=false
diff --git a/dotnet/samples/marketing/src/frontend/Dockerfile b/dotnet/samples/marketing/src/frontend/Dockerfile
new file mode 100644
index 0000000000..8fa873779b
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/Dockerfile
@@ -0,0 +1,43 @@
+FROM refinedev/node:18 AS base
+
+FROM base AS deps
+
+RUN apk add --no-cache libc6-compat
+
+COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
+
+RUN \
+ if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
+ elif [ -f package-lock.json ]; then npm ci; \
+ elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
+ else echo "Lockfile not found." && exit 1; \
+ fi
+
+FROM base AS builder
+
+COPY --from=deps /app/refine/node_modules ./node_modules
+
+COPY . .
+
+RUN npm run build
+
+FROM base AS runner
+
+ENV NODE_ENV production
+
+COPY --from=builder /app/refine/public ./public
+
+RUN mkdir .next
+RUN chown refine:nodejs .next
+
+COPY --from=builder --chown=refine:nodejs /app/refine/.next/standalone ./
+COPY --from=builder --chown=refine:nodejs /app/refine/.next/static ./.next/static
+
+USER refine
+
+EXPOSE 3000
+
+ENV PORT 3000
+ENV HOSTNAME "0.0.0.0"
+
+CMD ["node", "server.js"]
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/README.MD b/dotnet/samples/marketing/src/frontend/README.MD
new file mode 100644
index 0000000000..79065783d8
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/README.MD
@@ -0,0 +1,11 @@
+## TODO: describe the frontend app
+
+## How I started
+```
+npm -i
+```
+
+## How to run it
+```shell
+ npm run dev
+```
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/next.config.mjs b/dotnet/samples/marketing/src/frontend/next.config.mjs
new file mode 100644
index 0000000000..338e10b538
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/next.config.mjs
@@ -0,0 +1,17 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: 'standalone',
+ images: {
+ domains: ['dalleproduse.blob.core.windows.net'],
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'dalleproduse.blob.core.windows.net',
+ port: '**',
+ pathname: '**',
+ },
+ ],
+ },
+};
+
+export default nextConfig;
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/package-lock.json b/dotnet/samples/marketing/src/frontend/package-lock.json
new file mode 100644
index 0000000000..c281c7f999
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/package-lock.json
@@ -0,0 +1,10363 @@
+{
+ "name": "Learning",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "Learning",
+ "version": "0.1.0",
+ "dependencies": {
+ "@emotion/react": "^11.8.2",
+ "@emotion/styled": "^11.8.1",
+ "@fontsource/roboto": "^4.5.8",
+ "@microsoft/signalr": "^8.0.0",
+ "@mui/icons-material": "^5.8.3",
+ "@mui/lab": "^5.0.0-alpha.85",
+ "@mui/material": "^5.8.6",
+ "@mui/x-data-grid": "^6.6.0",
+ "@refinedev/cli": "^2.16.21",
+ "@refinedev/core": "^4.47.1",
+ "@refinedev/devtools": "^1.1.32",
+ "@refinedev/kbar": "^1.3.6",
+ "@refinedev/mui": "^5.14.4",
+ "@refinedev/nextjs-router": "^6.0.0",
+ "@refinedev/react-hook-form": "^4.8.14",
+ "@refinedev/simple-rest": "^5.0.1",
+ "js-cookie": "^3.0.5",
+ "next": "14.1.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "react-flippy": "^1.1.0"
+ },
+ "devDependencies": {
+ "@types/js-cookie": "^3.0.6",
+ "@types/node": "^18.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "@typescript-eslint/parser": "5.48.0",
+ "cross-env": "^7.0.3",
+ "eslint": "^8",
+ "eslint-config-next": "14.1.0",
+ "typescript": "^4.7.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aliemir/dom-to-fiber-utils": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@aliemir/dom-to-fiber-utils/-/dom-to-fiber-utils-0.4.0.tgz",
+ "integrity": "sha512-QxJLBDQG4tMTv56yvAHeUdRVoocTYGUqyVHqUsATT7TMCgFj1JRcbzzUbdiwwIJ1d5loDUK5PesyKG2RY7t0iQ==",
+ "dependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "react-reconciler": "^0.29.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.24.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz",
+ "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==",
+ "dependencies": {
+ "@babel/highlight": "^7.24.2",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.24.4",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz",
+ "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz",
+ "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.24.2",
+ "@babel/generator": "^7.24.5",
+ "@babel/helper-compilation-targets": "^7.23.6",
+ "@babel/helper-module-transforms": "^7.24.5",
+ "@babel/helpers": "^7.24.5",
+ "@babel/parser": "^7.24.5",
+ "@babel/template": "^7.24.0",
+ "@babel/traverse": "^7.24.5",
+ "@babel/types": "^7.24.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz",
+ "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==",
+ "dependencies": {
+ "@babel/types": "^7.24.5",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.23.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz",
+ "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==",
+ "dependencies": {
+ "@babel/compat-data": "^7.23.5",
+ "@babel/helper-validator-option": "^7.23.5",
+ "browserslist": "^4.22.2",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz",
+ "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-member-expression-to-functions": "^7.24.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.24.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.24.5",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+ "dependencies": {
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz",
+ "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==",
+ "dependencies": {
+ "@babel/types": "^7.24.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.24.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz",
+ "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==",
+ "dependencies": {
+ "@babel/types": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz",
+ "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-module-imports": "^7.24.3",
+ "@babel/helper-simple-access": "^7.24.5",
+ "@babel/helper-split-export-declaration": "^7.24.5",
+ "@babel/helper-validator-identifier": "^7.24.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
+ "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz",
+ "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz",
+ "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-member-expression-to-functions": "^7.23.0",
+ "@babel/helper-optimise-call-expression": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz",
+ "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==",
+ "dependencies": {
+ "@babel/types": "^7.24.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
+ "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz",
+ "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==",
+ "dependencies": {
+ "@babel/types": "^7.24.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
+ "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz",
+ "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.23.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
+ "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz",
+ "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==",
+ "dependencies": {
+ "@babel/template": "^7.24.0",
+ "@babel/traverse": "^7.24.5",
+ "@babel/types": "^7.24.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.24.2",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz",
+ "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz",
+ "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-flow": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz",
+ "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz",
+ "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz",
+ "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz",
+ "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.24.1",
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-flow-strip-types": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz",
+ "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/plugin-syntax-flow": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz",
+ "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.23.3",
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/helper-simple-access": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz",
+ "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz",
+ "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz",
+ "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.24.1",
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.5.tgz",
+ "integrity": "sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-create-class-features-plugin": "^7.24.5",
+ "@babel/helper-plugin-utils": "^7.24.5",
+ "@babel/plugin-syntax-typescript": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-flow": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.1.tgz",
+ "integrity": "sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/helper-validator-option": "^7.23.5",
+ "@babel/plugin-transform-flow-strip-types": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz",
+ "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/helper-validator-option": "^7.23.5",
+ "@babel/plugin-syntax-jsx": "^7.24.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.1",
+ "@babel/plugin-transform-typescript": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/register": {
+ "version": "7.23.7",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz",
+ "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==",
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "find-cache-dir": "^2.0.0",
+ "make-dir": "^2.1.0",
+ "pirates": "^4.0.6",
+ "source-map-support": "^0.5.16"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz",
+ "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz",
+ "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==",
+ "dependencies": {
+ "@babel/code-frame": "^7.23.5",
+ "@babel/parser": "^7.24.0",
+ "@babel/types": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz",
+ "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.2",
+ "@babel/generator": "^7.24.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.24.5",
+ "@babel/parser": "^7.24.5",
+ "@babel/types": "^7.24.5",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz",
+ "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.24.1",
+ "@babel/helper-validator-identifier": "^7.24.5",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
+ "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/serialize": "^1.1.2",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
+ "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/sheet": "^1.2.2",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.11.4",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
+ "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/cache": "^11.11.0",
+ "@emotion/serialize": "^1.1.3",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz",
+ "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/unitless": "^0.8.1",
+ "@emotion/utils": "^1.2.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
+ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
+ },
+ "node_modules/@emotion/styled": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
+ "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.0.0-rc.0",
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
+ "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
+ "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
+ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@fireworks-js/react": {
+ "version": "2.10.7",
+ "resolved": "https://registry.npmjs.org/@fireworks-js/react/-/react-2.10.7.tgz",
+ "integrity": "sha512-hxfEB0vRUX7nNznhc5SEw0W8jamgF32oUiMvd5c8dOAFZgkidF8qylRw/V1Xp6In1QsjUQXnv/gvOKCe2o8JOg==",
+ "dependencies": {
+ "fireworks-js": "2.10.7"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8.0",
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.1"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
+ "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
+ "dependencies": {
+ "@floating-ui/core": "^1.0.0",
+ "@floating-ui/utils": "^0.2.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz",
+ "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.6.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
+ "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
+ },
+ "node_modules/@fontsource/roboto": {
+ "version": "4.5.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz",
+ "integrity": "sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA=="
+ },
+ "node_modules/@headlessui/react": {
+ "version": "1.7.19",
+ "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz",
+ "integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==",
+ "dependencies": {
+ "@tanstack/react-virtual": "^3.0.0-beta.60",
+ "client-only": "^0.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@microsoft/signalr": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-8.0.0.tgz",
+ "integrity": "sha512-K/wS/VmzRWePCGqGh8MU8OWbS1Zvu7DG7LSJS62fBB8rJUXwwj4axQtqrAAwKGUZHQF6CuteuQR9xMsVpM2JNA==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "eventsource": "^2.0.2",
+ "fetch-cookie": "^2.0.3",
+ "node-fetch": "^2.6.7",
+ "ws": "^7.4.5"
+ }
+ },
+ "node_modules/@microsoft/signalr/node_modules/ws": {
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+ "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/base": {
+ "version": "5.0.0-beta.40",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
+ "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@floating-ui/react-dom": "^2.0.8",
+ "@mui/types": "^7.2.14",
+ "@mui/utils": "^5.15.14",
+ "@popperjs/core": "^2.11.8",
+ "clsx": "^2.1.0",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/core-downloads-tracker": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz",
+ "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ }
+ },
+ "node_modules/@mui/icons-material": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.14.tgz",
+ "integrity": "sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.0.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/lab": {
+ "version": "5.0.0-alpha.169",
+ "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.169.tgz",
+ "integrity": "sha512-h6xe1K6ISKUbyxTDgdvql4qoDP6+q8ad5fg9nXQxGLUrIeT2jVrBuT/jRECSTufbnhzP+V5kulvYxaMfM8rEdA==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@mui/base": "5.0.0-beta.40",
+ "@mui/system": "^5.15.14",
+ "@mui/types": "^7.2.14",
+ "@mui/utils": "^5.15.14",
+ "clsx": "^2.1.0",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@mui/material": ">=5.15.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/material": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz",
+ "integrity": "sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@mui/base": "5.0.0-beta.40",
+ "@mui/core-downloads-tracker": "^5.15.14",
+ "@mui/system": "^5.15.14",
+ "@mui/types": "^7.2.14",
+ "@mui/utils": "^5.15.14",
+ "@types/react-transition-group": "^4.4.10",
+ "clsx": "^2.1.0",
+ "csstype": "^3.1.3",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "react-transition-group": "^4.4.5"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/private-theming": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz",
+ "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@mui/utils": "^5.15.14",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/styled-engine": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz",
+ "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@emotion/cache": "^11.11.0",
+ "csstype": "^3.1.3",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.4.1",
+ "@emotion/styled": "^11.3.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/system": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz",
+ "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@mui/private-theming": "^5.15.14",
+ "@mui/styled-engine": "^5.15.14",
+ "@mui/types": "^7.2.14",
+ "@mui/utils": "^5.15.14",
+ "clsx": "^2.1.0",
+ "csstype": "^3.1.3",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/types": {
+ "version": "7.2.14",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz",
+ "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==",
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/utils": {
+ "version": "5.15.14",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz",
+ "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@types/prop-types": "^15.7.11",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/x-data-grid": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.19.8.tgz",
+ "integrity": "sha512-QsOW9GhJdhvagJfUb5jpZE1MMaCLugxx0l89amxJAthMia95BlGS7jndiDEh8IQNthgzfxjAzrSv8GZpcgSEaA==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "@mui/utils": "^5.14.16",
+ "clsx": "^2.0.0",
+ "prop-types": "^15.8.1",
+ "reselect": "^4.1.8"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.4.1",
+ "@mui/system": "^5.4.1",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.0.tgz",
+ "integrity": "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw=="
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz",
+ "integrity": "sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==",
+ "dev": true,
+ "dependencies": {
+ "glob": "10.3.10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz",
+ "integrity": "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz",
+ "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz",
+ "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz",
+ "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz",
+ "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz",
+ "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz",
+ "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz",
+ "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz",
+ "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@ory/client": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@ory/client/-/client-1.9.0.tgz",
+ "integrity": "sha512-O4a1ijgJtMNIA+ZmWUmCodxX13ID72hOaCB0b9FQGQBzuFgF2x/Yq5D43nrMYZaDtvDvja8J1XIXhUkjz1TDOw==",
+ "dependencies": {
+ "axios": "^1.6.1"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
+ "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz",
+ "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-primitive": "1.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
+ "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-slot": "1.0.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
+ "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@reach/observe-rect": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@reach/observe-rect/-/observe-rect-1.2.0.tgz",
+ "integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ=="
+ },
+ "node_modules/@refinedev/cli": {
+ "version": "2.16.29",
+ "resolved": "https://registry.npmjs.org/@refinedev/cli/-/cli-2.16.29.tgz",
+ "integrity": "sha512-jfVI/QRyGlCfMEucIwvXc+V8w9flUN6mjsa0b/UGxb9a2aAO5K//vJCWupKF4wiTnmOQDveZ/Rgr/nTvdw0kkg==",
+ "dependencies": {
+ "@refinedev/devtools-server": "1.1.27",
+ "boxen": "^5.1.2",
+ "cardinal": "^2.1.1",
+ "center-align": "1.0.1",
+ "chalk": "^4.1.2",
+ "cli-table3": "^0.6.3",
+ "commander": "9.4.1",
+ "conf": "^10.2.0",
+ "decamelize": "^5.0.0",
+ "dedent": "^0.7.0",
+ "dotenv": "^16.0.3",
+ "envinfo": "^7.8.1",
+ "execa": "^5.1.1",
+ "express": "^4.18.2",
+ "figlet": "^1.5.2",
+ "fs-extra": "^10.1.0",
+ "globby": "^11.1.0",
+ "gray-matter": "^4.0.3",
+ "handlebars": "^4.7.7",
+ "http-proxy-middleware": "^2.0.6",
+ "inquirer": "^8.2.5",
+ "inquirer-autocomplete-prompt": "^2.0.0",
+ "jscodeshift": "0.15.2",
+ "marked": "^4.3.0",
+ "marked-terminal": "^6.0.0",
+ "node-emoji": "^2.1.3",
+ "node-env-type": "^0.0.8",
+ "node-fetch": "^2.6.7",
+ "ora": "^5.4.1",
+ "pluralize": "^8.0.0",
+ "preferred-pm": "^3.0.3",
+ "prettier": "^2.7.1",
+ "semver": "7.5.2",
+ "semver-diff": "^3.1.1",
+ "temp": "^0.9.4",
+ "tslib": "^2.6.2"
+ },
+ "bin": {
+ "refine": "dist/cli.cjs"
+ }
+ },
+ "node_modules/@refinedev/core": {
+ "version": "4.48.0",
+ "resolved": "https://registry.npmjs.org/@refinedev/core/-/core-4.48.0.tgz",
+ "integrity": "sha512-rJWtP8jFkBmNzibUBIAYKapjC2MOYuu3xCxPEhtZJY2qCxwbVSxBsDKiCFe5fd84+EuJr7sqjFPujJdhKrK57g==",
+ "dependencies": {
+ "@refinedev/devtools-internal": "1.1.6",
+ "@tanstack/react-query": "^4.10.1",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "papaparse": "^5.3.0",
+ "pluralize": "^8.0.0",
+ "qs": "^6.10.1",
+ "tslib": "^2.3.1",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "@tanstack/react-query": "^4.10.1",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools": {
+ "version": "1.1.35",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools/-/devtools-1.1.35.tgz",
+ "integrity": "sha512-jCyiADzrv6T+uJTUhf7sZ3ZoLZl2DhALUYRTTQs1pNnd/PpEQuYORCfTyjLqUjQSOi9yXdkGJUN/gpuIuHVD7g==",
+ "dependencies": {
+ "@aliemir/dom-to-fiber-utils": "^0.4.0",
+ "@refinedev/devtools-shared": "1.1.4",
+ "error-stack-parser": "^2.1.4",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@refinedev/cli": "2.16.27",
+ "@refinedev/core": "^4.46.1",
+ "@refinedev/devtools-server": "1.1.25",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-internal": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-internal/-/devtools-internal-1.1.6.tgz",
+ "integrity": "sha512-5RMv8euyngJDJGyPa97o2d/h9qKZGvIzIjBbnjm0+teO6+Q9ADPCIOVwtC0ZgqEiEQMmPS8k+qD7UZuFJStIHg==",
+ "dependencies": {
+ "@refinedev/devtools-shared": "1.1.4",
+ "@tanstack/react-query": "^4.10.1",
+ "error-stack-parser": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-server": {
+ "version": "1.1.27",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-server/-/devtools-server-1.1.27.tgz",
+ "integrity": "sha512-Tu63sxPox+FnXrxjxGVkK/9ODPaQTPjSbLrCfMP1AcJY6CJlaQFj37ZWsp6tOgkU45FcHOf7B+t81P4GXLOMSQ==",
+ "dependencies": {
+ "@ory/client": "^1.5.2",
+ "@refinedev/devtools-shared": "1.1.5",
+ "@refinedev/devtools-ui": "1.1.20",
+ "body-parser": "^1.20.2",
+ "boxen": "^5.1.2",
+ "chalk": "^4.1.2",
+ "dedent": "^0.7.0",
+ "error-stack-parser": "^2.1.4",
+ "execa": "^5.1.1",
+ "express": "^4.18.2",
+ "fs-extra": "^10.1.0",
+ "globby": "^11.1.0",
+ "gray-matter": "^4.0.3",
+ "http-proxy-middleware": "^2.0.6",
+ "jscodeshift": "0.15.2",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "marked": "^4.3.0",
+ "node-fetch": "^2.6.7",
+ "preferred-pm": "^3.0.3",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "sanitize-html": "^2.11.0",
+ "ws": "^8.13.0"
+ },
+ "bin": {
+ "refine-devtools": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-server/node_modules/@refinedev/devtools-shared": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.5.tgz",
+ "integrity": "sha512-2WUmiKj337xjaQBpaJHj3ahFjhtx7rD/+sID+vMp5N7abdtSUiMebn5bk9ty7BAj+CCnw0J4MRqFg1XNjYieHQ==",
+ "dependencies": {
+ "@tanstack/react-query": "^4.10.1",
+ "error-stack-parser": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-shared": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.4.tgz",
+ "integrity": "sha512-YMVRGVmck0UyV5UoIW82EMCSFm2E1ejjXYWzqTiaiZgU5tbLR4NZf8W10enyxtCLzUPONFF5uvFc6tMleodXYA==",
+ "dependencies": {
+ "@tanstack/react-query": "^4.10.1",
+ "error-stack-parser": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-ui": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-ui/-/devtools-ui-1.1.20.tgz",
+ "integrity": "sha512-QbG4PxfcurMyZLPfO2QZVdv0IrDUAlhrEyjemWDH37Zyvri8KNaopj3aLexNUFScWXeaZcSeAiqyKQV8YPyeeA==",
+ "dependencies": {
+ "@fireworks-js/react": "^2.10.7",
+ "@headlessui/react": "^1.7.17",
+ "@ory/client": "^1.5.2",
+ "@refinedev/devtools-shared": "1.1.5",
+ "@tanstack/react-table": "^8.2.6",
+ "clsx": "^1.1.1",
+ "dayjs": "^1.10.7",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "prism-react-renderer": "^1.3.5",
+ "react-gravatar": "^2.6.3",
+ "react-json-view": "^1.21.3",
+ "react-router-dom": "^6.8.1",
+ "semver-diff": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-ui/node_modules/@refinedev/devtools-shared": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.5.tgz",
+ "integrity": "sha512-2WUmiKj337xjaQBpaJHj3ahFjhtx7rD/+sID+vMp5N7abdtSUiMebn5bk9ty7BAj+CCnw0J4MRqFg1XNjYieHQ==",
+ "dependencies": {
+ "@tanstack/react-query": "^4.10.1",
+ "error-stack-parser": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/devtools-ui/node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@refinedev/kbar": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/@refinedev/kbar/-/kbar-1.3.7.tgz",
+ "integrity": "sha512-fOeqdc2/zn+WI+kRBQAiI2cPRbT2vYLYFbTceBkPu1wLz5FCfgyylyHslHhNtEYkXbgvitG4E1xrYB58SgQuAQ==",
+ "dependencies": {
+ "kbar": "^0.1.0-beta.40"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@refinedev/core": "^4.46.1",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/mui": {
+ "version": "5.14.5",
+ "resolved": "https://registry.npmjs.org/@refinedev/mui/-/mui-5.14.5.tgz",
+ "integrity": "sha512-XT9ZvaLoit2QhAVVyNvb7at9DBlp7bpi4ztSzTi1LUzMEAnKK+hbsa/IuwahmOsgbfZpLFYKVu0jHBngoBeDwg==",
+ "dependencies": {
+ "@emotion/react": "^11.8.2",
+ "@emotion/styled": "^11.8.1",
+ "@mui/icons-material": "^5.8.3",
+ "@mui/lab": "^5.0.0-alpha.85",
+ "@mui/material": "^5.14.2",
+ "@mui/x-data-grid": "^6.6.0",
+ "@refinedev/react-hook-form": "^4.8.15",
+ "@refinedev/ui-types": "^1.22.4",
+ "dayjs": "^1.10.7",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "notistack": "^2.0.4",
+ "react-hook-form": "^7.30.0",
+ "react-markdown": "^6.0.1",
+ "remark-gfm": "^1.0.0",
+ "tslib": "^2.3.1",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.8.2",
+ "@emotion/styled": "^11.8.1",
+ "@mui/lab": "^5.0.0-alpha.85",
+ "@mui/material": "^5.14.2",
+ "@mui/x-data-grid": "^6.6.0",
+ "@refinedev/core": "^4.46.1",
+ "@refinedev/react-hook-form": "^4.0.0",
+ "dayjs": "^1.10.7",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0",
+ "react-hook-form": "^7.30.0"
+ }
+ },
+ "node_modules/@refinedev/nextjs-router": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@refinedev/nextjs-router/-/nextjs-router-6.0.1.tgz",
+ "integrity": "sha512-qbJK9mWgvKHI2jS5kBesyL2OcR4+ew5ntR0fD96V4QTmx7WVP1rAh7gLZUKU6OaHQK/Ca1nYZ+rqT1AP3hMOgA==",
+ "dependencies": {
+ "qs": "^6.10.1",
+ "warn-once": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@refinedev/core": "^4.46.1",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "next": "*",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@refinedev/react-hook-form": {
+ "version": "4.8.15",
+ "resolved": "https://registry.npmjs.org/@refinedev/react-hook-form/-/react-hook-form-4.8.15.tgz",
+ "integrity": "sha512-lhz3Y9d0iK93ytms692QvNXw5u6GrS8yp8th9wsNKwcyUavE62KzmYMOrc8f2JhzoLkhmzTrnjr31K3Dm0BnhA==",
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-hook-form": "^7.30.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@refinedev/core": "^4.46.1",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0",
+ "react-hook-form": "^7.30.0"
+ }
+ },
+ "node_modules/@refinedev/simple-rest": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@refinedev/simple-rest/-/simple-rest-5.0.3.tgz",
+ "integrity": "sha512-6b+np4f8kNGxoZiZ8YoC2gEoFV/zlsFfTHNK0KI2XmCpeG5SDCDC9T4leMkntzai8Kn4AhLeVx7+005d+Ww+qA==",
+ "dependencies": {
+ "axios": "^1.6.2",
+ "query-string": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@refinedev/core": "^4.46.1"
+ }
+ },
+ "node_modules/@refinedev/ui-types": {
+ "version": "1.22.4",
+ "resolved": "https://registry.npmjs.org/@refinedev/ui-types/-/ui-types-1.22.4.tgz",
+ "integrity": "sha512-IMgDazFSePPO7BDOfnGnrvfi/2onnSAmtaujkW9sPEibb+sjaJ7SX7NJLqI5Zp8w/hb0T0tO4ezGFvaFVVPoYw==",
+ "dependencies": {
+ "@refinedev/core": "^4.46.1",
+ "dayjs": "^1.10.7",
+ "tslib": "^2.3.1"
+ },
+ "peerDependencies": {
+ "@refinedev/core": "^4.46.1",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.0.tgz",
+ "integrity": "sha512-Quz1KOffeEf/zwkCBM3kBtH4ZoZ+pT3xIXBG4PPW/XFtDP7EGhtTiC2+gpL9GnR7+Qdet5Oa6cYSvwKYg6kN9Q==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.8.0.tgz",
+ "integrity": "sha512-0HejFckBN2W+ucM6cUOlwsByTKt9/+0tWhqUffNIcHqCXkthY/mZ7AuYPK/2IIaGWhdl0h+tICDO0ssLMd6XMQ==",
+ "dev": true
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
+ "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tanstack/query-core": {
+ "version": "4.36.1",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.36.1.tgz",
+ "integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-query": {
+ "version": "4.36.1",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.36.1.tgz",
+ "integrity": "sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==",
+ "dependencies": {
+ "@tanstack/query-core": "4.36.1",
+ "use-sync-external-store": "^1.2.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@tanstack/react-table": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.16.0.tgz",
+ "integrity": "sha512-rKRjnt8ostqN2fercRVOIH/dq7MAmOENCMvVlKx6P9Iokhh6woBGnIZEkqsY/vEJf1jN3TqLOb34xQGLVRuhAg==",
+ "dependencies": {
+ "@tanstack/table-core": "8.16.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/@tanstack/react-virtual": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz",
+ "integrity": "sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==",
+ "dependencies": {
+ "@tanstack/virtual-core": "3.5.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@tanstack/table-core": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.16.0.tgz",
+ "integrity": "sha512-dCG8vQGk4js5v88/k83tTedWOwjGnIyONrKpHpfmSJB8jwFHl8GSu1sBBxbtACVAPtAQgwNxl0rw1d3RqRM1Tg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/virtual-core": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz",
+ "integrity": "sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
+ "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.14",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz",
+ "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/js-cookie": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
+ "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/mdast": {
+ "version": "3.0.15",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
+ "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "18.19.26",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz",
+ "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.11",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
+ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
+ },
+ "node_modules/@types/react": {
+ "version": "18.2.67",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.67.tgz",
+ "integrity": "sha512-vkIE2vTIMHQ/xL0rgmuoECBCkZFZeHr49HeWSc24AptMbNRo7pwSBvj73rlJJs9fGKj0koS+V7kQB1jHS0uCgw==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.2.22",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz",
+ "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.10",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
+ "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
+ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
+ "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.0.tgz",
+ "integrity": "sha512-1mxNA8qfgxX8kBvRDIHEzrRGrKHQfQlbW6iHyfHYS0Q4X1af+S6mkLNtgCOsGVl8+/LUPrqdHMssAemkrQ01qg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.48.0",
+ "@typescript-eslint/types": "5.48.0",
+ "@typescript-eslint/typescript-estree": "5.48.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.0.tgz",
+ "integrity": "sha512-0AA4LviDtVtZqlyUQnZMVHydDATpD9SAX/RC5qh6cBd3xmyWvmXYF+WT1oOmxkeMnWDlUVTwdODeucUnjz3gow==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.48.0",
+ "@typescript-eslint/visitor-keys": "5.48.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.0.tgz",
+ "integrity": "sha512-UTe67B0Ypius0fnEE518NB2N8gGutIlTojeTg4nt0GQvikReVkurqxd2LvYa9q9M5MQ6rtpNyWTBxdscw40Xhw==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.0.tgz",
+ "integrity": "sha512-7pjd94vvIjI1zTz6aq/5wwE/YrfIyEPLtGJmRfyNR9NYIW+rOvzzUv3Cmq2hRKpvt6e9vpvPUQ7puzX7VSmsEw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.48.0",
+ "@typescript-eslint/visitor-keys": "5.48.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.0.tgz",
+ "integrity": "sha512-5motVPz5EgxQ0bHjut3chzBkJ3Z3sheYVcSwS5BpHZpLqSptSmELNtGixmgj65+rIfhvtQTz5i9OP2vtzdDH7Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.48.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/align-text": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-1.0.2.tgz",
+ "integrity": "sha512-uBPDs72zrRTdiTBY0YjBbuBOdXtRyT4qsKPb4bL4O7vH4utz/7KjwTJVsVbdThxMbVzkRGAfk8Ml3xoMvXSEYw==",
+ "dependencies": {
+ "kind-of": "^5.0.2",
+ "longest": "^2.0.1",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/ansicolors": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+ "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg=="
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
+ "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.toreversed": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz",
+ "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz",
+ "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.1.0",
+ "es-shim-unscopables": "^1.0.2"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.2.1",
+ "get-intrinsic": "^1.2.3",
+ "is-array-buffer": "^3.0.4",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
+ },
+ "node_modules/ast-types": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
+ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/atomically": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
+ "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
+ "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
+ "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/babel-core": {
+ "version": "7.0.0-bridge.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
+ "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/bail": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
+ "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base16": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
+ "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/body-parser/node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/boxen": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+ "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+ "dependencies": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.23.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+ "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001587",
+ "electron-to-chromium": "^1.4.668",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001599",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz",
+ "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/cardinal": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
+ "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==",
+ "dependencies": {
+ "ansicolors": "~0.3.2",
+ "redeyed": "~2.1.0"
+ },
+ "bin": {
+ "cdl": "bin/cdl.js"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz",
+ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/center-align": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-1.0.1.tgz",
+ "integrity": "sha512-j6Ba1Vwtu0i9CUfM5VicnMqOsNRMYnNAoTUTB/EzUFhBKkqFPD5UE2WTCSIy49OnbjTEnJ0t2CFPYMbKNrUi/A==",
+ "dependencies": {
+ "align-text": "^1.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-table3": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
+ "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==",
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clone-deep/node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz",
+ "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/conf": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz",
+ "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==",
+ "dependencies": {
+ "ajv": "^8.6.3",
+ "ajv-formats": "^2.1.1",
+ "atomically": "^1.7.0",
+ "debounce-fn": "^4.0.0",
+ "dot-prop": "^6.0.1",
+ "env-paths": "^2.2.1",
+ "json-schema-typed": "^7.0.3",
+ "onetime": "^5.1.2",
+ "pkg-up": "^3.1.0",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ },
+ "node_modules/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ },
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cross-env": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
+ "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.1"
+ },
+ "bin": {
+ "cross-env": "src/bin/cross-env.js",
+ "cross-env-shell": "src/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=10.14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/cross-fetch": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
+ "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
+ "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
+ "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.10",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
+ "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
+ },
+ "node_modules/debounce-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz",
+ "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
+ "dependencies": {
+ "mimic-fn": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz",
+ "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decode-uri-component": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+ "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.756",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.756.tgz",
+ "integrity": "sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/emojilib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz",
+ "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw=="
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.16.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz",
+ "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.11.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz",
+ "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==",
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.23.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz",
+ "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "arraybuffer.prototype.slice": "^1.0.3",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "data-view-buffer": "^1.0.1",
+ "data-view-byte-length": "^1.0.1",
+ "data-view-byte-offset": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-set-tostringtag": "^2.0.3",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.4",
+ "get-symbol-description": "^1.0.2",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.3",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.0.7",
+ "is-array-buffer": "^3.0.4",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.1",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.3",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.13",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.13.1",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.5",
+ "regexp.prototype.flags": "^1.5.2",
+ "safe-array-concat": "^1.1.2",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.trim": "^1.2.9",
+ "string.prototype.trimend": "^1.0.8",
+ "string.prototype.trimstart": "^1.0.7",
+ "typed-array-buffer": "^1.0.2",
+ "typed-array-byte-length": "^1.0.1",
+ "typed-array-byte-offset": "^1.0.2",
+ "typed-array-length": "^1.0.5",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.15"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.18",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz",
+ "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.3",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.3",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "iterator.prototype": "^1.1.2",
+ "safe-array-concat": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.0.tgz",
+ "integrity": "sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==",
+ "dev": true,
+ "dependencies": {
+ "@next/eslint-plugin-next": "14.1.0",
+ "@rushstack/eslint-patch": "^1.3.3",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.28.1",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz",
+ "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "enhanced-resolve": "^5.12.0",
+ "eslint-module-utils": "^2.7.4",
+ "fast-glob": "^3.3.1",
+ "get-tsconfig": "^4.5.0",
+ "is-core-module": "^2.11.0",
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz",
+ "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
+ "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlastindex": "^1.2.3",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.8.0",
+ "hasown": "^2.0.0",
+ "is-core-module": "^2.13.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.7",
+ "object.groupby": "^1.0.1",
+ "object.values": "^1.1.7",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
+ "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "aria-query": "^5.3.0",
+ "array-includes": "^3.1.7",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "=4.7.0",
+ "axobject-query": "^3.2.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "es-iterator-helpers": "^1.0.15",
+ "hasown": "^2.0.0",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.7",
+ "object.fromentries": "^2.0.7"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.34.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz",
+ "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlast": "^1.2.4",
+ "array.prototype.flatmap": "^1.3.2",
+ "array.prototype.toreversed": "^1.1.2",
+ "array.prototype.tosorted": "^1.1.3",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.0.17",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.7",
+ "object.fromentries": "^2.0.7",
+ "object.hasown": "^1.1.3",
+ "object.values": "^1.1.7",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.10"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ },
+ "node_modules/eventsource": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
+ "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.2",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.6.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/express/node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-equals": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-2.0.4.tgz",
+ "integrity": "sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w=="
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fbemitter": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz",
+ "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==",
+ "dependencies": {
+ "fbjs": "^3.0.0"
+ }
+ },
+ "node_modules/fbjs": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz",
+ "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==",
+ "dependencies": {
+ "cross-fetch": "^3.1.5",
+ "fbjs-css-vars": "^1.0.0",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^1.0.35"
+ }
+ },
+ "node_modules/fbjs-css-vars": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
+ "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
+ },
+ "node_modules/fetch-cookie": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz",
+ "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==",
+ "dependencies": {
+ "set-cookie-parser": "^2.4.8",
+ "tough-cookie": "^4.0.0"
+ }
+ },
+ "node_modules/figlet": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.7.0.tgz",
+ "integrity": "sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==",
+ "bin": {
+ "figlet": "bin/index.js"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/figures/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/filter-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
+ "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dependencies": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2": {
+ "version": "1.2.16",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz",
+ "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==",
+ "dependencies": {
+ "micromatch": "^4.0.2",
+ "pkg-dir": "^4.2.0"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2/node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fireworks-js": {
+ "version": "2.10.7",
+ "resolved": "https://registry.npmjs.org/fireworks-js/-/fireworks-js-2.10.7.tgz",
+ "integrity": "sha512-FyRNiqlgu9ZeFCjfN0UiGUlj5dUWNYLyFaWN/Q8sOMf0E+KGA4dMROaBZpCtym85fChgCspoa3jHoLTRZiy74A=="
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/flow-parser": {
+ "version": "0.235.1",
+ "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.235.1.tgz",
+ "integrity": "sha512-s04193L4JE+ntEcQXbD6jxRRlyj9QXcgEl2W6xSjH4l9x4b0eHoCHfbYHjqf9LdZFUiM5LhgpiqsvLj/AyOyYQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/flux": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.4.tgz",
+ "integrity": "sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==",
+ "dependencies": {
+ "fbemitter": "^3.0.0",
+ "fbjs": "^3.0.1"
+ },
+ "peerDependencies": {
+ "react": "^15.0.2 || ^16.0.0 || ^17.0.0"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/fuse.js": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
+ "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.7.3",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz",
+ "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/gray-matter": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
+ "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
+ "dependencies": {
+ "js-yaml": "^3.13.1",
+ "kind-of": "^6.0.2",
+ "section-matter": "^1.0.0",
+ "strip-bom-string": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/gray-matter/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/gray-matter/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/gray-matter/node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/handlebars/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/http-proxy-middleware": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
+ "dependencies": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
+ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
+ },
+ "node_modules/inquirer": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
+ "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/inquirer-autocomplete-prompt": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-2.0.1.tgz",
+ "integrity": "sha512-jUHrH0btO7j5r8DTQgANf2CBkTZChoVySD8zF/wp5fZCOLIuUbleXhf4ZY5jNBOc1owA3gdfWtfZuppfYBhcUg==",
+ "dependencies": {
+ "ansi-escapes": "^4.3.2",
+ "figures": "^3.2.0",
+ "picocolors": "^1.0.0",
+ "run-async": "^2.4.1",
+ "rxjs": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "inquirer": "^8.0.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
+ "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+ "dev": true,
+ "dependencies": {
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-retina": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-retina/-/is-retina-1.0.3.tgz",
+ "integrity": "sha512-/tCmbIETZwCd8uHWO+GvbRa7jxwHFHdfetHfiwoP0aN9UDf3prUJMtKn7iBFYipYhqY1bSTjur8hC/Dakt8eyw=="
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz",
+ "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.4",
+ "set-function-name": "^2.0.1"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+ "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jscodeshift": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz",
+ "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==",
+ "dependencies": {
+ "@babel/core": "^7.23.0",
+ "@babel/parser": "^7.23.0",
+ "@babel/plugin-transform-class-properties": "^7.22.5",
+ "@babel/plugin-transform-modules-commonjs": "^7.23.0",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
+ "@babel/plugin-transform-optional-chaining": "^7.23.0",
+ "@babel/plugin-transform-private-methods": "^7.22.5",
+ "@babel/preset-flow": "^7.22.15",
+ "@babel/preset-typescript": "^7.23.0",
+ "@babel/register": "^7.22.15",
+ "babel-core": "^7.0.0-bridge.0",
+ "chalk": "^4.1.2",
+ "flow-parser": "0.*",
+ "graceful-fs": "^4.2.4",
+ "micromatch": "^4.0.4",
+ "neo-async": "^2.5.0",
+ "node-dir": "^0.1.17",
+ "recast": "^0.23.3",
+ "temp": "^0.8.4",
+ "write-file-atomic": "^2.3.0"
+ },
+ "bin": {
+ "jscodeshift": "bin/jscodeshift.js"
+ },
+ "peerDependencies": {
+ "@babel/preset-env": "^7.1.6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/preset-env": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jscodeshift/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/temp": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz",
+ "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==",
+ "dependencies": {
+ "rimraf": "~2.6.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+ },
+ "node_modules/json-schema-typed": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
+ "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A=="
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/kbar": {
+ "version": "0.1.0-beta.45",
+ "resolved": "https://registry.npmjs.org/kbar/-/kbar-0.1.0-beta.45.tgz",
+ "integrity": "sha512-kXvjthqPLoWZXlxLJPrFKioskNdQv1O3Ukg5mqq2ExK3Ix1qvYT3W/ACDRIv/e/CHxPWZoTriB4oFbQ6UCSX5g==",
+ "dependencies": {
+ "@radix-ui/react-portal": "^1.0.1",
+ "fast-equals": "^2.0.3",
+ "fuse.js": "^6.6.2",
+ "react-virtual": "^2.8.2",
+ "tiny-invariant": "^1.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/load-yaml-file": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz",
+ "integrity": "sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==",
+ "dependencies": {
+ "graceful-fs": "^4.1.5",
+ "js-yaml": "^3.13.0",
+ "pify": "^4.0.1",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/load-yaml-file/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/load-yaml-file/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
+ "node_modules/lodash.curry": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
+ "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
+ },
+ "node_modules/lodash.flow": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
+ "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/longest": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz",
+ "integrity": "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/longest-streak": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
+ "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dependencies": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dependencies": {
+ "repeat-string": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/marked": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
+ "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/marked-terminal": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz",
+ "integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==",
+ "dependencies": {
+ "ansi-escapes": "^6.2.0",
+ "cardinal": "^2.1.1",
+ "chalk": "^5.3.0",
+ "cli-table3": "^0.6.3",
+ "node-emoji": "^2.1.3",
+ "supports-hyperlinks": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "marked": ">=1 <12"
+ }
+ },
+ "node_modules/marked-terminal/node_modules/ansi-escapes": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz",
+ "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==",
+ "dependencies": {
+ "type-fest": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/marked-terminal/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/marked-terminal/node_modules/type-fest": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
+ "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
+ "node_modules/mdast-util-definitions": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz",
+ "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==",
+ "dependencies": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-find-and-replace": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz",
+ "integrity": "sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA==",
+ "dependencies": {
+ "escape-string-regexp": "^4.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-from-markdown": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
+ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "micromark": "~2.11.0",
+ "parse-entities": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz",
+ "integrity": "sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ==",
+ "dependencies": {
+ "mdast-util-gfm-autolink-literal": "^0.1.0",
+ "mdast-util-gfm-strikethrough": "^0.2.0",
+ "mdast-util-gfm-table": "^0.1.0",
+ "mdast-util-gfm-task-list-item": "^0.1.0",
+ "mdast-util-to-markdown": "^0.6.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-autolink-literal": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz",
+ "integrity": "sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A==",
+ "dependencies": {
+ "ccount": "^1.0.0",
+ "mdast-util-find-and-replace": "^1.1.0",
+ "micromark": "^2.11.3"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-strikethrough": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz",
+ "integrity": "sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA==",
+ "dependencies": {
+ "mdast-util-to-markdown": "^0.6.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-table": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz",
+ "integrity": "sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ==",
+ "dependencies": {
+ "markdown-table": "^2.0.0",
+ "mdast-util-to-markdown": "~0.6.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-task-list-item": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz",
+ "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==",
+ "dependencies": {
+ "mdast-util-to-markdown": "~0.6.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz",
+ "integrity": "sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "mdast-util-definitions": "^4.0.0",
+ "mdurl": "^1.0.0",
+ "unist-builder": "^2.0.0",
+ "unist-util-generated": "^1.0.0",
+ "unist-util-position": "^3.0.0",
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
+ "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "longest-streak": "^2.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.0.0",
+ "zwitch": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
+ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromark": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
+ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "debug": "^4.0.0",
+ "parse-entities": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-extension-gfm": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz",
+ "integrity": "sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A==",
+ "dependencies": {
+ "micromark": "~2.11.0",
+ "micromark-extension-gfm-autolink-literal": "~0.5.0",
+ "micromark-extension-gfm-strikethrough": "~0.6.5",
+ "micromark-extension-gfm-table": "~0.4.0",
+ "micromark-extension-gfm-tagfilter": "~0.3.0",
+ "micromark-extension-gfm-task-list-item": "~0.3.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-autolink-literal": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz",
+ "integrity": "sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw==",
+ "dependencies": {
+ "micromark": "~2.11.3"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-strikethrough": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz",
+ "integrity": "sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw==",
+ "dependencies": {
+ "micromark": "~2.11.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-table": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz",
+ "integrity": "sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA==",
+ "dependencies": {
+ "micromark": "~2.11.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-tagfilter": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz",
+ "integrity": "sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-task-list-item": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz",
+ "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==",
+ "dependencies": {
+ "micromark": "~2.11.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
+ "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+ },
+ "node_modules/next": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.1.0.tgz",
+ "integrity": "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==",
+ "dependencies": {
+ "@next/env": "14.1.0",
+ "@swc/helpers": "0.5.2",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001579",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.1.0",
+ "@next/swc-darwin-x64": "14.1.0",
+ "@next/swc-linux-arm64-gnu": "14.1.0",
+ "@next/swc-linux-arm64-musl": "14.1.0",
+ "@next/swc-linux-x64-gnu": "14.1.0",
+ "@next/swc-linux-x64-musl": "14.1.0",
+ "@next/swc-win32-arm64-msvc": "14.1.0",
+ "@next/swc-win32-ia32-msvc": "14.1.0",
+ "@next/swc-win32-x64-msvc": "14.1.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-dir": {
+ "version": "0.1.17",
+ "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
+ "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==",
+ "dependencies": {
+ "minimatch": "^3.0.2"
+ },
+ "engines": {
+ "node": ">= 0.10.5"
+ }
+ },
+ "node_modules/node-emoji": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz",
+ "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==",
+ "dependencies": {
+ "@sindresorhus/is": "^4.6.0",
+ "char-regex": "^1.0.2",
+ "emojilib": "^2.4.0",
+ "skin-tone": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/node-env-type": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/node-env-type/-/node-env-type-0.0.8.tgz",
+ "integrity": "sha512-EXyxUOlwkuoMm6QHgX3zw06tY6NNpXm3Akf9n1zPUX8UD08FTXBQ9gcS0EWbuSPYqtxMneP72QgdPlLFrn2SpA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
+ },
+ "node_modules/notistack": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/notistack/-/notistack-2.0.8.tgz",
+ "integrity": "sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==",
+ "dependencies": {
+ "clsx": "^1.1.0",
+ "hoist-non-react-statics": "^3.3.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/notistack"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.4.1",
+ "@emotion/styled": "^11.3.0",
+ "@mui/material": "^5.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/notistack/node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.hasown": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
+ "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
+ "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/onetime/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dev": true,
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/papaparse": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
+ "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dependencies": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-srcset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
+ "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q=="
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
+ "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
+ "dev": true,
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dependencies": {
+ "find-up": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pkg-up": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
+ "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+ "dependencies": {
+ "find-up": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-up/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/preferred-pm": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.3.tgz",
+ "integrity": "sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==",
+ "dependencies": {
+ "find-up": "^5.0.0",
+ "find-yarn-workspace-root2": "1.2.16",
+ "path-exists": "^4.0.0",
+ "which-pm": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prism-react-renderer": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz",
+ "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==",
+ "peerDependencies": {
+ "react": ">=0.14.9"
+ }
+ },
+ "node_modules/promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dependencies": {
+ "asap": "~2.0.3"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/property-information": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
+ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-color": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
+ "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA=="
+ },
+ "node_modules/qs": {
+ "version": "6.12.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz",
+ "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/query-string": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
+ "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
+ "dependencies": {
+ "decode-uri-component": "^0.2.2",
+ "filter-obj": "^1.1.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-base16-styling": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz",
+ "integrity": "sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==",
+ "dependencies": {
+ "base16": "^1.0.0",
+ "lodash.curry": "^4.0.1",
+ "lodash.flow": "^3.3.0",
+ "pure-color": "^1.2.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-flippy": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/react-flippy/-/react-flippy-1.1.0.tgz",
+ "integrity": "sha512-fMaHrGL2HeyYq4ohl65b4EZG5JAawL6NMSiSOhhI68l54nortHvJBqHi5DeR1sF44/4RN2jeNsBXSXuBnOj7Vg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.0"
+ },
+ "peerDependencies": {
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2"
+ }
+ },
+ "node_modules/react-gravatar": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/react-gravatar/-/react-gravatar-2.6.3.tgz",
+ "integrity": "sha512-yITonigS2LmG7Fw0gWfZfcVwy1mpiBHNVmoFyetitQjXu7JCYoE6jtub0GIfq+ydpnQSYyJT3kwpX6zj1wXR4w==",
+ "dependencies": {
+ "is-retina": "^1.0.3",
+ "md5": "^2.1.0",
+ "query-string": "^4.2.2"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/react-gravatar/node_modules/query-string": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
+ "integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==",
+ "dependencies": {
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-gravatar/node_modules/strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-hook-form": {
+ "version": "7.51.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.1.tgz",
+ "integrity": "sha512-ifnBjl+kW0ksINHd+8C/Gp6a4eZOdWyvRv0UBaByShwU8JbVx5hTcTWEcd5VdybvmPTATkVVXk9npXArHmo56w==",
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "node_modules/react-json-view": {
+ "version": "1.21.3",
+ "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz",
+ "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==",
+ "dependencies": {
+ "flux": "^4.0.1",
+ "react-base16-styling": "^0.6.0",
+ "react-lifecycles-compat": "^3.0.4",
+ "react-textarea-autosize": "^8.3.2"
+ },
+ "peerDependencies": {
+ "react": "^17.0.0 || ^16.3.0 || ^15.5.4",
+ "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4"
+ }
+ },
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "node_modules/react-markdown": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-6.0.3.tgz",
+ "integrity": "sha512-kQbpWiMoBHnj9myLlmZG9T1JdoT/OEyHK7hqM6CqFT14MAkgWiWBUYijLyBmxbntaN6dCDicPcUhWhci1QYodg==",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "@types/unist": "^2.0.3",
+ "comma-separated-tokens": "^1.0.0",
+ "prop-types": "^15.7.2",
+ "property-information": "^5.3.0",
+ "react-is": "^17.0.0",
+ "remark-parse": "^9.0.0",
+ "remark-rehype": "^8.0.0",
+ "space-separated-tokens": "^1.1.0",
+ "style-to-object": "^0.3.0",
+ "unified": "^9.0.0",
+ "unist-util-visit": "^2.0.0",
+ "vfile": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16",
+ "react": ">=16"
+ }
+ },
+ "node_modules/react-markdown/node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
+ },
+ "node_modules/react-reconciler": {
+ "version": "0.29.0",
+ "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
+ "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.0.tgz",
+ "integrity": "sha512-wPMZ8S2TuPadH0sF5irFGjkNLIcRvOSaEe7v+JER8508dyJumm6XZB1u5kztlX0RVq6AzRVndzqcUh6sFIauzA==",
+ "dependencies": {
+ "@remix-run/router": "1.16.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.0.tgz",
+ "integrity": "sha512-Q9YaSYvubwgbal2c9DJKfx6hTNoBp3iJDsl+Duva/DwxoJH+OTXkxGpql4iUK2sla/8z4RpjAm6EWx1qUDuopQ==",
+ "dependencies": {
+ "@remix-run/router": "1.16.0",
+ "react-router": "6.23.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-textarea-autosize": {
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz",
+ "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "use-composed-ref": "^1.3.0",
+ "use-latest": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/react-virtual": {
+ "version": "2.10.4",
+ "resolved": "https://registry.npmjs.org/react-virtual/-/react-virtual-2.10.4.tgz",
+ "integrity": "sha512-Ir6+oPQZTVHfa6+JL9M7cvMILstFZH/H3jqeYeKI4MSUX+rIruVwFC6nGVXw9wqAw8L0Kg2KvfXxI85OvYQdpQ==",
+ "funding": [
+ "https://github.com/sponsors/tannerlinsley"
+ ],
+ "dependencies": {
+ "@reach/observe-rect": "^1.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.6.3 || ^17.0.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/recast": {
+ "version": "0.23.6",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz",
+ "integrity": "sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==",
+ "dependencies": {
+ "ast-types": "^0.16.1",
+ "esprima": "~4.0.0",
+ "source-map": "~0.6.1",
+ "tiny-invariant": "^1.3.3",
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/recast/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/redeyed": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
+ "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==",
+ "dependencies": {
+ "esprima": "~4.0.0"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
+ "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.1",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/remark-gfm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz",
+ "integrity": "sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA==",
+ "dependencies": {
+ "mdast-util-gfm": "^0.1.0",
+ "micromark-extension-gfm": "^0.3.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
+ "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
+ "dependencies": {
+ "mdast-util-from-markdown": "^0.8.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-8.1.0.tgz",
+ "integrity": "sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA==",
+ "dependencies": {
+ "mdast-util-to-hast": "^10.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
+ },
+ "node_modules/reselect": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
+ "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
+ "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/sanitize-html": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz",
+ "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==",
+ "dependencies": {
+ "deepmerge": "^4.2.2",
+ "escape-string-regexp": "^4.0.0",
+ "htmlparser2": "^8.0.0",
+ "is-plain-object": "^5.0.0",
+ "parse-srcset": "^1.0.2",
+ "postcss": "^8.3.11"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/section-matter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
+ "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/section-matter/node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver-diff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+ "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+ "dependencies": {
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/semver-diff/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+ "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ=="
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shallow-clone/node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/skin-tone": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz",
+ "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==",
+ "dependencies": {
+ "unicode-emoji-modifier-base": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
+ "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/split-on-first": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/strict-uri-encode": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+ "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
+ "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "regexp.prototype.flags": "^1.5.2",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
+ "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
+ "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-bom-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
+ "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/style-to-object": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
+ "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
+ "dependencies": {
+ "inline-style-parser": "0.1.1"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-hyperlinks": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
+ "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
+ "dependencies": {
+ "has-flag": "^4.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/temp": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
+ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
+ "dependencies": {
+ "mkdirp": "^0.5.1",
+ "rimraf": "~2.6.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/temp/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/temp/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+ "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/trough": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
+ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz",
+ "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/ua-parser-js": {
+ "version": "1.0.37",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
+ "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ua-parser-js"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/faisalman"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/faisalman"
+ }
+ ],
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
+ "node_modules/unicode-emoji-modifier-base": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz",
+ "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unified": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz",
+ "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==",
+ "dependencies": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified/node_modules/is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unified/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-generated": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz",
+ "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
+ "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz",
+ "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dependencies": {
+ "@types/unist": "^2.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.15",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz",
+ "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.2",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/use-composed-ref": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz",
+ "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
+ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-latest": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz",
+ "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==",
+ "dependencies": {
+ "use-isomorphic-layout-effect": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz",
+ "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0",
+ "vfile-message": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
+ "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile/node_modules/is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/warn-once": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz",
+ "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "dev": true,
+ "dependencies": {
+ "function.prototype.name": "^1.1.5",
+ "has-tostringtag": "^1.0.0",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.0.5",
+ "is-finalizationregistry": "^1.0.2",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.1.4",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-pm": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.0.0.tgz",
+ "integrity": "sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==",
+ "dependencies": {
+ "load-yaml-file": "^0.2.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8.15"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+ "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dependencies": {
+ "string-width": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz",
+ "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
+ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/dotnet/samples/marketing/src/frontend/package.json b/dotnet/samples/marketing/src/frontend/package.json
new file mode 100644
index 0000000000..49b2bf6c0a
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "Learning",
+ "version": "0.1.0",
+ "private": true,
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "scripts": {
+ "dev": "cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
+ "build": "refine build",
+ "start": "refine start",
+ "lint": "eslint '**/*.{js,jsx,ts,tsx}'",
+ "refine": "refine"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.8.2",
+ "@emotion/styled": "^11.8.1",
+ "@fontsource/roboto": "^4.5.8",
+ "@microsoft/signalr": "^8.0.0",
+ "@mui/icons-material": "^5.8.3",
+ "@mui/lab": "^5.0.0-alpha.85",
+ "@mui/material": "^5.8.6",
+ "@mui/x-data-grid": "^6.6.0",
+ "@refinedev/cli": "^2.16.21",
+ "@refinedev/core": "^4.47.1",
+ "@refinedev/devtools": "^1.1.32",
+ "@refinedev/kbar": "^1.3.6",
+ "@refinedev/mui": "^5.14.4",
+ "@refinedev/nextjs-router": "^6.0.0",
+ "@refinedev/react-hook-form": "^4.8.14",
+ "@refinedev/simple-rest": "^5.0.1",
+ "js-cookie": "^3.0.5",
+ "next": "14.1.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "react-flippy": "^1.1.0"
+ },
+ "devDependencies": {
+ "@types/js-cookie": "^3.0.6",
+ "@types/node": "^18.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "@typescript-eslint/parser": "5.48.0",
+ "cross-env": "^7.0.3",
+ "eslint": "^8",
+ "eslint-config-next": "14.1.0",
+ "typescript": "^4.7.4"
+ },
+ "refine": {
+ "projectId": "Z0Y3hf-6BZFyJ-VWX5Qq"
+ }
+}
diff --git a/dotnet/samples/marketing/src/frontend/public/static/background1.webp b/dotnet/samples/marketing/src/frontend/public/static/background1.webp
new file mode 100644
index 0000000000..21226ba76f
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/background1.webp differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/check.png b/dotnet/samples/marketing/src/frontend/public/static/check.png
new file mode 100644
index 0000000000..33965edb38
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/check.png differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/face.jpg b/dotnet/samples/marketing/src/frontend/public/static/face.jpg
new file mode 100644
index 0000000000..a054f2e682
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/face.jpg differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/face2.jpg b/dotnet/samples/marketing/src/frontend/public/static/face2.jpg
new file mode 100644
index 0000000000..20e994fb00
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/face2.jpg differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/icons/docs.png b/dotnet/samples/marketing/src/frontend/public/static/icons/docs.png
new file mode 100644
index 0000000000..b070e21dcc
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/icons/docs.png differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/icons/edge.png b/dotnet/samples/marketing/src/frontend/public/static/icons/edge.png
new file mode 100644
index 0000000000..eb345a7530
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/icons/edge.png differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/icons/pdf.png b/dotnet/samples/marketing/src/frontend/public/static/icons/pdf.png
new file mode 100644
index 0000000000..91160940e0
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/icons/pdf.png differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/icons/xslx.png b/dotnet/samples/marketing/src/frontend/public/static/icons/xslx.png
new file mode 100644
index 0000000000..c3463f3d06
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/icons/xslx.png differ
diff --git a/dotnet/samples/marketing/src/frontend/public/static/x.png b/dotnet/samples/marketing/src/frontend/public/static/x.png
new file mode 100644
index 0000000000..a7dfd8ef02
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/public/static/x.png differ
diff --git a/dotnet/samples/marketing/src/frontend/src/app/forgot-password/page.tsx b/dotnet/samples/marketing/src/frontend/src/app/forgot-password/page.tsx
new file mode 100644
index 0000000000..72d4dbc0fc
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/forgot-password/page.tsx
@@ -0,0 +1,23 @@
+import { AuthPage } from "@components/auth-page";
+import { authProviderServer } from "@providers/auth-provider";
+import { redirect } from "next/navigation";
+
+export default async function ForgotPassword() {
+ const data = await getData();
+
+ if (data.authenticated) {
+ redirect(data?.redirectTo || "/");
+ }
+
+ return ;
+}
+
+async function getData() {
+ const { authenticated, redirectTo, error } = await authProviderServer.check();
+
+ return {
+ authenticated,
+ redirectTo,
+ error,
+ };
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/app/icon.ico b/dotnet/samples/marketing/src/frontend/src/app/icon.ico
new file mode 100644
index 0000000000..a3df394d64
Binary files /dev/null and b/dotnet/samples/marketing/src/frontend/src/app/icon.ico differ
diff --git a/dotnet/samples/marketing/src/frontend/src/app/layout.tsx b/dotnet/samples/marketing/src/frontend/src/app/layout.tsx
new file mode 100644
index 0000000000..bb8334585c
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/layout.tsx
@@ -0,0 +1,68 @@
+import { DevtoolsProvider } from "@providers/devtools";
+import { Refine } from "@refinedev/core";
+import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
+import { RefineSnackbarProvider, notificationProvider } from "@refinedev/mui";
+import routerProvider from "@refinedev/nextjs-router";
+import { Metadata } from "next";
+import { cookies } from "next/headers";
+import React, { Suspense } from "react";
+
+import { ColorModeContextProvider } from "@contexts/color-mode";
+import { authProvider } from "@providers/auth-provider";
+import { dataProvider } from "@providers/data-provider";
+
+export const metadata: Metadata = {
+ title: "Refine",
+ description: "Generated by create refine app",
+ icons: {
+ icon: "/favicon.ico",
+ },
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const cookieStore = cookies();
+ const theme = cookieStore.get("theme");
+ const defaultMode = theme?.value === "dark" ? "dark" : "light";
+
+ return (
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/app/login/page.tsx b/dotnet/samples/marketing/src/frontend/src/app/login/page.tsx
new file mode 100644
index 0000000000..cfe99c5720
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/login/page.tsx
@@ -0,0 +1,23 @@
+import { AuthPage } from "@components/auth-page";
+import { authProviderServer } from "@providers/auth-provider";
+import { redirect } from "next/navigation";
+
+export default async function Login() {
+ const data = await getData();
+
+ if (data.authenticated) {
+ redirect(data?.redirectTo || "/");
+ }
+
+ return ;
+}
+
+async function getData() {
+ const { authenticated, redirectTo, error } = await authProviderServer.check();
+
+ return {
+ authenticated,
+ redirectTo,
+ error,
+ };
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/chat/chat.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/chat/chat.tsx
new file mode 100644
index 0000000000..e8c99aead1
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/chat/chat.tsx
@@ -0,0 +1,147 @@
+"use client";
+
+import * as React from 'react';
+import List from '@mui/material/List';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import Public from '@mui/icons-material/Public';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
+import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
+import { styled } from '@mui/material/styles';
+import LightbulbIcon from '@mui/icons-material/Lightbulb';
+import { Button, Container, Grid, TextField } from '@mui/material';
+
+const data = [
+ { icon: , label: 'Bank vs Mrs Peters - Settled - chf 1.5M - 1 year' },
+ { icon: , label: 'Bank vs Mr Pertussi - Won - chf0 - 4 years' },
+ { icon: , label: 'Bank vs Governnent - Public Case - chf 3.7M - 10 years' },
+];
+
+const FireNav = styled(List)<{ component?: React.ElementType }>({
+ '& .MuiListItemButton-root': {
+ paddingLeft: 24,
+ paddingRight: 24,
+ },
+ '& .MuiListItemIcon-root': {
+ minWidth: 0,
+ marginRight: 16,
+ },
+ '& .MuiSvgIcon-root': {
+ fontSize: 20,
+ },
+});
+
+type Message = {
+ sender: string;
+ text: any;
+};
+
+type ChatProps = {
+ messages: Message[];
+ setMessages: (messages: Message[]) => void;
+ sendMessage: (message: string, agent: string) => void;
+};
+
+export default function Chat({ messages, setMessages, sendMessage }: ChatProps) {
+ const [open, setOpen] = React.useState(true);
+ const [message, setMessage] = React.useState('');
+
+ const handleSend = (message:string) => {
+ setMessages([...messages, { sender: 'user', text: message }]);
+ sendMessage(message, "chat");
+ };
+
+ return (
+
+ setOpen(!open)}
+ sx={{
+ px: 3,
+ pt: 2.5,
+ pb: open ? 0 : 2.5,
+ '&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
+ }}
+ >
+
+
+
+
+
+
+ {open && (
+
+
+
+ {messages.map((message, index) => (
+
+ {message.sender}: {message.text}
+
+ ))}
+
+
+
+
+
+ setMessage(e.target.value)}
+ fullWidth
+ inputProps={{ style: { height: 'auto' } }}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ handleSend((e.target as HTMLInputElement).value);
+ setMessage('');
+ }
+ }}
+ />
+
+
+
+
+
+
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/community-manager/community-manager.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/community-manager/community-manager.tsx
new file mode 100644
index 0000000000..aa617fa5c9
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/community-manager/community-manager.tsx
@@ -0,0 +1,131 @@
+"use client";
+
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import List from '@mui/material/List';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import { styled } from '@mui/material/styles';
+import AppShortcut from '@mui/icons-material/AttachMoney';
+import LoopIcon from '@mui/icons-material/Loop';
+import { Card, CardContent, Typography } from '@mui/material';
+import Image from 'next/image';
+
+const FireNav = styled(List)<{ component?: React.ElementType }>({
+ '& .MuiListItemButton-root': {
+ paddingLeft: 24,
+ paddingRight: 24,
+ },
+ '& .MuiListItemIcon-root': {
+ minWidth: 0,
+ marginRight: 16,
+ },
+ '& .MuiSvgIcon-root': {
+ fontSize: 20,
+ },
+});
+
+type CommunityManagerProps = {
+ article: string;
+ open: boolean;
+ setOpen: React.Dispatch>;
+ imgUrl: string;
+};
+
+export default function CommunityManager({ article, open, setOpen, imgUrl }: CommunityManagerProps) {
+ console.log(`[CommunityManager] Rendering. Url: '${imgUrl}'`);
+
+ return (
+
+
+
+ setOpen(!open)}
+ sx={{
+ px: 3,
+ pt: 2.5,
+ pb: open ? 0 : 2.5,
+ '&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
+ }}
+ >
+
+
+
+
+
+
+ {open && (
+ article === '' || article === null ? (
+
+
+
+ ) : (
+
+
+
+ Social media posts on X
+
+ {article}
+ {imgUrl && (
+
+
+
+ )}
+
+
+ )
+ )}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/costs/cost.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/costs/cost.tsx
new file mode 100644
index 0000000000..4d1dec5260
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/costs/cost.tsx
@@ -0,0 +1,111 @@
+"use client";
+
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import List from '@mui/material/List';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import Public from '@mui/icons-material/Public';
+import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
+import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
+import GavelIcon from '@mui/icons-material/Gavel';
+import { styled } from '@mui/material/styles';
+import { green, pink } from '@mui/material/colors';
+import AttachMoneyIcon from '@mui/icons-material/AttachMoney';
+
+const data = [
+ { icon: , label: 'IPA discount form 9-9 - eur 15k' },
+ { icon: , label: '2x1 brewery birthday - eur 250k' },
+ { icon: , label: 'Summer day 1 - CHF 180k' },
+ { icon: , label: 'Worldcup promo 1.5M' },
+];
+
+const FireNav = styled(List)<{ component?: React.ElementType }>({
+ '& .MuiListItemButton-root': {
+ paddingLeft: 24,
+ paddingRight: 24,
+ },
+ '& .MuiListItemIcon-root': {
+ minWidth: 0,
+ marginRight: 16,
+ },
+ '& .MuiSvgIcon-root': {
+ fontSize: 20,
+ },
+});
+
+export default function CostList() {
+ const [open, setOpen] = React.useState(false);
+ console.log(`[Marketing] Rendering.`);
+
+ return (
+
+
+
+ setOpen(!open)}
+ sx={{
+ px: 3,
+ pt: 2.5,
+ pb: open ? 0 : 2.5,
+ '&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
+ }}
+ >
+
+
+
+
+
+
+ {open &&
+ data.map((item) => (
+
+
+ {item.icon}
+
+
+
+ ))}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/docs/docs.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/docs/docs.tsx
new file mode 100644
index 0000000000..77d1583318
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/docs/docs.tsx
@@ -0,0 +1,170 @@
+"use client";
+
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import List from '@mui/material/List';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import Public from '@mui/icons-material/Public';
+import HandshakeTwoToneIcon from '@mui/icons-material/HandshakeTwoTone';
+import WorkspacePremiumTwoToneIcon from '@mui/icons-material/WorkspacePremiumTwoTone';
+import { styled } from '@mui/material/styles';
+import FolderIcon from '@mui/icons-material/Folder';
+import ExpandLess from '@mui/icons-material/ExpandLess';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import Collapse from '@mui/material/Collapse';
+import FilePresentIcon from '@mui/icons-material/FilePresent';
+
+const data = [
+ { icon: , label: 'Internal guidance for marketing campaigns' },
+ { icon: , label: 'Belgium law on marketing of alcohol' },
+ { icon: , label: 'something else' },
+];
+
+const FireNav = styled(List)<{ component?: React.ElementType }>({
+ '& .MuiListItemButton-root': {
+ paddingLeft: 24,
+ paddingRight: 24,
+ },
+ '& .MuiListItemIcon-root': {
+ minWidth: 0,
+ marginRight: 16,
+ },
+ '& .MuiSvgIcon-root': {
+ fontSize: 20,
+ },
+});
+
+export default function RelevantDocumentList() {
+ const [open, setOpen] = React.useState(false);
+ console.log(`[Marketing] Rendering.`);
+
+ const [courtCasesOpen, setCourtCasesOpen] = React.useState(true);
+ const courtCasesOpenHandleClick = () => {
+ setCourtCasesOpen(!courtCasesOpen);
+ };
+
+ const [lawOpen, setLawOpen] = React.useState(true);
+ const LawOpenHandleClick = () => {
+ setLawOpen(!lawOpen);
+ };
+
+
+ return (
+
+
+
+ setOpen(!open)}
+ sx={{
+ px: 3,
+ pt: 2.5,
+ pb: open ? 0 : 2.5,
+ '&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
+ }}
+ >
+
+
+
+
+
+
+ {open && (
+
+
+ {/* Court cases */}
+
+
+
+
+
+
+ {courtCasesOpen ? : }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Laws */}
+
+
+
+
+
+
+ {lawOpen ? : }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/page.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/page.tsx
new file mode 100644
index 0000000000..c0b441f527
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/page.tsx
@@ -0,0 +1,187 @@
+"use client";
+
+import '@fontsource/roboto/300.css';
+import '@fontsource/roboto/400.css';
+import '@fontsource/roboto/500.css';
+import '@fontsource/roboto/700.css';
+
+import React, { useRef, useState } from 'react';
+import { styled, ThemeProvider, createTheme } from '@mui/material/styles';
+import Paper from '@mui/material/Paper';
+import Stack from '@mui/material/Stack';
+import Divider from '@mui/material/Divider';
+
+import StakeholderList from './stakeholders/stakeholders';
+import CostList from './costs/cost';
+import RelevantDocumentList from './docs/docs';
+import Chat from './chat/chat';
+import CommunityManager from './community-manager/community-manager';
+import { Container, Grid } from '@mui/material';
+import { HubConnectionBuilder, HubConnection, LogLevel } from '@microsoft/signalr';
+
+type SignalRMessage = {
+ userId: string;
+ message: string;
+ agent: string;
+};
+
+export default function Marketing() {
+ const Item = styled(Paper)(({ theme }) => ({
+ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
+ ...theme.typography.body2,
+ padding: theme.spacing(0),
+ textAlign: 'center',
+ color: theme.palette.text.secondary,
+ }));
+
+ // Add this style
+ const Background = styled('div')({
+ backgroundImage: `url(/static/background1.webp)`,
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: 'cover',
+ height: '100vh',
+ });
+
+ const [connection, setConnection] = React.useState();
+
+ const userId = 'Carlos';
+ //Chat component state
+ const [messages, setMessages] = React.useState<{ sender: string; text: any; }[]>([]);
+
+ //Community manager state
+ const [ article, setArticle ] = useState('');
+ const [ imgUrl, setImgUrl ] = useState('');
+ const [ communityManagerOpen, setCommunityManagerOpen ] = useState(false);
+
+ const createSignalRConnection = async (userId: string) => {
+ try {
+ // initi the connection
+ const connection = new HubConnectionBuilder()
+ .withUrl(`http://localhost:5244/articlehub`)
+ .configureLogging(LogLevel.Information)
+ .build();
+
+ //setup handler
+ connection.on('ReceiveMessage', (message: SignalRMessage) => {
+ console.log(`[MainPage][${message.userId}] Received message from ${message.agent}: ${message.message}`);
+ if (message.agent === 'Chat') {
+ const newMessage = { sender: 'agent', text: message.message };
+ setMessages(prevMessages => [...prevMessages, newMessage]);
+ }
+ if (message.agent === 'CommunityManager') {
+ setArticle(message.message);
+ }
+ if (message.agent === 'GraphicDesigner') {
+ setImgUrl(message.message);
+ }
+ });
+
+ connection.onclose(async () => {
+ console.log(`[MainPage] Connection closed.`);
+
+ try {
+ await connection.start();
+ console.log(`Connection ID: ${connection.connectionId}`);
+ await connection.invoke('ConnectToAgent', userId);
+ console.log(`[MainPage] Connection re-established.`);
+ } catch (error) {
+ console.error(error);
+ }
+ });
+
+ await connection.start();
+ console.log(`Connection ID: ${connection.connectionId}`);
+ await connection.invoke('ConnectToAgent', userId);
+
+ setConnection(connection);
+ console.log(`[MainPage] Connection established.`);
+ } catch (error) {
+ console.error(error);
+ }
+ };
+
+ const setMessagesInUI = async (messages: { sender: string; text: any; }[]) => {
+ await setMessages(messages);
+ }
+
+ const sendMessage = async (message: string, agent: string) => {
+ if (connection) {
+ const frontEndMessage:SignalRMessage = {
+ userId: userId,
+ message: message,
+ agent: agent
+ };
+ console.log(`[MainPage][${{agent}}] Sending message: ${message}`);
+ await connection.invoke('ProcessMessage', frontEndMessage);
+ console.log(`[MainPage][${{agent}}] message sent`);
+ } else {
+ console.error(`[MainPage] Connection not established.`);
+ }
+ }
+
+ React.useEffect(() => {
+ createSignalRConnection(userId);
+ }, []);
+
+ console.log(`[Marketing] Rendering.`);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/marketing/stakeholders/stakeholders.tsx b/dotnet/samples/marketing/src/frontend/src/app/marketing/stakeholders/stakeholders.tsx
new file mode 100644
index 0000000000..db2e75b8c5
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/marketing/stakeholders/stakeholders.tsx
@@ -0,0 +1,218 @@
+"use client";
+
+import React, { useRef, useState } from 'react';
+
+import '@fontsource/roboto/300.css';
+import '@fontsource/roboto/400.css';
+import '@fontsource/roboto/500.css';
+import '@fontsource/roboto/700.css';
+
+import { styled } from '@mui/material/styles';
+import { Avatar, Box, Container } from '@mui/material';
+import Badge, { BadgeProps } from '@mui/material/Badge';
+import { Typography } from '@mui/material';
+import List from '@mui/material/List';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemText from '@mui/material/ListItemText';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import PersonIcon from '@mui/icons-material/Person';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import { Title } from '@refinedev/mui';
+
+const GreenStyledBadge = styled(Badge)(({ theme }) => ({
+ '& .MuiBadge-badge': {
+ backgroundColor: '#44b700',
+ color: '#44b700',
+ boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
+ '&::after': {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ height: '100%',
+ borderRadius: '50%',
+ animation: 'ripple 1.2s infinite ease-in-out',
+ border: '1px solid currentColor',
+ content: '""',
+ },
+ },
+ '@keyframes ripple': {
+ '0%': {
+ transform: 'scale(.8)',
+ opacity: 1,
+ },
+ '100%': {
+ transform: 'scale(2.4)',
+ opacity: 0,
+ },
+ },
+}));
+
+const RedStyledBadge = styled(Badge)(({ theme }) => ({
+ '& .MuiBadge-badge': {
+ backgroundColor: 'red',
+ color: '#44b700',
+ boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
+ '&::after': {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ height: '100%',
+ borderRadius: '50%',
+ animation: 'ripple 1.2s infinite ease-in-out',
+ border: '1px solid currentColor',
+ content: '""',
+ },
+ },
+ '@keyframes ripple': {
+ '0%': {
+ transform: 'scale(.8)',
+ opacity: 1,
+ },
+ '100%': {
+ transform: 'scale(2.4)',
+ opacity: 0,
+ },
+ },
+}));
+
+export default function StakeholderList() {
+ const [open, setOpen] = React.useState(false);
+
+ console.log(`[Marketing] Rendering.`);
+ return (
+
+
+ setOpen(!open)}
+ sx={{
+ px: 3,
+ pt: 2.5,
+ pb: open ? 0 : 2.5,
+ '&:hover, &:focus': { '& #arrowdownicon': { opacity: open ? 1 : 0 } },
+ }}
+ >
+
+
+
+
+
+
+ {open && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ {open && (
+ Questions? These are relevant stakeholders for you:
+ )}
+ {open && (
+
+
+
+
+
+
+
+
+
+ General Attorney
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+ Marketing Manager
+
+
+ }
+ />
+
+
+ )}
+
+
+ );
+}
\ No newline at end of file
diff --git a/dotnet/samples/marketing/src/frontend/src/app/not-found.tsx b/dotnet/samples/marketing/src/frontend/src/app/not-found.tsx
new file mode 100644
index 0000000000..58d73059d7
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/not-found.tsx
@@ -0,0 +1,15 @@
+"use client";
+
+import { Authenticated } from "@refinedev/core";
+import { ErrorComponent } from "@refinedev/mui";
+import { Suspense } from "react";
+
+export default function NotFound() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/app/page.tsx b/dotnet/samples/marketing/src/frontend/src/app/page.tsx
new file mode 100644
index 0000000000..465054461d
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/page.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import { Suspense } from "react";
+
+import { Authenticated } from "@refinedev/core";
+import { NavigateToResource } from "@refinedev/nextjs-router";
+
+export default function IndexPage() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/app/register/page.tsx b/dotnet/samples/marketing/src/frontend/src/app/register/page.tsx
new file mode 100644
index 0000000000..bf26b7c12f
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/app/register/page.tsx
@@ -0,0 +1,23 @@
+import { AuthPage } from "@components/auth-page";
+import { authProviderServer } from "@providers/auth-provider";
+import { redirect } from "next/navigation";
+
+export default async function Register() {
+ const data = await getData();
+
+ if (data.authenticated) {
+ redirect(data?.redirectTo || "/");
+ }
+
+ return ;
+}
+
+async function getData() {
+ const { authenticated, redirectTo, error } = await authProviderServer.check();
+
+ return {
+ authenticated,
+ redirectTo,
+ error,
+ };
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/components/auth-page/index.tsx b/dotnet/samples/marketing/src/frontend/src/components/auth-page/index.tsx
new file mode 100644
index 0000000000..76e46ccedd
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/components/auth-page/index.tsx
@@ -0,0 +1,14 @@
+"use client";
+import type { AuthPageProps } from "@refinedev/core";
+import { AuthPage as AuthPageBase } from "@refinedev/mui";
+
+export const AuthPage = (props: AuthPageProps) => {
+ return (
+
+ );
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/components/header/index.tsx b/dotnet/samples/marketing/src/frontend/src/components/header/index.tsx
new file mode 100644
index 0000000000..ad6c003ab4
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/components/header/index.tsx
@@ -0,0 +1,80 @@
+import { ColorModeContext } from "@contexts/color-mode";
+import DarkModeOutlined from "@mui/icons-material/DarkModeOutlined";
+import LightModeOutlined from "@mui/icons-material/LightModeOutlined";
+import AppBar from "@mui/material/AppBar";
+import Avatar from "@mui/material/Avatar";
+import IconButton from "@mui/material/IconButton";
+import Stack from "@mui/material/Stack";
+import Toolbar from "@mui/material/Toolbar";
+import Typography from "@mui/material/Typography";
+import { useGetIdentity } from "@refinedev/core";
+import { HamburgerMenu, RefineThemedLayoutV2HeaderProps } from "@refinedev/mui";
+import React, { useContext } from "react";
+
+type IUser = {
+ id: number;
+ name: string;
+ avatar: string;
+};
+
+export const Header: React.FC = ({
+ sticky = true,
+}) => {
+ const { mode, setMode } = useContext(ColorModeContext);
+
+ const { data: user } = useGetIdentity();
+
+ return (
+
+
+
+
+
+ {
+ setMode();
+ }}
+ >
+ {mode === "dark" ? : }
+
+
+ {(user?.avatar || user?.name) && (
+
+ {user?.name && (
+
+ {user?.name}
+
+ )}
+
+
+ )}
+
+
+
+
+ );
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/components/themed-layout/index.tsx b/dotnet/samples/marketing/src/frontend/src/components/themed-layout/index.tsx
new file mode 100644
index 0000000000..bed0348699
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/components/themed-layout/index.tsx
@@ -0,0 +1,11 @@
+"use client";
+
+import { Header } from "@components/header";
+import { ThemedLayoutV2 } from "@refinedev/mui";
+import React from "react";
+
+export const ThemedLayout = ({ children }: React.PropsWithChildren) => {
+ return (
+ }>{children}
+ );
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/contexts/color-mode/index.tsx b/dotnet/samples/marketing/src/frontend/src/contexts/color-mode/index.tsx
new file mode 100644
index 0000000000..f064de7b89
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/contexts/color-mode/index.tsx
@@ -0,0 +1,72 @@
+"use client";
+
+import CssBaseline from "@mui/material/CssBaseline";
+import GlobalStyles from "@mui/material/GlobalStyles";
+import { ThemeProvider } from "@mui/material/styles";
+import useMediaQuery from "@mui/material/useMediaQuery";
+import { RefineThemes } from "@refinedev/mui";
+import Cookies from "js-cookie";
+import React, {
+ PropsWithChildren,
+ createContext,
+ useEffect,
+ useState,
+} from "react";
+
+type ColorModeContextType = {
+ mode: string;
+ setMode: () => void;
+};
+
+export const ColorModeContext = createContext(
+ {} as ColorModeContextType
+);
+
+type ColorModeContextProviderProps = {
+ defaultMode?: string;
+};
+
+export const ColorModeContextProvider: React.FC<
+ PropsWithChildren
+> = ({ children, defaultMode }) => {
+ const [isMounted, setIsMounted] = useState(false);
+ const [mode, setMode] = useState(defaultMode || "light");
+
+ useEffect(() => {
+ setIsMounted(true);
+ }, []);
+
+ const systemTheme = useMediaQuery(`(prefers-color-scheme: dark)`);
+
+ useEffect(() => {
+ if (isMounted) {
+ const theme = Cookies.get("theme") || (systemTheme ? "dark" : "light");
+ setMode(theme);
+ }
+ }, [isMounted, systemTheme]);
+
+ const toggleTheme = () => {
+ const nextTheme = mode === "light" ? "dark" : "light";
+
+ setMode(nextTheme);
+ Cookies.set("theme", nextTheme);
+ };
+
+ return (
+
+
+
+
+ {children}
+
+
+ );
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/interfaces/theme.d.ts b/dotnet/samples/marketing/src/frontend/src/interfaces/theme.d.ts
new file mode 100644
index 0000000000..9819aac105
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/interfaces/theme.d.ts
@@ -0,0 +1,15 @@
+import "@refinedev/mui";
+
+export interface CustomTheme {
+ // Add custom variables here like below:
+ // status: {
+ // danger: string;
+ // };
+}
+
+declare module "@refinedev/mui" {
+ interface Theme extends import("@refinedev/mui").Theme, CustomTheme {}
+ interface ThemeOptions
+ extends import("@refinedev/mui").ThemeOptions,
+ CustomTheme {}
+}
diff --git a/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.server.ts b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.server.ts
new file mode 100644
index 0000000000..5f1f974313
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.server.ts
@@ -0,0 +1,21 @@
+import { AuthBindings } from "@refinedev/core";
+import { cookies } from "next/headers";
+
+export const authProviderServer: Pick = {
+ check: async () => {
+ const cookieStore = cookies();
+ const auth = cookieStore.get("auth");
+
+ if (auth) {
+ return {
+ authenticated: true,
+ };
+ }
+
+ return {
+ authenticated: false,
+ logout: true,
+ redirectTo: "/login",
+ };
+ },
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.ts b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.ts
new file mode 100644
index 0000000000..2f626b2b44
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/auth-provider.ts
@@ -0,0 +1,91 @@
+"use client";
+
+import { AuthBindings } from "@refinedev/core";
+import Cookies from "js-cookie";
+
+const mockUsers = [
+ {
+ name: "John Doe",
+ email: "johndoe@mail.com",
+ roles: ["admin"],
+ avatar: "https://i.pravatar.cc/150?img=1",
+ },
+ {
+ name: "Jane Doe",
+ email: "janedoe@mail.com",
+ roles: ["editor"],
+ avatar: "https://i.pravatar.cc/150?img=1",
+ },
+];
+
+export const authProvider: AuthBindings = {
+ login: async ({ email, username, password, remember }) => {
+ // Suppose we actually send a request to the back end here.
+ const user = mockUsers[0];
+
+ if (user) {
+ Cookies.set("auth", JSON.stringify(user), {
+ expires: 30, // 30 days
+ path: "/",
+ });
+ return {
+ success: true,
+ redirectTo: "/",
+ };
+ }
+
+ return {
+ success: false,
+ error: {
+ name: "LoginError",
+ message: "Invalid username or password",
+ },
+ };
+ },
+ logout: async () => {
+ Cookies.remove("auth", { path: "/" });
+ return {
+ success: true,
+ redirectTo: "/login",
+ };
+ },
+ check: async () => {
+ const auth = Cookies.get("auth");
+ if (auth) {
+ return {
+ authenticated: true,
+ };
+ }
+
+ return {
+ authenticated: false,
+ logout: true,
+ redirectTo: "/login",
+ };
+ },
+ getPermissions: async () => {
+ const auth = Cookies.get("auth");
+ if (auth) {
+ const parsedUser = JSON.parse(auth);
+ return parsedUser.roles;
+ }
+ return null;
+ },
+ getIdentity: async () => {
+ const auth = Cookies.get("auth");
+ if (auth) {
+ const parsedUser = JSON.parse(auth);
+ return parsedUser;
+ }
+ return null;
+ },
+ onError: async (error) => {
+ if (error.response?.status === 401) {
+ return {
+ logout: true,
+ };
+ }
+
+ return { error };
+ },
+};
diff --git a/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/index.ts b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/index.ts
new file mode 100644
index 0000000000..6734cd53b8
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/providers/auth-provider/index.ts
@@ -0,0 +1,2 @@
+export * from "./auth-provider";
+export * from "./auth-provider.server";
diff --git a/dotnet/samples/marketing/src/frontend/src/providers/data-provider/index.ts b/dotnet/samples/marketing/src/frontend/src/providers/data-provider/index.ts
new file mode 100644
index 0000000000..a049c0e10c
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/providers/data-provider/index.ts
@@ -0,0 +1,7 @@
+"use client";
+
+import dataProviderSimpleRest from "@refinedev/simple-rest";
+
+const API_URL = "https://api.fake-rest.refine.dev";
+
+export const dataProvider = dataProviderSimpleRest(API_URL);
diff --git a/dotnet/samples/marketing/src/frontend/src/providers/devtools/index.tsx b/dotnet/samples/marketing/src/frontend/src/providers/devtools/index.tsx
new file mode 100644
index 0000000000..e039bf9dcc
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/src/providers/devtools/index.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import {
+ DevtoolsPanel,
+ DevtoolsProvider as DevtoolsProviderBase,
+} from "@refinedev/devtools";
+import React from "react";
+
+export const DevtoolsProvider = (props: React.PropsWithChildren) => {
+ return (
+
+ {props.children}
+
+
+ );
+};
diff --git a/dotnet/samples/marketing/src/frontend/tsconfig.json b/dotnet/samples/marketing/src/frontend/tsconfig.json
new file mode 100644
index 0000000000..ebdf6714cb
--- /dev/null
+++ b/dotnet/samples/marketing/src/frontend/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@*": [
+ "./src/*"
+ ],
+ "@pages/*": [
+ "./pages/*"
+ ]
+ },
+ "incremental": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/dotnet/src/Microsoft.AI.Agents.Dapr/Agent.cs b/dotnet/src/Microsoft.AI.Agents.Dapr/Agent.cs
new file mode 100644
index 0000000000..8d6d26f285
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Dapr/Agent.cs
@@ -0,0 +1,27 @@
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+
+namespace Microsoft.AI.Agents.Dapr;
+
+public abstract class Agent : Actor, IAgent
+{
+ private readonly DaprClient daprClient;
+
+ protected Agent(ActorHost host, DaprClient daprClient) : base(host)
+ {
+ this.daprClient = daprClient;
+ }
+ public abstract Task HandleEvent(Event item);
+
+ public async Task PublishEvent(string ns, string id, Event item)
+ {
+ var metadata = new Dictionary() {
+ { "cloudevent.Type", item.Type },
+ { "cloudevent.Subject", item.Subject },
+ { "cloudevent.id", Guid.NewGuid().ToString()}
+ };
+
+ await daprClient.PublishEventAsync(ns, id, item, metadata);
+ }
+}
diff --git a/dotnet/src/Microsoft.AI.Agents.Dapr/AiAgent.cs b/dotnet/src/Microsoft.AI.Agents.Dapr/AiAgent.cs
new file mode 100644
index 0000000000..1537defb70
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Dapr/AiAgent.cs
@@ -0,0 +1,80 @@
+using System.Text;
+using Dapr.Actors;
+using Dapr.Actors.Runtime;
+using Dapr.Client;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.Memory;
+
+namespace Microsoft.AI.Agents.Dapr;
+
+public abstract class AiAgent : Agent, IAiAgent where T: class, new()
+{
+ public string StateStore = "agents-statestore";
+ public AiAgent(ActorHost host, DaprClient client,ISemanticTextMemory memory, Kernel kernel)
+ : base(host, client)
+ {
+ _memory = memory;
+ _kernel = kernel;
+ }
+ private readonly ISemanticTextMemory _memory;
+ private readonly Kernel _kernel;
+
+ protected AgentState state;
+
+
+ protected override async Task OnActivateAsync()
+ {
+ state = await StateManager.GetOrAddStateAsync(StateStore, new AgentState());
+ }
+
+ public void AddToHistory(string message, ChatUserType userType)
+ {
+ if (state.History == null) state.History = new List();
+ state.History.Add(new ChatHistoryItem
+ {
+ Message = message,
+ Order = state.History.Count + 1,
+ UserType = userType
+ });
+ }
+
+ public string AppendChatHistory(string ask)
+ {
+ AddToHistory(ask, ChatUserType.User);
+ return string.Join("\n", state.History.Select(message => $"{message.UserType}: {message.Message}"));
+ }
+
+ public virtual async Task CallFunction(string template, KernelArguments arguments, OpenAIPromptExecutionSettings? settings = null)
+ {
+ var propmptSettings = (settings == null) ? new OpenAIPromptExecutionSettings { MaxTokens = 18000, Temperature = 0.8, TopP = 1 }
+ : settings;
+ var function = _kernel.CreateFunctionFromPrompt(template, propmptSettings);
+ var result = (await _kernel.InvokeAsync(function, arguments)).ToString();
+ AddToHistory(result, ChatUserType.Agent);
+ await StateManager.SetStateAsync(
+ StateStore,
+ state);
+ return result;
+ }
+
+ ///
+ /// Adds knowledge to the
+ ///
+ /// The instruction string that uses the value of !index! as a placeholder to inject the data. Example:"Consider the following architectural guidelines: {waf}"
+ /// Knowledge index
+ /// The sk arguments, "input" is the argument
+ ///
+ public async Task AddKnowledge(string instruction, string index, KernelArguments arguments)
+ {
+ var documents = _memory.SearchAsync(index, arguments["input"].ToString(), 5);
+ var kbStringBuilder = new StringBuilder();
+ await foreach (var doc in documents)
+ {
+ kbStringBuilder.AppendLine($"{doc.Metadata.Text}");
+ }
+ arguments[index] = instruction.Replace($"!{index}!", $"{kbStringBuilder}");
+ return arguments;
+ }
+}
diff --git a/dotnet/src/Microsoft.AI.Agents.Dapr/IDaprAgent.cs b/dotnet/src/Microsoft.AI.Agents.Dapr/IDaprAgent.cs
new file mode 100644
index 0000000000..228359fc62
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Dapr/IDaprAgent.cs
@@ -0,0 +1,9 @@
+using Dapr.Actors;
+using Microsoft.AI.Agents.Abstractions;
+
+namespace Microsoft.AI.Agents.Dapr;
+
+public interface IDaprAgent : IActor
+{
+ Task HandleEvent(Event item);
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents.Dapr/Microsoft.AI.Agents.Dapr.csproj b/dotnet/src/Microsoft.AI.Agents.Dapr/Microsoft.AI.Agents.Dapr.csproj
new file mode 100644
index 0000000000..6e1d44f479
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Dapr/Microsoft.AI.Agents.Dapr.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/src/Microsoft.AI.Agents.Orleans/Agent.cs b/dotnet/src/Microsoft.AI.Agents.Orleans/Agent.cs
new file mode 100644
index 0000000000..48fd318ff9
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Orleans/Agent.cs
@@ -0,0 +1,32 @@
+using Microsoft.AI.Agents.Abstractions;
+using Orleans.Runtime;
+using Orleans.Streams;
+
+namespace Microsoft.AI.Agents.Orleans;
+
+public abstract class Agent : Grain, IGrainWithStringKey, IAgent
+{
+ protected virtual string Namespace { get;set;}
+ public abstract Task HandleEvent(Event item);
+
+ private async Task HandleEvent(Event item, StreamSequenceToken? token)
+ {
+ await HandleEvent(item);
+ }
+
+ public async Task PublishEvent(string ns, string id, Event item)
+ {
+ var streamProvider = this.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(ns, id);
+ var stream = streamProvider.GetStream(streamId);
+ await stream.OnNextAsync(item);
+ }
+
+ public async override Task OnActivateAsync(CancellationToken cancellationToken)
+ {
+ var streamProvider = this.GetStreamProvider("StreamProvider");
+ var streamId = StreamId.Create(Namespace, this.GetPrimaryKeyString());
+ var stream = streamProvider.GetStream(streamId);
+ await stream.SubscribeAsync(HandleEvent);
+ }
+}
diff --git a/dotnet/src/Microsoft.AI.Agents.Orleans/AiAgent.cs b/dotnet/src/Microsoft.AI.Agents.Orleans/AiAgent.cs
new file mode 100644
index 0000000000..6d7294c606
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Orleans/AiAgent.cs
@@ -0,0 +1,75 @@
+using System.Text;
+using Microsoft.AI.Agents.Abstractions;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.Memory;
+using Orleans.Runtime;
+
+namespace Microsoft.AI.Agents.Orleans;
+
+public abstract class AiAgent : Agent, IAiAgent where T : class, new()
+{
+ protected IPersistentState> _state;
+ protected Kernel _kernel;
+ private readonly ISemanticTextMemory _memory;
+
+
+ public AiAgent([PersistentState("state", "messages")] IPersistentState> state, ISemanticTextMemory memory, Kernel kernel)
+ {
+ _state = state;
+ _memory = memory;
+ _kernel = kernel;
+ }
+
+ public override Task OnActivateAsync(CancellationToken cancellationToken)
+ {
+ // Initialize the Agent state
+ if (_state.State.History == null) _state.State.History = new List();
+ if (_state.State.Data == null) _state.State.Data = new T();
+
+ return base.OnActivateAsync(cancellationToken);
+ }
+
+ public void AddToHistory(string message, ChatUserType userType) => _state.State.History.Add(new ChatHistoryItem
+ {
+ Message = message,
+ Order = _state.State.History.Count + 1,
+ UserType = userType
+ });
+
+ public string AppendChatHistory(string ask)
+ {
+ AddToHistory(ask, ChatUserType.User);
+ return string.Join("\n", _state.State.History.Select(message => $"{message.UserType}: {message.Message}"));
+ }
+
+ public virtual async Task CallFunction(string template, KernelArguments arguments, OpenAIPromptExecutionSettings? settings = null)
+ {
+ // TODO: extract this to be configurable
+ var propmptSettings = settings ?? new OpenAIPromptExecutionSettings { MaxTokens = 4096, Temperature = 0.8, TopP = 1 };
+ var function = _kernel.CreateFunctionFromPrompt(template, propmptSettings);
+ var result = (await _kernel.InvokeAsync(function, arguments)).ToString();
+ AddToHistory(result, ChatUserType.Agent);
+ await _state.WriteStateAsync();
+ return result;
+ }
+
+ ///
+ /// Adds knowledge to the
+ ///
+ /// The instruction string that uses the value of !index! as a placeholder to inject the data. Example:"Consider the following architectural guidelines: {waf}"
+ /// Knowledge index
+ /// The sk arguments, "input" is the argument
+ ///
+ public async Task AddKnowledge(string instruction, string index, KernelArguments arguments)
+ {
+ var documents = _memory.SearchAsync(index, arguments["input"].ToString(), 5);
+ var kbStringBuilder = new StringBuilder();
+ await foreach (var doc in documents)
+ {
+ kbStringBuilder.AppendLine($"{doc.Metadata.Text}");
+ }
+ arguments[index] = instruction.Replace($"!{index}!", $"{kbStringBuilder}");
+ return arguments;
+ }
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents.Orleans/EventSurrogate.cs b/dotnet/src/Microsoft.AI.Agents.Orleans/EventSurrogate.cs
new file mode 100644
index 0000000000..451cd3391a
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Orleans/EventSurrogate.cs
@@ -0,0 +1,32 @@
+using Microsoft.AI.Agents.Abstractions;
+
+namespace Microsoft.AI.Agents.Orleans;
+
+[GenerateSerializer]
+public struct EventSurrogate
+{
+ [Id(0)]
+ public Dictionary Data { get; set; }
+ [Id(1)]
+ public string Type { get; set; }
+ [Id(2)]
+ public string Subject { get; set; }
+}
+
+[RegisterConverter]
+public sealed class EventSurrogateConverter :
+ IConverter
+{
+ public Event ConvertFromSurrogate(
+ in EventSurrogate surrogate) =>
+ new Event { Data = surrogate.Data, Subject = surrogate.Subject, Type = surrogate.Type};
+
+ public EventSurrogate ConvertToSurrogate(
+ in Event value) =>
+ new EventSurrogate
+ {
+ Data = value.Data,
+ Type = value.Type,
+ Subject = value.Subject
+ };
+}
diff --git a/dotnet/src/Microsoft.AI.Agents.Orleans/Microsoft.AI.Agents.Orleans.csproj b/dotnet/src/Microsoft.AI.Agents.Orleans/Microsoft.AI.Agents.Orleans.csproj
new file mode 100644
index 0000000000..ce6deabf4a
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents.Orleans/Microsoft.AI.Agents.Orleans.csproj
@@ -0,0 +1,15 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/AgentState.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/AgentState.cs
new file mode 100644
index 0000000000..10bc212f96
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/AgentState.cs
@@ -0,0 +1,7 @@
+namespace Microsoft.AI.Agents.Abstractions;
+
+public class AgentState where T: class, new()
+{
+ public List History { get; set; }
+ public T Data { get; set; }
+}
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatHistoryItem.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatHistoryItem.cs
new file mode 100644
index 0000000000..30d915254a
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatHistoryItem.cs
@@ -0,0 +1,10 @@
+namespace Microsoft.AI.Agents.Abstractions;
+
+[Serializable]
+public class ChatHistoryItem
+{
+ public string Message { get; set; }
+ public ChatUserType UserType { get; set; }
+ public int Order { get; set; }
+
+}
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatUserType.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatUserType.cs
new file mode 100644
index 0000000000..4168b7bcd2
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/ChatUserType.cs
@@ -0,0 +1,8 @@
+namespace Microsoft.AI.Agents.Abstractions;
+
+public enum ChatUserType
+{
+ System,
+ User,
+ Agent
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/Event.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/Event.cs
new file mode 100644
index 0000000000..95b64ba2b7
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/Event.cs
@@ -0,0 +1,12 @@
+using System.Runtime.Serialization;
+
+namespace Microsoft.AI.Agents.Abstractions
+{
+ [DataContract]
+ public class Event
+ {
+ public Dictionary Data { get; set; }
+ public string Type { get; set; }
+ public string Subject { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/IAgent.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/IAgent.cs
new file mode 100644
index 0000000000..d05c4c37a2
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/IAgent.cs
@@ -0,0 +1,7 @@
+namespace Microsoft.AI.Agents.Abstractions;
+
+public interface IAgent
+{
+ Task HandleEvent(Event item);
+ Task PublishEvent(string ns, string id, Event item);
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents/Abstractions/IAiAgent.cs b/dotnet/src/Microsoft.AI.Agents/Abstractions/IAiAgent.cs
new file mode 100644
index 0000000000..54ea314eb1
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Abstractions/IAiAgent.cs
@@ -0,0 +1,13 @@
+
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+
+namespace Microsoft.AI.Agents.Abstractions;
+
+public interface IAiAgent : IAgent
+{
+ void AddToHistory(string message, ChatUserType userType);
+ string AppendChatHistory(string ask);
+ Task CallFunction(string template, KernelArguments arguments, OpenAIPromptExecutionSettings? settings = null);
+ Task AddKnowledge(string instruction, string index, KernelArguments arguments);
+}
\ No newline at end of file
diff --git a/dotnet/src/Microsoft.AI.Agents/Microsoft.AI.Agents.csproj b/dotnet/src/Microsoft.AI.Agents/Microsoft.AI.Agents.csproj
new file mode 100644
index 0000000000..be26f7a588
--- /dev/null
+++ b/dotnet/src/Microsoft.AI.Agents/Microsoft.AI.Agents.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
\ No newline at end of file