mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-04-01 11:51:36 +00:00
Merge branch 'main' into PowerPoint
This commit is contained in:
commit
1f5fcb2816
134
.github/workflows/build-and-release.yml
vendored
134
.github/workflows/build-and-release.yml
vendored
@ -173,6 +173,9 @@ jobs:
|
|||||||
pdfium_version=$(sed -n '11p' metadata.txt)
|
pdfium_version=$(sed -n '11p' metadata.txt)
|
||||||
pdfium_version=$(echo $pdfium_version | cut -d'.' -f3)
|
pdfium_version=$(echo $pdfium_version | cut -d'.' -f3)
|
||||||
|
|
||||||
|
# Next line is the Qdrant version:
|
||||||
|
qdrant_version="v$(sed -n '12p' metadata.txt)"
|
||||||
|
|
||||||
# Write the metadata to the environment:
|
# Write the metadata to the environment:
|
||||||
echo "APP_VERSION=${app_version}" >> $GITHUB_ENV
|
echo "APP_VERSION=${app_version}" >> $GITHUB_ENV
|
||||||
echo "FORMATTED_APP_VERSION=${formatted_app_version}" >> $GITHUB_ENV
|
echo "FORMATTED_APP_VERSION=${formatted_app_version}" >> $GITHUB_ENV
|
||||||
@ -185,6 +188,7 @@ jobs:
|
|||||||
echo "TAURI_VERSION=${tauri_version}" >> $GITHUB_ENV
|
echo "TAURI_VERSION=${tauri_version}" >> $GITHUB_ENV
|
||||||
echo "ARCHITECTURE=${{ matrix.dotnet_runtime }}" >> $GITHUB_ENV
|
echo "ARCHITECTURE=${{ matrix.dotnet_runtime }}" >> $GITHUB_ENV
|
||||||
echo "PDFIUM_VERSION=${pdfium_version}" >> $GITHUB_ENV
|
echo "PDFIUM_VERSION=${pdfium_version}" >> $GITHUB_ENV
|
||||||
|
echo "QDRANT_VERSION=${qdrant_version}" >> $GITHUB_ENV
|
||||||
|
|
||||||
# Log the metadata:
|
# Log the metadata:
|
||||||
echo "App version: '${formatted_app_version}'"
|
echo "App version: '${formatted_app_version}'"
|
||||||
@ -197,6 +201,7 @@ jobs:
|
|||||||
echo "Tauri version: '${tauri_version}'"
|
echo "Tauri version: '${tauri_version}'"
|
||||||
echo "Architecture: '${{ matrix.dotnet_runtime }}'"
|
echo "Architecture: '${{ matrix.dotnet_runtime }}'"
|
||||||
echo "PDFium version: '${pdfium_version}'"
|
echo "PDFium version: '${pdfium_version}'"
|
||||||
|
echo "Qdrant version: '${qdrant_version}'"
|
||||||
|
|
||||||
- name: Read and format metadata (Windows)
|
- name: Read and format metadata (Windows)
|
||||||
if: matrix.platform == 'windows-latest'
|
if: matrix.platform == 'windows-latest'
|
||||||
@ -241,6 +246,9 @@ jobs:
|
|||||||
$pdfium_version = $metadata[10]
|
$pdfium_version = $metadata[10]
|
||||||
$pdfium_version = $pdfium_version.Split('.')[2]
|
$pdfium_version = $pdfium_version.Split('.')[2]
|
||||||
|
|
||||||
|
# Next line is the necessary Qdrant version:
|
||||||
|
$qdrant_version = "v$($metadata[11])"
|
||||||
|
|
||||||
# Write the metadata to the environment:
|
# Write the metadata to the environment:
|
||||||
Write-Output "APP_VERSION=${app_version}" >> $env:GITHUB_ENV
|
Write-Output "APP_VERSION=${app_version}" >> $env:GITHUB_ENV
|
||||||
Write-Output "FORMATTED_APP_VERSION=${formatted_app_version}" >> $env:GITHUB_ENV
|
Write-Output "FORMATTED_APP_VERSION=${formatted_app_version}" >> $env:GITHUB_ENV
|
||||||
@ -252,6 +260,7 @@ jobs:
|
|||||||
Write-Output "MUD_BLAZOR_VERSION=${mud_blazor_version}" >> $env:GITHUB_ENV
|
Write-Output "MUD_BLAZOR_VERSION=${mud_blazor_version}" >> $env:GITHUB_ENV
|
||||||
Write-Output "ARCHITECTURE=${{ matrix.dotnet_runtime }}" >> $env:GITHUB_ENV
|
Write-Output "ARCHITECTURE=${{ matrix.dotnet_runtime }}" >> $env:GITHUB_ENV
|
||||||
Write-Output "PDFIUM_VERSION=${pdfium_version}" >> $env:GITHUB_ENV
|
Write-Output "PDFIUM_VERSION=${pdfium_version}" >> $env:GITHUB_ENV
|
||||||
|
Write-Output "QDRANT_VERSION=${qdrant_version}" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
# Log the metadata:
|
# Log the metadata:
|
||||||
Write-Output "App version: '${formatted_app_version}'"
|
Write-Output "App version: '${formatted_app_version}'"
|
||||||
@ -264,6 +273,7 @@ jobs:
|
|||||||
Write-Output "Tauri version: '${tauri_version}'"
|
Write-Output "Tauri version: '${tauri_version}'"
|
||||||
Write-Output "Architecture: '${{ matrix.dotnet_runtime }}'"
|
Write-Output "Architecture: '${{ matrix.dotnet_runtime }}'"
|
||||||
Write-Output "PDFium version: '${pdfium_version}'"
|
Write-Output "PDFium version: '${pdfium_version}'"
|
||||||
|
Write-Output "Qdrant version: '${qdrant_version}'"
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
@ -334,7 +344,7 @@ jobs:
|
|||||||
echo "Cleaning up ..."
|
echo "Cleaning up ..."
|
||||||
rm -fr "$TMP"
|
rm -fr "$TMP"
|
||||||
|
|
||||||
- name: Install PDFium (Windows)
|
- name: Deploy PDFium (Windows)
|
||||||
if: matrix.platform == 'windows-latest'
|
if: matrix.platform == 'windows-latest'
|
||||||
env:
|
env:
|
||||||
PDFIUM_VERSION: ${{ env.PDFIUM_VERSION }}
|
PDFIUM_VERSION: ${{ env.PDFIUM_VERSION }}
|
||||||
@ -385,6 +395,128 @@ jobs:
|
|||||||
Write-Host "Cleaning up ..."
|
Write-Host "Cleaning up ..."
|
||||||
Remove-Item $ARCHIVE -Force -ErrorAction SilentlyContinue
|
Remove-Item $ARCHIVE -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Try to remove the temporary directory, but ignore errors if files are still in use
|
||||||
|
try {
|
||||||
|
Remove-Item $TMP -Recurse -Force -ErrorAction Stop
|
||||||
|
Write-Host "Successfully cleaned up temporary directory: $TMP"
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Could not fully clean up temporary directory: $TMP. This is usually harmless as Windows will clean it up later. Error: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
- name: Deploy Qdrant (Unix)
|
||||||
|
if: matrix.platform != 'windows-latest'
|
||||||
|
env:
|
||||||
|
QDRANT_VERSION: ${{ env.QDRANT_VERSION }}
|
||||||
|
DOTNET_RUNTIME: ${{ matrix.dotnet_runtime }}
|
||||||
|
RUST_TARGET: ${{ matrix.rust_target }}
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Target directory:
|
||||||
|
TDB_DIR="runtime/target/databases/qdrant"
|
||||||
|
mkdir -p "$TDB_DIR"
|
||||||
|
|
||||||
|
case "${DOTNET_RUNTIME}" in
|
||||||
|
linux-x64)
|
||||||
|
QDRANT_FILE="x86_64-unknown-linux-gnu.tar.gz"
|
||||||
|
DB_SOURCE="qdrant"
|
||||||
|
DB_TARGET="qdrant-${RUST_TARGET}"
|
||||||
|
;;
|
||||||
|
linux-arm64)
|
||||||
|
QDRANT_FILE="aarch64-unknown-linux-musl.tar.gz"
|
||||||
|
DB_SOURCE="qdrant"
|
||||||
|
DB_TARGET="qdrant-${RUST_TARGET}"
|
||||||
|
;;
|
||||||
|
osx-x64)
|
||||||
|
QDRANT_FILE="x86_64-apple-darwin.tar.gz"
|
||||||
|
DB_SOURCE="qdrant"
|
||||||
|
DB_TARGET="qdrant-${RUST_TARGET}"
|
||||||
|
;;
|
||||||
|
osx-arm64)
|
||||||
|
QDRANT_FILE="aarch64-apple-darwin.tar.gz"
|
||||||
|
DB_SOURCE="qdrant"
|
||||||
|
DB_TARGET="qdrant-${RUST_TARGET}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown platform: ${DOTNET_RUNTIME}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
QDRANT_URL="https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSION}/qdrant-${QDRANT_FILE}"
|
||||||
|
|
||||||
|
echo "Download Qdrant $QDRANT_URL ..."
|
||||||
|
TMP=$(mktemp -d)
|
||||||
|
ARCHIVE="${TMP}/qdrant.tgz"
|
||||||
|
|
||||||
|
curl -fsSL -o "$ARCHIVE" "$QDRANT_URL"
|
||||||
|
|
||||||
|
echo "Extracting Qdrant ..."
|
||||||
|
tar xzf "$ARCHIVE" -C "$TMP"
|
||||||
|
SRC="${TMP}/${DB_SOURCE}"
|
||||||
|
|
||||||
|
if [ ! -f "$SRC" ]; then
|
||||||
|
echo "Was not able to find Qdrant source: $SRC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Copy Qdrant from ${DB_TARGET} to ${TDB_DIR}/"
|
||||||
|
cp -f "$SRC" "$TDB_DIR/$DB_TARGET"
|
||||||
|
|
||||||
|
echo "Cleaning up ..."
|
||||||
|
rm -fr "$TMP"
|
||||||
|
|
||||||
|
- name: Deploy Qdrant (Windows)
|
||||||
|
if: matrix.platform == 'windows-latest'
|
||||||
|
env:
|
||||||
|
QDRANT_VERSION: ${{ env.QDRANT_VERSION }}
|
||||||
|
DOTNET_RUNTIME: ${{ matrix.dotnet_runtime }}
|
||||||
|
RUST_TARGET: ${{ matrix.rust_target }}
|
||||||
|
run: |
|
||||||
|
$TDB_DIR = "runtime\target\databases\qdrant"
|
||||||
|
New-Item -ItemType Directory -Force -Path $TDB_DIR | Out-Null
|
||||||
|
|
||||||
|
switch ($env:DOTNET_RUNTIME) {
|
||||||
|
"win-x64" {
|
||||||
|
$QDRANT_FILE = "x86_64-pc-windows-msvc.zip"
|
||||||
|
$DB_SOURCE = "qdrant.exe"
|
||||||
|
$DB_TARGET = "qdrant-$($env:RUST_TARGET).exe"
|
||||||
|
}
|
||||||
|
"win-arm64" {
|
||||||
|
$QDRANT_FILE = "x86_64-pc-windows-msvc.zip"
|
||||||
|
$DB_SOURCE = "qdrant.exe"
|
||||||
|
$DB_TARGET = "qdrant-$($env:RUST_TARGET).exe"
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
Write-Error "Unknown platform: $($env:DOTNET_RUNTIME)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$QDRANT_URL = "https://github.com/qdrant/qdrant/releases/download/$($env:QDRANT_VERSION)/qdrant-$QDRANT_FILE"
|
||||||
|
Write-Host "Download $QDRANT_URL ..."
|
||||||
|
|
||||||
|
# Create a unique temporary directory (not just a file)
|
||||||
|
$TMP = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
|
||||||
|
New-Item -ItemType Directory -Path $TMP -Force | Out-Null
|
||||||
|
$ARCHIVE = Join-Path $TMP "qdrant.tgz"
|
||||||
|
|
||||||
|
Invoke-WebRequest -Uri $QDRANT_URL -OutFile $ARCHIVE
|
||||||
|
|
||||||
|
Write-Host "Extracting Qdrant ..."
|
||||||
|
tar -xzf $ARCHIVE -C $TMP
|
||||||
|
|
||||||
|
$SRC = Join-Path $TMP $DB_SOURCE
|
||||||
|
if (!(Test-Path $SRC)) {
|
||||||
|
Write-Error "Cannot find Qdrant source: $SRC"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$DEST = Join-Path $TDB_DIR $DB_TARGET
|
||||||
|
Copy-Item -Path $SRC -Destination $DEST -Force
|
||||||
|
|
||||||
|
Write-Host "Cleaning up ..."
|
||||||
|
Remove-Item $ARCHIVE -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
# Try to remove the temporary directory, but ignore errors if files are still in use
|
# Try to remove the temporary directory, but ignore errors if files are still in use
|
||||||
try {
|
try {
|
||||||
Remove-Item $TMP -Recurse -Force -ErrorAction Stop
|
Remove-Item $TMP -Recurse -Force -ErrorAction Stop
|
||||||
|
|||||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -6,6 +6,13 @@ libpdfium.dylib
|
|||||||
libpdfium.so
|
libpdfium.so
|
||||||
libpdfium.dll
|
libpdfium.dll
|
||||||
|
|
||||||
|
# Ignore qdrant database:
|
||||||
|
qdrant-aarch64-apple-darwin
|
||||||
|
qdrant-x86_64-apple-darwin
|
||||||
|
qdrant-aarch64-unknown-linux-gnu
|
||||||
|
qdrant-x86_64-unknown-linux-gnu
|
||||||
|
qdrant-x86_64-pc-windows-msvc.exe
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
|
|||||||
@ -32,7 +32,7 @@ Since November 2024: Work on RAG (integration of your data and files) has begun.
|
|||||||
- [x] ~~App: Implement dialog for checking & handling [pandoc](https://pandoc.org/) installation ([PR #393](https://github.com/MindWorkAI/AI-Studio/pull/393), [PR #487](https://github.com/MindWorkAI/AI-Studio/pull/487))~~
|
- [x] ~~App: Implement dialog for checking & handling [pandoc](https://pandoc.org/) installation ([PR #393](https://github.com/MindWorkAI/AI-Studio/pull/393), [PR #487](https://github.com/MindWorkAI/AI-Studio/pull/487))~~
|
||||||
- [ ] App: Implement external embedding providers
|
- [ ] App: Implement external embedding providers
|
||||||
- [ ] App: Implement the process to vectorize one local file using embeddings
|
- [ ] App: Implement the process to vectorize one local file using embeddings
|
||||||
- [ ] Runtime: Integration of the vector database [Qdrant](https://github.com/qdrant/qdrant)
|
- [x] ~~Runtime: Integration of the vector database [Qdrant](https://github.com/qdrant/qdrant) ([PR #580](https://github.com/MindWorkAI/AI-Studio/pull/580))~~
|
||||||
- [ ] App: Implement the continuous process of vectorizing data
|
- [ ] App: Implement the continuous process of vectorizing data
|
||||||
- [x] ~~App: Define a common retrieval context interface for the integration of RAG processes in chats (PR [#281](https://github.com/MindWorkAI/AI-Studio/pull/281), [#284](https://github.com/MindWorkAI/AI-Studio/pull/284), [#286](https://github.com/MindWorkAI/AI-Studio/pull/286), [#287](https://github.com/MindWorkAI/AI-Studio/pull/287))~~
|
- [x] ~~App: Define a common retrieval context interface for the integration of RAG processes in chats (PR [#281](https://github.com/MindWorkAI/AI-Studio/pull/281), [#284](https://github.com/MindWorkAI/AI-Studio/pull/284), [#286](https://github.com/MindWorkAI/AI-Studio/pull/286), [#287](https://github.com/MindWorkAI/AI-Studio/pull/287))~~
|
||||||
- [x] ~~App: Define a common augmentation interface for the integration of RAG processes in chats (PR [#288](https://github.com/MindWorkAI/AI-Studio/pull/288), [#289](https://github.com/MindWorkAI/AI-Studio/pull/289))~~
|
- [x] ~~App: Define a common augmentation interface for the integration of RAG processes in chats (PR [#288](https://github.com/MindWorkAI/AI-Studio/pull/288), [#289](https://github.com/MindWorkAI/AI-Studio/pull/289))~~
|
||||||
@ -105,6 +105,7 @@ MindWork AI Studio is a free desktop app for macOS, Windows, and Linux. It provi
|
|||||||
|
|
||||||
**Key advantages:**
|
**Key advantages:**
|
||||||
- **Free of charge**: The app is free to use, both for personal and commercial purposes.
|
- **Free of charge**: The app is free to use, both for personal and commercial purposes.
|
||||||
|
- **Democratization of AI**: We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models.
|
||||||
- **Independence**: You are not tied to any single provider. Instead, you can choose the providers that best suit your needs. Right now, we support:
|
- **Independence**: You are not tied to any single provider. Instead, you can choose the providers that best suit your needs. Right now, we support:
|
||||||
- [OpenAI](https://openai.com/) (GPT5, GPT4.1, o1, o3, o4, etc.)
|
- [OpenAI](https://openai.com/) (GPT5, GPT4.1, o1, o3, o4, etc.)
|
||||||
- [Perplexity](https://www.perplexity.ai/)
|
- [Perplexity](https://www.perplexity.ai/)
|
||||||
|
|||||||
3
app/Build/Commands/Database.cs
Normal file
3
app/Build/Commands/Database.cs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
namespace Build.Commands;
|
||||||
|
|
||||||
|
public record Database(string Path, string Filename);
|
||||||
120
app/Build/Commands/Qdrant.cs
Normal file
120
app/Build/Commands/Qdrant.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System.Formats.Tar;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
|
using SharedTools;
|
||||||
|
|
||||||
|
namespace Build.Commands;
|
||||||
|
|
||||||
|
public static class Qdrant
|
||||||
|
{
|
||||||
|
public static async Task InstallAsync(RID rid, string version)
|
||||||
|
{
|
||||||
|
Console.Write($"- Installing Qdrant {version} for {rid.ToUserFriendlyName()} ...");
|
||||||
|
|
||||||
|
var cwd = Environment.GetRustRuntimeDirectory();
|
||||||
|
var qdrantTmpDownloadPath = Path.GetTempFileName();
|
||||||
|
var qdrantTmpExtractPath = Directory.CreateTempSubdirectory();
|
||||||
|
var qdrantUrl = GetQdrantDownloadUrl(rid, version);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Download the file:
|
||||||
|
//
|
||||||
|
Console.Write(" downloading ...");
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
var response = await client.GetAsync(qdrantUrl);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" failed to download Qdrant {version} for {rid.ToUserFriendlyName()} from {qdrantUrl}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var fileStream = File.Create(qdrantTmpDownloadPath);
|
||||||
|
await response.Content.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Extract the downloaded file:
|
||||||
|
//
|
||||||
|
Console.Write(" extracting ...");
|
||||||
|
await using(var zStream = File.Open(qdrantTmpDownloadPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||||
|
{
|
||||||
|
if (rid == RID.WIN_X64)
|
||||||
|
{
|
||||||
|
using var archive = new ZipArchive(zStream, ZipArchiveMode.Read);
|
||||||
|
archive.ExtractToDirectory(qdrantTmpExtractPath.FullName, overwriteFiles: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await using var uncompressedStream = new GZipStream(zStream, CompressionMode.Decompress);
|
||||||
|
await TarFile.ExtractToDirectoryAsync(uncompressedStream, qdrantTmpExtractPath.FullName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Copy the database to the target directory:
|
||||||
|
//
|
||||||
|
Console.Write(" deploying ...");
|
||||||
|
var database = GetDatabasePath(rid);
|
||||||
|
if (string.IsNullOrWhiteSpace(database.Path))
|
||||||
|
{
|
||||||
|
Console.WriteLine($" failed to find the database path for {rid.ToUserFriendlyName()}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var qdrantDbSourcePath = Path.Join(qdrantTmpExtractPath.FullName, database.Path);
|
||||||
|
var qdrantDbTargetPath = Path.Join(cwd, "target", "databases", "qdrant",database.Filename);
|
||||||
|
if (!File.Exists(qdrantDbSourcePath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($" failed to find the database file '{qdrantDbSourcePath}'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.Join(cwd, "target", "databases", "qdrant"));
|
||||||
|
if (File.Exists(qdrantDbTargetPath))
|
||||||
|
File.Delete(qdrantDbTargetPath);
|
||||||
|
|
||||||
|
File.Copy(qdrantDbSourcePath, qdrantDbTargetPath);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cleanup:
|
||||||
|
//
|
||||||
|
Console.Write(" cleaning up ...");
|
||||||
|
File.Delete(qdrantTmpDownloadPath);
|
||||||
|
Directory.Delete(qdrantTmpExtractPath.FullName, true);
|
||||||
|
|
||||||
|
Console.WriteLine(" done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Database GetDatabasePath(RID rid) => rid switch
|
||||||
|
{
|
||||||
|
RID.OSX_ARM64 => new("qdrant", "qdrant-aarch64-apple-darwin"),
|
||||||
|
RID.OSX_X64 => new("qdrant", "qdrant-x86_64-apple-darwin"),
|
||||||
|
|
||||||
|
RID.LINUX_ARM64 => new("qdrant", "qdrant-aarch64-unknown-linux-gnu"),
|
||||||
|
RID.LINUX_X64 => new("qdrant", "qdrant-x86_64-unknown-linux-gnu"),
|
||||||
|
|
||||||
|
RID.WIN_X64 => new("qdrant.exe", "qdrant-x86_64-pc-windows-msvc.exe"),
|
||||||
|
RID.WIN_ARM64 => new("qdrant.exe", "qdrant-aarch64-pc-windows-msvc.exe"),
|
||||||
|
|
||||||
|
_ => new(string.Empty, string.Empty),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static string GetQdrantDownloadUrl(RID rid, string version)
|
||||||
|
{
|
||||||
|
var baseUrl = $"https://github.com/qdrant/qdrant/releases/download/v{version}/qdrant-";
|
||||||
|
return rid switch
|
||||||
|
{
|
||||||
|
RID.LINUX_ARM64 => $"{baseUrl}aarch64-unknown-linux-musl.tar.gz",
|
||||||
|
RID.LINUX_X64 => $"{baseUrl}x86_64-unknown-linux-gnu.tar.gz",
|
||||||
|
|
||||||
|
RID.OSX_ARM64 => $"{baseUrl}aarch64-apple-darwin.tar.gz",
|
||||||
|
RID.OSX_X64 => $"{baseUrl}x86_64-apple-darwin.tar.gz",
|
||||||
|
|
||||||
|
RID.WIN_X64 => $"{baseUrl}x86_64-pc-windows-msvc.zip",
|
||||||
|
RID.WIN_ARM64 => $"{baseUrl}x86_64-pc-windows-msvc.zip",
|
||||||
|
|
||||||
|
_ => string.Empty,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -151,6 +151,9 @@ public sealed partial class UpdateMetadataCommands
|
|||||||
var pdfiumVersion = await this.ReadPdfiumVersion();
|
var pdfiumVersion = await this.ReadPdfiumVersion();
|
||||||
await Pdfium.InstallAsync(rid, pdfiumVersion);
|
await Pdfium.InstallAsync(rid, pdfiumVersion);
|
||||||
|
|
||||||
|
var qdrantVersion = await this.ReadQdrantVersion();
|
||||||
|
await Qdrant.InstallAsync(rid, qdrantVersion);
|
||||||
|
|
||||||
Console.Write($"- Start .NET build for {rid.ToUserFriendlyName()} ...");
|
Console.Write($"- Start .NET build for {rid.ToUserFriendlyName()} ...");
|
||||||
await this.ReadCommandOutput(pathApp, "dotnet", $"clean --configuration release --runtime {rid.AsMicrosoftRid()}");
|
await this.ReadCommandOutput(pathApp, "dotnet", $"clean --configuration release --runtime {rid.AsMicrosoftRid()}");
|
||||||
var dotnetBuildOutput = await this.ReadCommandOutput(pathApp, "dotnet", $"publish --configuration release --runtime {rid.AsMicrosoftRid()} --disable-build-servers --force");
|
var dotnetBuildOutput = await this.ReadCommandOutput(pathApp, "dotnet", $"publish --configuration release --runtime {rid.AsMicrosoftRid()} --disable-build-servers --force");
|
||||||
@ -364,6 +367,16 @@ public sealed partial class UpdateMetadataCommands
|
|||||||
return shortVersion;
|
return shortVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> ReadQdrantVersion()
|
||||||
|
{
|
||||||
|
const int QDRANT_VERSION_INDEX = 11;
|
||||||
|
var pathMetadata = Environment.GetMetadataPath();
|
||||||
|
var lines = await File.ReadAllLinesAsync(pathMetadata, Encoding.UTF8);
|
||||||
|
var currentQdrantVersion = lines[QDRANT_VERSION_INDEX].Trim();
|
||||||
|
|
||||||
|
return currentQdrantVersion;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task UpdateArchitecture(RID rid)
|
private async Task UpdateArchitecture(RID rid)
|
||||||
{
|
{
|
||||||
const int ARCHITECTURE_INDEX = 9;
|
const int ARCHITECTURE_INDEX = 9;
|
||||||
|
|||||||
@ -27,4 +27,6 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mime/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mime/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mwais/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mwais/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ollama/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=ollama/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Qdrant/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=qdrant/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tauri_0027s/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tauri_0027s/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
@ -7,7 +7,7 @@ namespace AIStudio.Assistants.Agenda;
|
|||||||
|
|
||||||
public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
|
public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.AGENDA_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.AGENDA_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Agenda Planner");
|
protected override string Title => T("Agenda Planner");
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,10 @@
|
|||||||
@this.Title
|
@this.Title
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" OnClick="@(async () => await this.OpenSettingsDialog())"/>
|
@if (this.HasSettingsPanel)
|
||||||
|
{
|
||||||
|
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" OnClick="@(async () => await this.OpenSettingsDialog())"/>
|
||||||
|
}
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<InnerScrolling>
|
<InnerScrolling>
|
||||||
@ -22,7 +25,9 @@
|
|||||||
@if (this.Body is not null)
|
@if (this.Body is not null)
|
||||||
{
|
{
|
||||||
<CascadingValue Value="@this">
|
<CascadingValue Value="@this">
|
||||||
@this.Body
|
<CascadingValue Value="@this.Component">
|
||||||
|
@this.Body
|
||||||
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
|
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" StretchItems="StretchItems.Start" Class="mb-3">
|
<MudStack Row="true" AlignItems="AlignItems.Center" StretchItems="StretchItems.Start" Class="mb-3">
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider;
|
using AIStudio.Provider;
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Dialogs.Settings;
|
||||||
using AIStudio.Tools.Services;
|
using AIStudio.Tools.Services;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@ -42,7 +43,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
|
|
||||||
protected abstract string SystemPrompt { get; }
|
protected abstract string SystemPrompt { get; }
|
||||||
|
|
||||||
public abstract Tools.Components Component { get; }
|
protected abstract Tools.Components Component { get; }
|
||||||
|
|
||||||
protected virtual Func<string> Result2Copy => () => this.resultingContentBlock is null ? string.Empty : this.resultingContentBlock.Content switch
|
protected virtual Func<string> Result2Copy => () => this.resultingContentBlock is null ? string.Empty : this.resultingContentBlock.Content switch
|
||||||
{
|
{
|
||||||
@ -82,6 +83,8 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
|
|
||||||
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
|
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
|
||||||
|
|
||||||
|
protected virtual bool HasSettingsPanel => typeof(TSettings) != typeof(NoSettingsPanel);
|
||||||
|
|
||||||
protected AIStudio.Settings.Provider providerSettings = Settings.Provider.NONE;
|
protected AIStudio.Settings.Provider providerSettings = Settings.Provider.NONE;
|
||||||
protected MudForm? form;
|
protected MudForm? form;
|
||||||
protected bool inputIsValid;
|
protected bool inputIsValid;
|
||||||
@ -186,6 +189,16 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
this.StateHasChanged();
|
this.StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear all input issues.
|
||||||
|
/// </summary>
|
||||||
|
protected void ClearInputIssues()
|
||||||
|
{
|
||||||
|
this.inputIssues = [];
|
||||||
|
this.inputIsValid = true;
|
||||||
|
this.StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
protected void CreateChatThread()
|
protected void CreateChatThread()
|
||||||
{
|
{
|
||||||
this.chatThread = new()
|
this.chatThread = new()
|
||||||
@ -219,6 +232,13 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
return chatId;
|
return chatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void ResetProviderAndProfileSelection()
|
||||||
|
{
|
||||||
|
this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
|
||||||
|
this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
|
||||||
|
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
|
||||||
|
}
|
||||||
|
|
||||||
protected DateTimeOffset AddUserRequest(string request, bool hideContentFromUser = false, params List<FileAttachment> attachments)
|
protected DateTimeOffset AddUserRequest(string request, bool hideContentFromUser = false, params List<FileAttachment> attachments)
|
||||||
{
|
{
|
||||||
var time = DateTimeOffset.Now;
|
var time = DateTimeOffset.Now;
|
||||||
@ -310,6 +330,9 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
|
|
||||||
protected async Task OpenSettingsDialog()
|
protected async Task OpenSettingsDialog()
|
||||||
{
|
{
|
||||||
|
if (!this.HasSettingsPanel)
|
||||||
|
return;
|
||||||
|
|
||||||
var dialogParameters = new DialogParameters();
|
var dialogParameters = new DialogParameters();
|
||||||
await this.DialogService.ShowAsync<TSettings>(null, dialogParameters, DialogOptions.FULLSCREEN);
|
await this.DialogService.ShowAsync<TSettings>(null, dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
}
|
}
|
||||||
@ -356,9 +379,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
await this.JsRuntime.ClearDiv(AFTER_RESULT_DIV_ID);
|
await this.JsRuntime.ClearDiv(AFTER_RESULT_DIV_ID);
|
||||||
|
|
||||||
this.ResetForm();
|
this.ResetForm();
|
||||||
this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
|
this.ResetProviderAndProfileSelection();
|
||||||
this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
|
|
||||||
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
|
|
||||||
|
|
||||||
this.inputIsValid = false;
|
this.inputIsValid = false;
|
||||||
this.inputIssues = [];
|
this.inputIssues = [];
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace AIStudio.Assistants.BiasDay;
|
|||||||
|
|
||||||
public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAssistantBias>
|
public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAssistantBias>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.BIAS_DAY_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.BIAS_DAY_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Bias of the Day");
|
protected override string Title => T("Bias of the Day");
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ namespace AIStudio.Assistants.Coding;
|
|||||||
|
|
||||||
public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
|
public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.CODING_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.CODING_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Coding Assistant");
|
protected override string Title => T("Coding Assistant");
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
@attribute [Route(Routes.ASSISTANT_DOCUMENT_ANALYSIS)]
|
@attribute [Route(Routes.ASSISTANT_DOCUMENT_ANALYSIS)]
|
||||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogDocumentAnalysis>
|
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.NoSettingsPanel>
|
||||||
|
|
||||||
@using AIStudio.Settings.DataModel
|
@using AIStudio.Settings.DataModel
|
||||||
|
|
||||||
<PreviewPrototype ApplyInnerScrollingFix="true"/>
|
<PreviewBeta ApplyInnerScrollingFix="true"/>
|
||||||
<div class="mb-6"></div>
|
<div class="mb-6"></div>
|
||||||
|
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">
|
<MudText Typo="Typo.h4" Class="mb-3">
|
||||||
@ -25,9 +24,21 @@ else
|
|||||||
<MudList Color="Color.Primary" T="DataDocumentAnalysisPolicy" Class="mb-1" SelectedValue="@this.selectedPolicy" SelectedValueChanged="@this.SelectedPolicyChanged">
|
<MudList Color="Color.Primary" T="DataDocumentAnalysisPolicy" Class="mb-1" SelectedValue="@this.selectedPolicy" SelectedValueChanged="@this.SelectedPolicyChanged">
|
||||||
@foreach (var policy in this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies)
|
@foreach (var policy in this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies)
|
||||||
{
|
{
|
||||||
<MudListItem T="DataDocumentAnalysisPolicy" Icon="@Icons.Material.Filled.Policy" Value="@policy">
|
@if (policy.IsEnterpriseConfiguration)
|
||||||
@policy.PolicyName
|
{
|
||||||
</MudListItem>
|
<MudListItem T="DataDocumentAnalysisPolicy" Icon="@Icons.Material.Filled.Policy" Value="@policy">
|
||||||
|
@policy.PolicyName
|
||||||
|
<MudTooltip Text="@T("This policy is managed by your organization.")" Placement="Placement.Right">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Business" Size="Size.Small" Class="ml-2" Style="vertical-align: middle;" />
|
||||||
|
</MudTooltip>
|
||||||
|
</MudListItem>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudListItem T="DataDocumentAnalysisPolicy" Icon="@Icons.Material.Filled.Policy" Value="@policy">
|
||||||
|
@policy.PolicyName
|
||||||
|
</MudListItem>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</MudList>
|
</MudList>
|
||||||
}
|
}
|
||||||
@ -36,71 +47,22 @@ else
|
|||||||
<MudButton OnClick="@this.AddPolicy" Variant="Variant.Filled" Color="Color.Primary">
|
<MudButton OnClick="@this.AddPolicy" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
@T("Add policy")
|
@T("Add policy")
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton OnClick="@this.RemovePolicy" Disabled="@(this.selectedPolicy?.IsProtected ?? true)" Variant="Variant.Filled" Color="Color.Error">
|
<MudButton OnClick="@this.RemovePolicy" Disabled="@((this.selectedPolicy?.IsProtected ?? true) || (this.selectedPolicy?.IsEnterpriseConfiguration ?? true))" Variant="Variant.Filled" Color="Color.Error">
|
||||||
@T("Delete this policy")
|
@T("Delete this policy")
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<MudExpansionPanels Class="mb-3 mt-6" MultiExpansion="@false">
|
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6" />
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Policy" HeaderText="@(T("Policy definition") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@this.policyDefinitionExpanded" ExpandedChanged="@this.PolicyDefinitionExpandedChanged">
|
|
||||||
@if (!this.policyDefinitionExpanded)
|
|
||||||
{
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-1">
|
|
||||||
@T("Expand this section to view and edit the policy definition.")
|
|
||||||
</MudJustifiedText>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h5" Class="mb-1">
|
|
||||||
@T("Common settings")
|
|
||||||
</MudText>
|
|
||||||
|
|
||||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyName" Validation="@this.ValidatePolicyName" Immediate="@true" Label="@T("Policy name")" HelperText="@T("Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.")" Counter="60" MaxLength="60" Variant="Variant.Outlined" Margin="Margin.Normal" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" OnKeyUp="@(() => this.PolicyNameWasChanged())"/>
|
@if ((this.selectedPolicy?.HidePolicyDefinition ?? false) && (this.selectedPolicy?.IsEnterpriseConfiguration ?? false))
|
||||||
|
{
|
||||||
|
@* When HidePolicyDefinition is true AND the policy is an enterprise configuration, show only the document selection section without expansion panels *@
|
||||||
|
<div class="mb-3 mt-3">
|
||||||
|
<MudText Typo="Typo.h5" Class="mb-3">
|
||||||
|
@T("Document selection - Policy"): @this.selectedPolicy?.PolicyName
|
||||||
|
</MudText>
|
||||||
|
|
||||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyDescription" Validation="@this.ValidatePolicyDescription" Immediate="@true" Label="@T("Policy description")" HelperText="@T("Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.")" Counter="512" MaxLength="512" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
<MudText Typo="Typo.h6" Class="mb-1">
|
||||||
|
|
||||||
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsManaged ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h5" Class="mt-6 mb-1">
|
|
||||||
@T("Analysis and output rules")
|
|
||||||
</MudText>
|
|
||||||
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
|
||||||
@T("Use the analysis and output rules to define how the AI evaluates your documents and formats the results.")
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
|
||||||
@T("The analysis rules specify what the AI should pay particular attention to while reviewing the documents you provide, and which aspects it should highlight or save. For example, if you want to extract the potential of green hydrogen for agriculture from a variety of general publications, you can explicitly define this in the analysis rules.")
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyAnalysisRules" Validation="@this.ValidateAnalysisRules" Immediate="@true" Label="@T("Analysis rules")" HelperText="@T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
|
||||||
|
|
||||||
<ReadFileContent Text="@T("Load analysis rules from document")" @bind-FileContent="@this.policyAnalysisRules"/>
|
|
||||||
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
|
||||||
@T("After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.")
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyOutputRules" Validation="@this.ValidateOutputRules" Immediate="@true" Label="@T("Output rules")" HelperText="@T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
|
||||||
|
|
||||||
<ReadFileContent Text="@T("Load output rules from document")" @bind-FileContent="@this.policyOutputRules"/>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h5" Class="mt-6 mb-1">
|
|
||||||
@T("Preparation for enterprise distribution")
|
|
||||||
</MudText>
|
|
||||||
|
|
||||||
<MudTooltip Text="@T("Not implemented yet.")">
|
|
||||||
<MudButton StartIcon="@Icons.Material.Filled.FileDownload" Disabled="true" Variant="Variant.Filled" Color="Color.Primary" OnClick="@this.ExportPolicyAsConfiguration">
|
|
||||||
@T("Export policy as configuration section")
|
|
||||||
</MudButton>
|
|
||||||
</MudTooltip>
|
|
||||||
}
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6" />
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.DocumentScanner" HeaderText="@(T("Document selection - Policy") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@(this.selectedPolicy?.IsProtected ?? false)">
|
|
||||||
<MudText Typo="Typo.h5" Class="mb-1">
|
|
||||||
@T("Policy Description")
|
@T("Policy Description")
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
@ -108,13 +70,104 @@ else
|
|||||||
@this.selectedPolicy?.PolicyDescription
|
@this.selectedPolicy?.PolicyDescription
|
||||||
</MudJustifiedText>
|
</MudJustifiedText>
|
||||||
|
|
||||||
<MudText Typo="Typo.h5" Class="mb-1 mt-6">
|
<MudText Typo="Typo.h6" Class="mb-1 mt-6">
|
||||||
@T("Documents for the analysis")
|
@T("Documents for the analysis")
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<AttachDocuments Name="Document Analysis Files" Layer="@DropLayers.ASSISTANTS" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.providerSettings"/>
|
<AttachDocuments Name="Document Analysis Files" Layer="@DropLayers.ASSISTANTS" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.providerSettings"/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@* Standard view with expansion panels *@
|
||||||
|
<MudExpansionPanels Class="mb-3 mt-3" MultiExpansion="@false">
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Policy" HeaderText="@(T("Policy definition") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@this.policyDefinitionExpanded" ExpandedChanged="@this.PolicyDefinitionExpandedChanged">
|
||||||
|
@if (!this.policyDefinitionExpanded)
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-1">
|
||||||
|
@T("Expand this section to view and edit the policy definition.")
|
||||||
|
</MudJustifiedText>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h5" Class="mb-1">
|
||||||
|
@T("Common settings")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
</ExpansionPanel>
|
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyName" Validation="@this.ValidatePolicyName" Immediate="@true" Label="@T("Policy name")" HelperText="@T("Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.")" Counter="60" MaxLength="60" Variant="Variant.Outlined" Margin="Margin.Normal" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" OnKeyUp="@(() => this.PolicyNameWasChanged())"/>
|
||||||
</MudExpansionPanels>
|
|
||||||
|
|
||||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyDescription" Validation="@this.ValidatePolicyDescription" Immediate="@true" Label="@T("Policy description")" HelperText="@T("Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.")" Counter="512" MaxLength="512" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||||
|
|
||||||
|
<MudTextSwitch Disabled="@this.IsNoPolicySelectedOrProtected" Label="@T("Hide the policy definition when distributed via configuration plugin?")" Value="@this.policyHidePolicyDefinition" ValueChanged="async state => await this.PolicyHidePolicyDefinitionWasChanged(state)" LabelOn="@T("Yes, hide the policy definition")" LabelOff="@T("No, show the policy definition")" />
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body2" Class="mt-2 mb-3">
|
||||||
|
@T("Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.")
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => this.IsNoPolicySelectedOrProtected)" RestrictToGlobalMinimumConfidence="true" SelectedValue="@(() => this.policyMinimumProviderConfidence)" SelectionUpdateAsync="@(async level => await this.PolicyMinimumConfidenceWasChangedAsync(level))" />
|
||||||
|
|
||||||
|
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@(providerId => this.PolicyPreselectedProviderWasChanged(providerId))" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||||
|
|
||||||
|
<ProfileFormSelection Disabled="@this.IsNoPolicySelected" Profile="@this.currentProfile" ProfileChanged="@this.PolicyPreselectedProfileWasChangedAsync" />
|
||||||
|
|
||||||
|
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsEnterpriseConfiguration ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h5" Class="mt-6 mb-1">
|
||||||
|
@T("Analysis and output rules")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
||||||
|
@T("Use the analysis and output rules to define how the AI evaluates your documents and formats the results.")
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
||||||
|
@T("The analysis rules specify what the AI should pay particular attention to while reviewing the documents you provide, and which aspects it should highlight or save. For example, if you want to extract the potential of green hydrogen for agriculture from a variety of general publications, you can explicitly define this in the analysis rules.")
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyAnalysisRules" Validation="@this.ValidateAnalysisRules" Immediate="@true" Label="@T("Analysis rules")" HelperText="@T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||||
|
|
||||||
|
<ReadFileContent Text="@T("Load analysis rules from document")" @bind-FileContent="@this.policyAnalysisRules" Disabled="@this.IsNoPolicySelectedOrProtected"/>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
|
||||||
|
@T("After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.")
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyOutputRules" Validation="@this.ValidateOutputRules" Immediate="@true" Label="@T("Output rules")" HelperText="@T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||||
|
|
||||||
|
<ReadFileContent Text="@T("Load output rules from document")" @bind-FileContent="@this.policyOutputRules" Disabled="@this.IsNoPolicySelectedOrProtected"/>
|
||||||
|
|
||||||
|
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h5" Class="mt-6 mb-1">
|
||||||
|
@T("Preparation for enterprise distribution")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudButton StartIcon="@Icons.Material.Filled.ContentCopy" Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsEnterpriseConfiguration ?? false))" Variant="Variant.Filled" Color="Color.Default" OnClick="@this.ExportPolicyAsConfiguration">
|
||||||
|
@T("Export policy as configuration section")
|
||||||
|
</MudButton>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</ExpansionPanel>
|
||||||
|
|
||||||
|
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6" />
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.DocumentScanner" HeaderText="@(T("Document selection - Policy") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@(this.selectedPolicy?.IsProtected ?? false)">
|
||||||
|
<MudText Typo="Typo.h5" Class="mb-1">
|
||||||
|
@T("Policy Description")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
@this.selectedPolicy?.PolicyDescription
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h5" Class="mb-1 mt-6">
|
||||||
|
@T("Documents for the analysis")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<AttachDocuments Name="Document Analysis Files" Layer="@DropLayers.ASSISTANTS" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.providerSettings"/>
|
||||||
|
|
||||||
|
</ExpansionPanel>
|
||||||
|
</MudExpansionPanels>
|
||||||
|
}
|
||||||
|
|
||||||
|
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Dialogs;
|
using AIStudio.Dialogs;
|
||||||
using AIStudio.Dialogs.Settings;
|
using AIStudio.Dialogs.Settings;
|
||||||
|
using AIStudio.Provider;
|
||||||
|
using AIStudio.Settings;
|
||||||
using AIStudio.Settings.DataModel;
|
using AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@ -11,12 +14,12 @@ using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
|||||||
|
|
||||||
namespace AIStudio.Assistants.DocumentAnalysis;
|
namespace AIStudio.Assistants.DocumentAnalysis;
|
||||||
|
|
||||||
public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialogDocumentAnalysis>
|
public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPanel>
|
||||||
{
|
{
|
||||||
[Inject]
|
[Inject]
|
||||||
private IDialogService DialogService { get; init; } = null!;
|
private IDialogService DialogService { get; init; } = null!;
|
||||||
|
|
||||||
public override Tools.Components Component => Tools.Components.DOCUMENT_ANALYSIS_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.DOCUMENT_ANALYSIS_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Document Analysis Assistant");
|
protected override string Title => T("Document Analysis Assistant");
|
||||||
|
|
||||||
@ -116,7 +119,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
|
|
||||||
protected override Func<Task> SubmitAction => this.Analyze;
|
protected override Func<Task> SubmitAction => this.Analyze;
|
||||||
|
|
||||||
protected override bool SubmitDisabled => (this.IsNoPolicySelected || this.loadedDocumentPaths.Count==0);
|
protected override bool SubmitDisabled => this.IsNoPolicySelected || this.loadedDocumentPaths.Count == 0;
|
||||||
|
|
||||||
protected override ChatThread ConvertToChatThread
|
protected override ChatThread ConvertToChatThread
|
||||||
{
|
{
|
||||||
@ -162,16 +165,32 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
|
|
||||||
protected override void ResetForm()
|
protected override void ResetForm()
|
||||||
{
|
{
|
||||||
|
this.loadedDocumentPaths.Clear();
|
||||||
if (!this.MightPreselectValues())
|
if (!this.MightPreselectValues())
|
||||||
{
|
{
|
||||||
this.policyName = string.Empty;
|
this.policyName = string.Empty;
|
||||||
this.policyDescription = string.Empty;
|
this.policyDescription = string.Empty;
|
||||||
this.policyIsProtected = false;
|
this.policyIsProtected = false;
|
||||||
|
this.policyHidePolicyDefinition = false;
|
||||||
this.policyAnalysisRules = string.Empty;
|
this.policyAnalysisRules = string.Empty;
|
||||||
this.policyOutputRules = string.Empty;
|
this.policyOutputRules = string.Empty;
|
||||||
|
this.policyMinimumProviderConfidence = ConfidenceLevel.NONE;
|
||||||
|
this.policyPreselectedProviderId = string.Empty;
|
||||||
|
this.policyPreselectedProfileId = Profile.NO_PROFILE.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ResetProviderAndProfileSelection()
|
||||||
|
{
|
||||||
|
if (this.selectedPolicy is null)
|
||||||
|
{
|
||||||
|
base.ResetProviderAndProfileSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ApplyPolicyPreselection(preferPolicyPreselection: true);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool MightPreselectValues()
|
protected override bool MightPreselectValues()
|
||||||
{
|
{
|
||||||
if (this.selectedPolicy is not null)
|
if (this.selectedPolicy is not null)
|
||||||
@ -179,8 +198,12 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
this.policyName = this.selectedPolicy.PolicyName;
|
this.policyName = this.selectedPolicy.PolicyName;
|
||||||
this.policyDescription = this.selectedPolicy.PolicyDescription;
|
this.policyDescription = this.selectedPolicy.PolicyDescription;
|
||||||
this.policyIsProtected = this.selectedPolicy.IsProtected;
|
this.policyIsProtected = this.selectedPolicy.IsProtected;
|
||||||
|
this.policyHidePolicyDefinition = this.selectedPolicy.HidePolicyDefinition;
|
||||||
this.policyAnalysisRules = this.selectedPolicy.AnalysisRules;
|
this.policyAnalysisRules = this.selectedPolicy.AnalysisRules;
|
||||||
this.policyOutputRules = this.selectedPolicy.OutputRules;
|
this.policyOutputRules = this.selectedPolicy.OutputRules;
|
||||||
|
this.policyMinimumProviderConfidence = this.selectedPolicy.MinimumProviderConfidence;
|
||||||
|
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
|
||||||
|
this.policyPreselectedProfileId = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProfile) ? Profile.NO_PROFILE.Id : this.selectedPolicy.PreselectedProfile;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -205,12 +228,10 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
|
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
|
||||||
|
|
||||||
var receivedDeferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT).FirstOrDefault();
|
|
||||||
if (receivedDeferredContent is not null)
|
|
||||||
this.deferredContent = receivedDeferredContent;
|
|
||||||
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
|
this.ApplyFilters([], [ Event.CONFIGURATION_CHANGED, Event.PLUGINS_RELOADED ]);
|
||||||
|
this.UpdateProviders();
|
||||||
|
this.ApplyPolicyPreselection(preferPolicyPreselection: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -220,33 +241,42 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
if(this.selectedPolicy is null)
|
if(this.selectedPolicy is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!force && this.selectedPolicy.IsProtected)
|
// The preselected profile is always user-adjustable, even for protected policies and enterprise configurations:
|
||||||
|
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfileId;
|
||||||
|
|
||||||
|
// Enterprise configurations cannot be modified at all:
|
||||||
|
if(this.selectedPolicy.IsEnterpriseConfiguration)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!force && this.policyIsProtected)
|
var canEditProtectedFields = force || (!this.selectedPolicy.IsProtected && !this.policyIsProtected);
|
||||||
return;
|
if (canEditProtectedFields)
|
||||||
|
{
|
||||||
this.selectedPolicy.PreselectedProvider = this.providerSettings.Id;
|
this.selectedPolicy.PreselectedProvider = this.policyPreselectedProviderId;
|
||||||
|
this.selectedPolicy.PolicyName = this.policyName;
|
||||||
this.selectedPolicy.PolicyName = this.policyName;
|
this.selectedPolicy.PolicyDescription = this.policyDescription;
|
||||||
this.selectedPolicy.PolicyDescription = this.policyDescription;
|
this.selectedPolicy.IsProtected = this.policyIsProtected;
|
||||||
this.selectedPolicy.IsProtected = this.policyIsProtected;
|
this.selectedPolicy.HidePolicyDefinition = this.policyHidePolicyDefinition;
|
||||||
this.selectedPolicy.AnalysisRules = this.policyAnalysisRules;
|
this.selectedPolicy.AnalysisRules = this.policyAnalysisRules;
|
||||||
this.selectedPolicy.OutputRules = this.policyOutputRules;
|
this.selectedPolicy.OutputRules = this.policyOutputRules;
|
||||||
|
this.selectedPolicy.MinimumProviderConfidence = this.policyMinimumProviderConfidence;
|
||||||
|
}
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
await this.SettingsManager.StoreSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataDocumentAnalysisPolicy? selectedPolicy;
|
private DataDocumentAnalysisPolicy? selectedPolicy;
|
||||||
private bool policyIsProtected;
|
private bool policyIsProtected;
|
||||||
|
private bool policyHidePolicyDefinition;
|
||||||
private bool policyDefinitionExpanded;
|
private bool policyDefinitionExpanded;
|
||||||
private string policyName = string.Empty;
|
private string policyName = string.Empty;
|
||||||
private string policyDescription = string.Empty;
|
private string policyDescription = string.Empty;
|
||||||
private string policyAnalysisRules = string.Empty;
|
private string policyAnalysisRules = string.Empty;
|
||||||
private string policyOutputRules = string.Empty;
|
private string policyOutputRules = string.Empty;
|
||||||
#warning Use deferred content for document analysis
|
private ConfidenceLevel policyMinimumProviderConfidence = ConfidenceLevel.NONE;
|
||||||
private string deferredContent = string.Empty;
|
private string policyPreselectedProviderId = string.Empty;
|
||||||
|
private string policyPreselectedProfileId = Profile.NO_PROFILE.Id;
|
||||||
private HashSet<FileAttachment> loadedDocumentPaths = [];
|
private HashSet<FileAttachment> loadedDocumentPaths = [];
|
||||||
|
private readonly List<ConfigurationSelectData<string>> availableLLMProviders = new();
|
||||||
|
|
||||||
private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected;
|
private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected;
|
||||||
|
|
||||||
@ -257,6 +287,10 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
this.selectedPolicy = policy;
|
this.selectedPolicy = policy;
|
||||||
this.ResetForm();
|
this.ResetForm();
|
||||||
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
|
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
|
||||||
|
this.ApplyPolicyPreselection(preferPolicyPreselection: true);
|
||||||
|
|
||||||
|
this.form?.ResetValidation();
|
||||||
|
this.ClearInputIssues();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task PolicyDefinitionExpandedChanged(bool isExpanded)
|
private Task PolicyDefinitionExpandedChanged(bool isExpanded)
|
||||||
@ -269,12 +303,22 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
{
|
{
|
||||||
this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Add(new ()
|
this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Add(new ()
|
||||||
{
|
{
|
||||||
|
Id = Guid.NewGuid().ToString(),
|
||||||
|
Num = this.SettingsManager.ConfigurationData.NextDocumentAnalysisPolicyNum++,
|
||||||
PolicyName = string.Format(T("Policy {0}"), DateTimeOffset.UtcNow),
|
PolicyName = string.Format(T("Policy {0}"), DateTimeOffset.UtcNow),
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
await this.SettingsManager.StoreSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
|
||||||
|
private void UpdateProviders()
|
||||||
|
{
|
||||||
|
this.availableLLMProviders.Clear();
|
||||||
|
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||||
|
this.availableLLMProviders.Add(new ConfigurationSelectData<string>(provider.InstanceName, provider.Id));
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RemovePolicy()
|
private async Task RemovePolicy()
|
||||||
{
|
{
|
||||||
if(this.selectedPolicy is null)
|
if(this.selectedPolicy is null)
|
||||||
@ -283,6 +327,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
if(this.selectedPolicy.IsProtected)
|
if(this.selectedPolicy.IsProtected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(this.selectedPolicy.IsEnterpriseConfiguration)
|
||||||
|
return;
|
||||||
|
|
||||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
{
|
{
|
||||||
{ x => x.Message, string.Format(T("Are you sure you want to delete the document analysis policy '{0}'?"), this.selectedPolicy.PolicyName) },
|
{ x => x.Message, string.Format(T("Are you sure you want to delete the document analysis policy '{0}'?"), this.selectedPolicy.PolicyName) },
|
||||||
@ -316,6 +363,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
if(this.selectedPolicy.IsProtected)
|
if(this.selectedPolicy.IsProtected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(this.selectedPolicy.IsEnterpriseConfiguration)
|
||||||
|
return;
|
||||||
|
|
||||||
this.selectedPolicy.PolicyName = this.policyName;
|
this.selectedPolicy.PolicyName = this.policyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,14 +374,191 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
if(this.selectedPolicy is null)
|
if(this.selectedPolicy is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(this.selectedPolicy.IsEnterpriseConfiguration)
|
||||||
|
return;
|
||||||
|
|
||||||
this.policyIsProtected = state;
|
this.policyIsProtected = state;
|
||||||
this.selectedPolicy.IsProtected = state;
|
this.selectedPolicy.IsProtected = state;
|
||||||
this.policyDefinitionExpanded = !state;
|
this.policyDefinitionExpanded = !state;
|
||||||
await this.AutoSave(true);
|
await this.AutoSave(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task PolicyHidePolicyDefinitionWasChanged(bool state)
|
||||||
|
{
|
||||||
|
if(this.selectedPolicy is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(this.selectedPolicy.IsEnterpriseConfiguration)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.policyHidePolicyDefinition = state;
|
||||||
|
this.selectedPolicy.HidePolicyDefinition = state;
|
||||||
|
await this.AutoSave(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed", Justification = "Policy-specific preselection needs to probe providers by id before falling back to SettingsManager APIs.")]
|
||||||
|
private void ApplyPolicyPreselection(bool preferPolicyPreselection = false)
|
||||||
|
{
|
||||||
|
if (this.selectedPolicy is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
|
||||||
|
var minimumLevel = this.GetPolicyMinimumConfidenceLevel();
|
||||||
|
|
||||||
|
if (!preferPolicyPreselection)
|
||||||
|
{
|
||||||
|
// Keep the current provider if it still satisfies the minimum confidence:
|
||||||
|
if (this.providerSettings != Settings.Provider.NONE &&
|
||||||
|
this.providerSettings.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
|
||||||
|
{
|
||||||
|
this.currentProfile = this.ResolveProfileSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to apply the policy preselection:
|
||||||
|
var policyProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.selectedPolicy.PreselectedProvider);
|
||||||
|
if (policyProvider is not null && policyProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
|
||||||
|
{
|
||||||
|
this.providerSettings = policyProvider;
|
||||||
|
this.currentProfile = this.ResolveProfileSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fallbackProvider = this.SettingsManager.GetPreselectedProvider(this.Component, this.providerSettings.Id);
|
||||||
|
if (fallbackProvider != Settings.Provider.NONE &&
|
||||||
|
fallbackProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level < minimumLevel)
|
||||||
|
fallbackProvider = Settings.Provider.NONE;
|
||||||
|
|
||||||
|
this.providerSettings = fallbackProvider;
|
||||||
|
this.currentProfile = this.ResolveProfileSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfidenceLevel GetPolicyMinimumConfidenceLevel()
|
||||||
|
{
|
||||||
|
var minimumLevel = ConfidenceLevel.NONE;
|
||||||
|
var llmSettings = this.SettingsManager.ConfigurationData.LLMProviders;
|
||||||
|
var enforceGlobalMinimumConfidence = llmSettings is { EnforceGlobalMinimumConfidence: true, GlobalMinimumConfidence: not ConfidenceLevel.NONE and not ConfidenceLevel.UNKNOWN };
|
||||||
|
if (enforceGlobalMinimumConfidence)
|
||||||
|
minimumLevel = llmSettings.GlobalMinimumConfidence;
|
||||||
|
|
||||||
|
if (this.selectedPolicy is not null && this.selectedPolicy.MinimumProviderConfidence > minimumLevel)
|
||||||
|
minimumLevel = this.selectedPolicy.MinimumProviderConfidence;
|
||||||
|
|
||||||
|
return minimumLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Profile ResolveProfileSelection()
|
||||||
|
{
|
||||||
|
if (this.selectedPolicy is not null && !string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProfile))
|
||||||
|
{
|
||||||
|
var policyProfile = this.SettingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.selectedPolicy.PreselectedProfile);
|
||||||
|
if (policyProfile is not null)
|
||||||
|
return policyProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.SettingsManager.GetPreselectedProfile(this.Component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PolicyMinimumConfidenceWasChangedAsync(ConfidenceLevel level)
|
||||||
|
{
|
||||||
|
this.policyMinimumProviderConfidence = level;
|
||||||
|
await this.AutoSave();
|
||||||
|
|
||||||
|
this.ApplyPolicyPreselection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PolicyPreselectedProviderWasChanged(string providerId)
|
||||||
|
{
|
||||||
|
if (this.selectedPolicy is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.policyPreselectedProviderId = providerId;
|
||||||
|
this.selectedPolicy.PreselectedProvider = providerId;
|
||||||
|
this.providerSettings = Settings.Provider.NONE;
|
||||||
|
this.ApplyPolicyPreselection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PolicyPreselectedProfileWasChangedAsync(Profile profile)
|
||||||
|
{
|
||||||
|
this.policyPreselectedProfileId = profile.Id;
|
||||||
|
if (this.selectedPolicy is not null)
|
||||||
|
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfileId;
|
||||||
|
|
||||||
|
this.currentProfile = this.ResolveProfileSelection();
|
||||||
|
await this.AutoSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of MSGComponentBase
|
||||||
|
|
||||||
|
protected override Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||||
|
{
|
||||||
|
switch (triggeredEvent)
|
||||||
|
{
|
||||||
|
case Event.CONFIGURATION_CHANGED:
|
||||||
|
this.UpdateProviders();
|
||||||
|
this.StateHasChanged();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event.PLUGINS_RELOADED:
|
||||||
|
this.HandlePluginsReloaded();
|
||||||
|
this.StateHasChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void HandlePluginsReloaded()
|
||||||
|
{
|
||||||
|
// Check if the currently selected policy still exists after plugin reload:
|
||||||
|
if (this.selectedPolicy is not null)
|
||||||
|
{
|
||||||
|
var stillExists = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies
|
||||||
|
.Any(p => p.Id == this.selectedPolicy.Id);
|
||||||
|
|
||||||
|
if (!stillExists)
|
||||||
|
{
|
||||||
|
// Policy was removed, select a new one:
|
||||||
|
this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.FirstOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Policy still exists, update the reference to the potentially updated version:
|
||||||
|
this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies
|
||||||
|
.First(p => p.Id == this.selectedPolicy.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No policy was selected, select the first one if available:
|
||||||
|
this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update form values to reflect the current policy:
|
||||||
|
this.ResetForm();
|
||||||
|
|
||||||
|
// Update the expansion state based on the policy protection:
|
||||||
|
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
|
||||||
|
|
||||||
|
// Update available providers:
|
||||||
|
this.UpdateProviders();
|
||||||
|
|
||||||
|
// Apply policy preselection:
|
||||||
|
this.ApplyPolicyPreselection(preferPolicyPreselection: true);
|
||||||
|
|
||||||
|
// Reset validation state:
|
||||||
|
this.form?.ResetValidation();
|
||||||
|
this.ClearInputIssues();
|
||||||
|
}
|
||||||
|
|
||||||
private string? ValidatePolicyName(string name)
|
private string? ValidatePolicyName(string name)
|
||||||
{
|
{
|
||||||
|
if(this.selectedPolicy?.IsEnterpriseConfiguration == true)
|
||||||
|
return null;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(name))
|
if(string.IsNullOrWhiteSpace(name))
|
||||||
return T("Please provide a name for your policy. This name will be used to identify the policy in AI Studio.");
|
return T("Please provide a name for your policy. This name will be used to identify the policy in AI Studio.");
|
||||||
|
|
||||||
@ -346,6 +573,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
|
|
||||||
private string? ValidatePolicyDescription(string description)
|
private string? ValidatePolicyDescription(string description)
|
||||||
{
|
{
|
||||||
|
if(this.selectedPolicy?.IsEnterpriseConfiguration == true)
|
||||||
|
return null;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(description))
|
if(string.IsNullOrWhiteSpace(description))
|
||||||
return T("Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.");
|
return T("Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.");
|
||||||
|
|
||||||
@ -480,15 +710,63 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
|
|||||||
|
|
||||||
private async Task ExportPolicyAsConfiguration()
|
private async Task ExportPolicyAsConfiguration()
|
||||||
{
|
{
|
||||||
return;
|
if (this.IsNoPolicySelected)
|
||||||
|
{
|
||||||
# warning Implement the export function
|
await this.MessageBus.SendError(new (Icons.Material.Filled.Policy, this.T("No policy is selected. Please select a policy to export.")));
|
||||||
// do not allow the export of a protected policy
|
|
||||||
if (this.IsNoPolicySelectedOrProtected)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.AutoSave();
|
await this.AutoSave();
|
||||||
await this.form!.Validate();
|
await this.form!.Validate();
|
||||||
|
if (!this.inputIsValid)
|
||||||
|
{
|
||||||
|
await this.MessageBus.SendError(new (Icons.Material.Filled.Policy, this.T("The selected policy contains invalid data. Please fix the issues before exporting the policy.")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var luaCode = this.GenerateLuaPolicyExport();
|
||||||
|
await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateLuaPolicyExport()
|
||||||
|
{
|
||||||
|
if(this.selectedPolicy is null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var preselectedProvider = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProvider) ? string.Empty : this.selectedPolicy.PreselectedProvider;
|
||||||
|
var preselectedProfile = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProfile) ? Profile.NO_PROFILE.Id : this.selectedPolicy.PreselectedProfile;
|
||||||
|
var id = string.IsNullOrWhiteSpace(this.selectedPolicy.Id) ? Guid.NewGuid().ToString() : this.selectedPolicy.Id;
|
||||||
|
|
||||||
|
return $$"""
|
||||||
|
CONFIG["DOCUMENT_ANALYSIS_POLICIES"][#CONFIG["DOCUMENT_ANALYSIS_POLICIES"]+1] = {
|
||||||
|
["Id"] = "{{id}}",
|
||||||
|
["PolicyName"] = "{{this.selectedPolicy.PolicyName.Trim()}}",
|
||||||
|
["PolicyDescription"] = "{{this.selectedPolicy.PolicyDescription.Trim()}}",
|
||||||
|
|
||||||
|
["AnalysisRules"] = [===[
|
||||||
|
{{this.selectedPolicy.AnalysisRules.Trim()}}
|
||||||
|
]===],
|
||||||
|
|
||||||
|
["OutputRules"] = [===[
|
||||||
|
{{this.selectedPolicy.OutputRules.Trim()}}
|
||||||
|
]===],
|
||||||
|
|
||||||
|
-- Optional: minimum provider confidence required for this policy.
|
||||||
|
-- Allowed values are: NONE, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
||||||
|
["MinimumProviderConfidence"] = "{{this.selectedPolicy.MinimumProviderConfidence}}",
|
||||||
|
|
||||||
|
-- Optional: preselect a provider or profile by ID.
|
||||||
|
-- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
|
||||||
|
["PreselectedProvider"] = "{{preselectedProvider}}",
|
||||||
|
["PreselectedProfile"] = "{{preselectedProfile}}",
|
||||||
|
|
||||||
|
-- Optional: hide the policy definition section in the UI.
|
||||||
|
-- When set to true, users will only see the document selection interface
|
||||||
|
-- and cannot view or modify the policy settings.
|
||||||
|
-- This is useful for enterprise configurations where policy details should remain hidden.
|
||||||
|
-- Allowed values are: true, false (default: false)
|
||||||
|
["HidePolicyDefinition"] = {{this.selectedPolicy.HidePolicyDefinition.ToString().ToLowerInvariant()}},
|
||||||
|
}
|
||||||
|
""";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace AIStudio.Assistants.EMail;
|
|||||||
|
|
||||||
public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMails>
|
public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMails>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.EMAIL_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.EMAIL_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("E-Mail");
|
protected override string Title => T("E-Mail");
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
|||||||
[Inject]
|
[Inject]
|
||||||
private IDialogService DialogService { get; init; } = null!;
|
private IDialogService DialogService { get; init; } = null!;
|
||||||
|
|
||||||
public override Tools.Components Component => Tools.Components.ERI_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.ERI_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("ERI Server");
|
protected override string Title => T("ERI Server");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.GrammarSpelling;
|
|||||||
|
|
||||||
public partial class AssistantGrammarSpelling : AssistantBaseCore<SettingsDialogGrammarSpelling>
|
public partial class AssistantGrammarSpelling : AssistantBaseCore<SettingsDialogGrammarSpelling>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.GRAMMAR_SPELLING_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.GRAMMAR_SPELLING_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Grammar & Spelling Checker");
|
protected override string Title => T("Grammar & Spelling Checker");
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace AIStudio.Assistants.I18N;
|
|||||||
|
|
||||||
public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
|
public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.I18N_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.I18N_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Localization");
|
protected override string Title => T("Localization");
|
||||||
|
|
||||||
|
|||||||
@ -397,9 +397,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."
|
||||||
|
|
||||||
-- Not implemented yet.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet."
|
|
||||||
|
|
||||||
-- Yes, protect this policy
|
-- Yes, protect this policy
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
||||||
|
|
||||||
@ -409,9 +406,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
||||||
|
|
||||||
|
-- Hide the policy definition when distributed via configuration plugin?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1875622568"] = "Hide the policy definition when distributed via configuration plugin?"
|
||||||
|
|
||||||
-- Common settings
|
-- Common settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
||||||
|
|
||||||
|
-- Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1984494439"] = "Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create."
|
||||||
|
|
||||||
|
-- This policy is managed by your organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2035084381"] = "This policy is managed by your organization."
|
||||||
|
|
||||||
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted."
|
||||||
|
|
||||||
@ -451,6 +457,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy name
|
-- Policy name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
||||||
|
|
||||||
|
-- No policy is selected. Please select a policy to export.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2929693091"] = "No policy is selected. Please select a policy to export."
|
||||||
|
|
||||||
-- Policy Description
|
-- Policy Description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Policy Description"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Policy Description"
|
||||||
|
|
||||||
@ -466,6 +475,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy {0}
|
-- Policy {0}
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
||||||
|
|
||||||
|
-- No, show the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3166091879"] = "No, show the policy definition"
|
||||||
|
|
||||||
-- The description of your policy must be between 32 and 512 characters long.
|
-- The description of your policy must be between 32 and 512 characters long.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
||||||
|
|
||||||
@ -508,6 +520,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points."
|
||||||
|
|
||||||
|
-- The selected policy contains invalid data. Please fix the issues before exporting the policy.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T736334861"] = "The selected policy contains invalid data. Please fix the issues before exporting the policy."
|
||||||
|
|
||||||
-- Policy description
|
-- Policy description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
||||||
|
|
||||||
@ -517,6 +532,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
||||||
|
|
||||||
|
-- Yes, hide the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T940701960"] = "Yes, hide the policy definition"
|
||||||
|
|
||||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
||||||
|
|
||||||
@ -1855,21 +1873,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Limitations
|
|||||||
-- Personal Needs and Limitations of Web Services
|
-- Personal Needs and Limitations of Web Services
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Personal Needs and Limitations of Web Services"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Personal Needs and Limitations of Web Services"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations."
|
||||||
|
|
||||||
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time.
|
-- We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3569462457"] = "Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3672974243"] = "We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge."
|
||||||
|
|
||||||
-- Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3622193740"] = "Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices."
|
|
||||||
|
|
||||||
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge."
|
||||||
|
|
||||||
|
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T483341611"] = "Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community."
|
||||||
|
|
||||||
-- Cross-Platform and Modern Development
|
-- Cross-Platform and Modern Development
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platform and Modern Development"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platform and Modern Development"
|
||||||
|
|
||||||
|
-- Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T904941692"] = "Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design."
|
||||||
|
|
||||||
-- Copies the content to the clipboard
|
-- Copies the content to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"
|
||||||
|
|
||||||
@ -2131,12 +2155,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1898060643"]
|
|||||||
-- Select the language for the app.
|
-- Select the language for the app.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Select the language for the app."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Select the language for the app."
|
||||||
|
|
||||||
|
-- When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2013281167"] = "When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization."
|
||||||
|
|
||||||
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused."
|
||||||
|
|
||||||
-- Disable dictation and transcription
|
-- Disable dictation and transcription
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Disable dictation and transcription"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Disable dictation and transcription"
|
||||||
|
|
||||||
|
-- Enterprise Administration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2277116008"] = "Enterprise Administration"
|
||||||
|
|
||||||
-- Language behavior
|
-- Language behavior
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Language behavior"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Language behavior"
|
||||||
|
|
||||||
@ -2146,6 +2176,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T237706157"]
|
|||||||
-- Language
|
-- Language
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Language"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Language"
|
||||||
|
|
||||||
|
-- Administration settings are visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591866808"] = "Administration settings are visible"
|
||||||
|
|
||||||
-- Save energy?
|
-- Save energy?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Save energy?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Save energy?"
|
||||||
|
|
||||||
@ -2155,9 +2188,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3165555978"]
|
|||||||
-- App Options
|
-- App Options
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App Options"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App Options"
|
||||||
|
|
||||||
|
-- Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T362833"] = "Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings."
|
||||||
|
|
||||||
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."
|
||||||
|
|
||||||
|
-- Show administration settings?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3694781396"] = "Show administration settings?"
|
||||||
|
|
||||||
|
-- Read the Enterprise IT documentation for details.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3705451321"] = "Read the Enterprise IT documentation for details."
|
||||||
|
|
||||||
-- Enable spellchecking?
|
-- Enable spellchecking?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Enable spellchecking?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Enable spellchecking?"
|
||||||
|
|
||||||
@ -2191,9 +2233,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T817101267"]
|
|||||||
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."
|
||||||
|
|
||||||
|
-- Generate an encryption secret and copy it to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T922066419"] = "Generate an encryption secret and copy it to the clipboard"
|
||||||
|
|
||||||
|
-- Administration settings are not visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T929143445"] = "Administration settings are not visible"
|
||||||
|
|
||||||
|
-- Embedding Result
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1387042335"] = "Embedding Result"
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Delete"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Delete"
|
||||||
|
|
||||||
|
-- Embed text
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1644934561"] = "Embed text"
|
||||||
|
|
||||||
|
-- Test Embedding Provider
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1655784761"] = "Test Embedding Provider"
|
||||||
|
|
||||||
-- Add Embedding
|
-- Add Embedding
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Add Embedding"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Add Embedding"
|
||||||
|
|
||||||
@ -2206,6 +2263,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T18253
|
|||||||
-- Add Embedding Provider
|
-- Add Embedding Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Add Embedding Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Add Embedding Provider"
|
||||||
|
|
||||||
|
-- Add text that should be embedded:
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1992646324"] = "Add text that should be embedded:"
|
||||||
|
|
||||||
|
-- Embedding Vector (one dimension per line)
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2174876961"] = "Embedding Vector (one dimension per line)"
|
||||||
|
|
||||||
-- Model
|
-- Model
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Model"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Model"
|
||||||
|
|
||||||
@ -2215,6 +2278,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199
|
|||||||
-- Name
|
-- Name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
||||||
|
|
||||||
|
-- No embedding was returned.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T291969"] = "No embedding was returned."
|
||||||
|
|
||||||
-- Configured Embedding Providers
|
-- Configured Embedding Providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers"
|
||||||
|
|
||||||
@ -2224,6 +2290,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T32512
|
|||||||
-- Edit
|
-- Edit
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3448155331"] = "Close"
|
||||||
|
|
||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions"
|
||||||
|
|
||||||
@ -2245,9 +2314,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T51130
|
|||||||
-- Open Dashboard
|
-- Open Dashboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Open Dashboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Open Dashboard"
|
||||||
|
|
||||||
|
-- Test
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T805092869"] = "Test"
|
||||||
|
|
||||||
|
-- Example text to embed
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Example text to embed"
|
||||||
|
|
||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
|
-- Cannot export the encrypted API key: No enterprise encryption secret is configured.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Cannot export the encrypted API key: No enterprise encryption secret is configured."
|
||||||
|
|
||||||
|
-- This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T3368145670"] = "This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key."
|
||||||
|
|
||||||
|
-- Export API Key?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T4010580285"] = "Export API Key?"
|
||||||
|
|
||||||
-- Show provider's confidence level?
|
-- Show provider's confidence level?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?"
|
||||||
|
|
||||||
@ -2353,6 +2440,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
-- No transcription provider configured yet.
|
-- No transcription provider configured yet.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet."
|
||||||
|
|
||||||
@ -2407,6 +2497,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
-- Copy {0} to the clipboard
|
-- Copy {0} to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard"
|
||||||
|
|
||||||
@ -2443,9 +2536,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1648606751"] = "You'll be able t
|
|||||||
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question."
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer."
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2201645589"] = "We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge."
|
||||||
|
|
||||||
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats."
|
||||||
|
|
||||||
@ -2527,8 +2626,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Are you sure
|
|||||||
-- Move chat
|
-- Move chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat"
|
||||||
|
|
||||||
-- Unnamed workspace
|
-- Loading chats...
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1307384014"] = "Unnamed workspace"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1364857726"] = "Loading chats..."
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Delete"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Delete"
|
||||||
@ -2584,9 +2683,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T323280982"] = "Please enter
|
|||||||
-- Please enter a workspace name.
|
-- Please enter a workspace name.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Please enter a workspace name."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Please enter a workspace name."
|
||||||
|
|
||||||
-- Unnamed chat
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3310482275"] = "Unnamed chat"
|
|
||||||
|
|
||||||
-- Rename
|
-- Rename
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Rename"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Rename"
|
||||||
|
|
||||||
@ -3325,6 +3421,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Pro
|
|||||||
-- Cancel
|
-- Cancel
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel"
|
||||||
|
|
||||||
|
-- Embedding Vector
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T1173984541"] = "Embedding Vector"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T3448155331"] = "Close"
|
||||||
|
|
||||||
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system."
|
||||||
|
|
||||||
@ -4096,33 +4198,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
|||||||
-- Local Directory
|
-- Local Directory
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
||||||
|
|
||||||
-- Assistant: Document Analysis
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis"
|
|
||||||
|
|
||||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function."
|
|
||||||
|
|
||||||
-- Would you like to preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?"
|
|
||||||
|
|
||||||
-- Preselect document analysis options?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some document analysis options.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options."
|
|
||||||
|
|
||||||
-- No document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected"
|
|
||||||
|
|
||||||
-- Close
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close"
|
|
||||||
|
|
||||||
-- Document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected"
|
|
||||||
|
|
||||||
-- Preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some ERI server options.
|
-- When enabled, you can preselect some ERI server options.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
||||||
|
|
||||||
@ -5023,6 +5098,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T878695986"] = "Learn about one co
|
|||||||
-- Localization
|
-- Localization
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Localization"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Localization"
|
||||||
|
|
||||||
|
-- Reload your workspaces
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T194629703"] = "Reload your workspaces"
|
||||||
|
|
||||||
-- Hide your workspaces
|
-- Hide your workspaces
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Hide your workspaces"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Hide your workspaces"
|
||||||
|
|
||||||
@ -5068,6 +5146,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T149711988"] = "You only pay for what yo
|
|||||||
-- Assistants
|
-- Assistants
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistants"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistants"
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1628689293"] = "We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models."
|
||||||
|
|
||||||
-- Unrestricted usage
|
-- Unrestricted usage
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unrestricted usage"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unrestricted usage"
|
||||||
|
|
||||||
@ -5077,6 +5158,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1702902297"] = "Introduction"
|
|||||||
-- Vision
|
-- Vision
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- Let's get started
|
-- Let's get started
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Let's get started"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Let's get started"
|
||||||
|
|
||||||
@ -5131,18 +5215,33 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1019424746"] = "Startup log file
|
|||||||
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Browse AI Studio's source code on GitHub — we welcome your contributions."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Browse AI Studio's source code on GitHub — we welcome your contributions."
|
||||||
|
|
||||||
|
-- ID mismatch: the plugin ID differs from the enterprise configuration ID.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1137744461"] = "ID mismatch: the plugin ID differs from the enterprise configuration ID."
|
||||||
|
|
||||||
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1282228996"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available."
|
|
||||||
|
|
||||||
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."
|
||||||
|
|
||||||
|
-- Database version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1420062548"] = "Database version"
|
||||||
|
|
||||||
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."
|
||||||
|
|
||||||
|
-- Waiting for the configuration plugin...
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1533382393"] = "Waiting for the configuration plugin..."
|
||||||
|
|
||||||
|
-- Encryption secret: is not configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1560776885"] = "Encryption secret: is not configured"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1596483935"] = "AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active."
|
||||||
|
|
||||||
|
-- Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG—retrieval-augmented generation—within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1619832053"] = "Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG—retrieval-augmented generation—within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant."
|
||||||
|
|
||||||
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library."
|
||||||
|
|
||||||
@ -5176,9 +5275,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1915240766"] = "In order to use
|
|||||||
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."
|
||||||
|
|
||||||
|
-- Encryption secret: is configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1931141322"] = "Encryption secret: is configured"
|
||||||
|
|
||||||
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust."
|
||||||
|
|
||||||
|
-- Copies the following to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2029659664"] = "Copies the following to the clipboard"
|
||||||
|
|
||||||
-- Copies the server URL to the clipboard
|
-- Copies the server URL to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Copies the server URL to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Copies the server URL to the clipboard"
|
||||||
|
|
||||||
@ -5197,9 +5302,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2272122662"] = "Configuration se
|
|||||||
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2280402765"] = "AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management."
|
|
||||||
|
|
||||||
-- Configuration plugin ID:
|
-- Configuration plugin ID:
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Configuration plugin ID:"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Configuration plugin ID:"
|
||||||
|
|
||||||
@ -5224,6 +5326,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2557066213"] = "Used Open Source
|
|||||||
-- Build time
|
-- Build time
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build time"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build time"
|
||||||
|
|
||||||
|
-- This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2619858133"] = "This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant."
|
||||||
|
|
||||||
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems."
|
||||||
|
|
||||||
@ -5260,6 +5365,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2840582448"] = "Explanation"
|
|||||||
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software."
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2924964415"] = "AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available."
|
||||||
|
|
||||||
-- Changelog
|
-- Changelog
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Changelog"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Changelog"
|
||||||
|
|
||||||
@ -5293,6 +5401,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3433065373"] = "Information abou
|
|||||||
-- Used Rust compiler
|
-- Used Rust compiler
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Used Rust compiler"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Used Rust compiler"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3449345633"] = "AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management."
|
||||||
|
|
||||||
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!"
|
||||||
|
|
||||||
@ -5302,9 +5413,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3563271893"] = "Motivation"
|
|||||||
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3741877842"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active."
|
|
||||||
|
|
||||||
-- this version does not met the requirements
|
-- this version does not met the requirements
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "this version does not met the requirements"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "this version does not met the requirements"
|
||||||
|
|
||||||
@ -5341,6 +5449,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T566998575"] = "This is a library
|
|||||||
-- Used .NET SDK
|
-- Used .NET SDK
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Used .NET SDK"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Used .NET SDK"
|
||||||
|
|
||||||
|
-- This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T633932150"] = "This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated."
|
||||||
|
|
||||||
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Did you find a bug or are you experiencing issues? Report your concern here."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Did you find a bug or are you experiencing issues? Report your concern here."
|
||||||
|
|
||||||
@ -5371,6 +5482,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Internal Plugins"
|
|||||||
-- Disabled Plugins
|
-- Disabled Plugins
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
|
||||||
|
|
||||||
|
-- Send a mail
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1999487139"] = "Send a mail"
|
||||||
|
|
||||||
-- Enable plugin
|
-- Enable plugin
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
||||||
|
|
||||||
@ -5383,6 +5497,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Enabled Plugins"
|
|||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
|
||||||
|
|
||||||
|
-- Open website
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4239378936"] = "Open website"
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Settings"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Settings"
|
||||||
|
|
||||||
@ -5902,6 +6019,21 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T3893997203"] = "
|
|||||||
-- Trust all LLM providers
|
-- Trust all LLM providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Trust all LLM providers"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Trust all LLM providers"
|
||||||
|
|
||||||
|
-- Storage size
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
|
||||||
|
|
||||||
|
-- HTTP port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1717573768"] = "HTTP port"
|
||||||
|
|
||||||
|
-- Reported version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T3556099842"] = "Reported version"
|
||||||
|
|
||||||
|
-- gRPC port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T757840040"] = "gRPC port"
|
||||||
|
|
||||||
|
-- Number of collections
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T842647336"] = "Number of collections"
|
||||||
|
|
||||||
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment."
|
||||||
|
|
||||||
@ -6091,15 +6223,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2262604281"] = "The
|
|||||||
-- The field DESCRIPTION does not exist or is not a valid string.
|
-- The field DESCRIPTION does not exist or is not a valid string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "The field DESCRIPTION does not exist or is not a valid string."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "The field DESCRIPTION does not exist or is not a valid string."
|
||||||
|
|
||||||
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://' or 'https://'.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2320984047"] = "The field SOURCE_URL is not a valid URL. The URL must start with 'http://' or 'https://'."
|
|
||||||
|
|
||||||
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X)."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X)."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://', 'https://', or 'mailto:'.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2892057533"] = "The field SOURCE_URL is not a valid URL. The URL must start with 'http://', 'https://', or 'mailto:'."
|
||||||
|
|
||||||
-- The table AUTHORS is empty. At least one author must be specified.
|
-- The table AUTHORS is empty. At least one author must be specified.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "The table AUTHORS is empty. At least one author must be specified."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "The table AUTHORS is empty. At least one author must be specified."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. When the URL starts with 'mailto:', it must contain a valid email address as recipient.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3165663073"] = "The field SOURCE_URL is not a valid URL. When the URL starts with 'mailto:', it must contain a valid email address as recipient."
|
||||||
|
|
||||||
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string."
|
||||||
|
|
||||||
@ -6507,3 +6642,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unnamed w
|
|||||||
|
|
||||||
-- Delete Chat
|
-- Delete Chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Delete Chat"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Delete Chat"
|
||||||
|
|
||||||
|
-- Unnamed chat
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3310482275"] = "Unnamed chat"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ namespace AIStudio.Assistants.IconFinder;
|
|||||||
|
|
||||||
public partial class AssistantIconFinder : AssistantBaseCore<SettingsDialogIconFinder>
|
public partial class AssistantIconFinder : AssistantBaseCore<SettingsDialogIconFinder>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.ICON_FINDER_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.ICON_FINDER_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Icon Finder");
|
protected override string Title => T("Icon Finder");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.JobPosting;
|
|||||||
|
|
||||||
public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobPostings>
|
public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobPostings>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.JOB_POSTING_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.JOB_POSTING_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Job Posting");
|
protected override string Title => T("Job Posting");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.LegalCheck;
|
|||||||
|
|
||||||
public partial class AssistantLegalCheck : AssistantBaseCore<SettingsDialogLegalCheck>
|
public partial class AssistantLegalCheck : AssistantBaseCore<SettingsDialogLegalCheck>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.LEGAL_CHECK_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.LEGAL_CHECK_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Legal Check");
|
protected override string Title => T("Legal Check");
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ namespace AIStudio.Assistants.MyTasks;
|
|||||||
|
|
||||||
public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
|
public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.MY_TASKS_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.MY_TASKS_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("My Tasks");
|
protected override string Title => T("My Tasks");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.RewriteImprove;
|
|||||||
|
|
||||||
public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogRewrite>
|
public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogRewrite>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.REWRITE_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.REWRITE_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Rewrite & Improve Text");
|
protected override string Title => T("Rewrite & Improve Text");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.Synonym;
|
|||||||
|
|
||||||
public partial class AssistantSynonyms : AssistantBaseCore<SettingsDialogSynonyms>
|
public partial class AssistantSynonyms : AssistantBaseCore<SettingsDialogSynonyms>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.SYNONYMS_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.SYNONYMS_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Synonyms");
|
protected override string Title => T("Synonyms");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.TextSummarizer;
|
|||||||
|
|
||||||
public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogTextSummarizer>
|
public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogTextSummarizer>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.TEXT_SUMMARIZER_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.TEXT_SUMMARIZER_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Text Summarizer");
|
protected override string Title => T("Text Summarizer");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace AIStudio.Assistants.Translation;
|
|||||||
|
|
||||||
public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTranslation>
|
public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTranslation>
|
||||||
{
|
{
|
||||||
public override Tools.Components Component => Tools.Components.TRANSLATION_ASSISTANT;
|
protected override Tools.Components Component => Tools.Components.TRANSLATION_ASSISTANT;
|
||||||
|
|
||||||
protected override string Title => T("Translation");
|
protected override string Title => T("Translation");
|
||||||
|
|
||||||
|
|||||||
@ -96,10 +96,10 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudMarkdown Value="@textContent.Text.RemoveThinkTags().Trim()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" />
|
<MudMarkdown Value="@NormalizeMarkdownForRendering(textContent.Text)" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE" />
|
||||||
@if (textContent.Sources.Count > 0)
|
@if (textContent.Sources.Count > 0)
|
||||||
{
|
{
|
||||||
<MudMarkdown Value="@textContent.Sources.ToMarkdown()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" />
|
<MudMarkdown Value="@textContent.Sources.ToMarkdown()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,18 @@ namespace AIStudio.Chat;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ContentBlockComponent : MSGComponentBase
|
public partial class ContentBlockComponent : MSGComponentBase
|
||||||
{
|
{
|
||||||
|
private static readonly string[] HTML_TAG_MARKERS =
|
||||||
|
[
|
||||||
|
"<!doctype",
|
||||||
|
"<html",
|
||||||
|
"<head",
|
||||||
|
"<body",
|
||||||
|
"<style",
|
||||||
|
"<script",
|
||||||
|
"<iframe",
|
||||||
|
"<svg",
|
||||||
|
];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The role of the chat content block.
|
/// The role of the chat content block.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,18 +80,37 @@ public partial class ContentBlockComponent : MSGComponentBase
|
|||||||
private RustService RustService { get; init; } = null!;
|
private RustService RustService { get; init; } = null!;
|
||||||
|
|
||||||
private bool HideContent { get; set; }
|
private bool HideContent { get; set; }
|
||||||
|
private bool hasRenderHash;
|
||||||
|
private int lastRenderHash;
|
||||||
|
|
||||||
#region Overrides of ComponentBase
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
// Register the streaming events:
|
this.RegisterStreamingEvents();
|
||||||
this.Content.StreamingDone = this.AfterStreaming;
|
|
||||||
this.Content.StreamingEvent = () => this.InvokeAsync(this.StateHasChanged);
|
|
||||||
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
this.RegisterStreamingEvents();
|
||||||
|
return base.OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override bool ShouldRender()
|
||||||
|
{
|
||||||
|
var currentRenderHash = this.CreateRenderHash();
|
||||||
|
if (!this.hasRenderHash || currentRenderHash != this.lastRenderHash)
|
||||||
|
{
|
||||||
|
this.lastRenderHash = currentRenderHash;
|
||||||
|
this.hasRenderHash = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets called when the content stream ended.
|
/// Gets called when the content stream ended.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -111,6 +142,47 @@ public partial class ContentBlockComponent : MSGComponentBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RegisterStreamingEvents()
|
||||||
|
{
|
||||||
|
this.Content.StreamingDone = this.AfterStreaming;
|
||||||
|
this.Content.StreamingEvent = () => this.InvokeAsync(this.StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CreateRenderHash()
|
||||||
|
{
|
||||||
|
var hash = new HashCode();
|
||||||
|
hash.Add(this.Role);
|
||||||
|
hash.Add(this.Type);
|
||||||
|
hash.Add(this.Time);
|
||||||
|
hash.Add(this.Class);
|
||||||
|
hash.Add(this.IsLastContentBlock);
|
||||||
|
hash.Add(this.IsSecondToLastBlock);
|
||||||
|
hash.Add(this.HideContent);
|
||||||
|
hash.Add(this.SettingsManager.IsDarkMode);
|
||||||
|
hash.Add(this.RegenerateEnabled());
|
||||||
|
hash.Add(this.Content.InitialRemoteWait);
|
||||||
|
hash.Add(this.Content.IsStreaming);
|
||||||
|
hash.Add(this.Content.FileAttachments.Count);
|
||||||
|
hash.Add(this.Content.Sources.Count);
|
||||||
|
|
||||||
|
switch (this.Content)
|
||||||
|
{
|
||||||
|
case ContentText text:
|
||||||
|
var textValue = text.Text;
|
||||||
|
hash.Add(textValue.Length);
|
||||||
|
hash.Add(textValue.GetHashCode(StringComparison.Ordinal));
|
||||||
|
hash.Add(text.Sources.Count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ContentImage image:
|
||||||
|
hash.Add(image.SourceType);
|
||||||
|
hash.Add(image.Source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash.ToHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private string CardClasses => $"my-2 rounded-lg {this.Class}";
|
private string CardClasses => $"my-2 rounded-lg {this.Class}";
|
||||||
@ -122,6 +194,34 @@ public partial class ContentBlockComponent : MSGComponentBase
|
|||||||
CodeBlock = { Theme = this.CodeColorPalette },
|
CodeBlock = { Theme = this.CodeColorPalette },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static string NormalizeMarkdownForRendering(string text)
|
||||||
|
{
|
||||||
|
var cleaned = text.RemoveThinkTags().Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(cleaned))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
if (cleaned.Contains("```", StringComparison.Ordinal))
|
||||||
|
return cleaned;
|
||||||
|
|
||||||
|
if (LooksLikeRawHtml(cleaned))
|
||||||
|
return $"```html{Environment.NewLine}{cleaned}{Environment.NewLine}```";
|
||||||
|
|
||||||
|
return cleaned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool LooksLikeRawHtml(string text)
|
||||||
|
{
|
||||||
|
var content = text.TrimStart();
|
||||||
|
if (!content.StartsWith("<", StringComparison.Ordinal))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var marker in HTML_TAG_MARKERS)
|
||||||
|
if (content.Contains(marker, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return content.Contains("</", StringComparison.Ordinal) || content.Contains("/>", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RemoveBlock()
|
private async Task RemoveBlock()
|
||||||
{
|
{
|
||||||
if (this.RemoveBlockFunc is null)
|
if (this.RemoveBlockFunc is null)
|
||||||
|
|||||||
@ -26,7 +26,10 @@
|
|||||||
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@this.Icon" Color="Color.Default" Href="@this.Link">
|
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@this.Icon" Color="Color.Default" Href="@this.Link">
|
||||||
@this.ButtonText
|
@this.ButtonText
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" Color="Color.Default" OnClick="@this.OpenSettingsDialog"/>
|
@if (this.HasSettingsPanel)
|
||||||
|
{
|
||||||
|
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" Color="Color.Default" OnClick="@this.OpenSettingsDialog"/>
|
||||||
|
}
|
||||||
</MudButtonGroup>
|
</MudButtonGroup>
|
||||||
</MudCardActions>
|
</MudCardActions>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using AIStudio.Settings.DataModel;
|
using AIStudio.Settings.DataModel;
|
||||||
|
using AIStudio.Dialogs.Settings;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
@ -37,6 +38,9 @@ public partial class AssistantBlock<TSettings> : MSGComponentBase where TSetting
|
|||||||
|
|
||||||
private async Task OpenSettingsDialog()
|
private async Task OpenSettingsDialog()
|
||||||
{
|
{
|
||||||
|
if (!this.HasSettingsPanel)
|
||||||
|
return;
|
||||||
|
|
||||||
var dialogParameters = new DialogParameters();
|
var dialogParameters = new DialogParameters();
|
||||||
|
|
||||||
await this.DialogService.ShowAsync<TSettings>(T("Open Settings"), dialogParameters, DialogOptions.FULLSCREEN);
|
await this.DialogService.ShowAsync<TSettings>(T("Open Settings"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
@ -51,4 +55,6 @@ public partial class AssistantBlock<TSettings> : MSGComponentBase where TSetting
|
|||||||
private string BlockStyle => $"border-width: 2px; border-color: {this.BorderColor}; border-radius: 12px; border-style: solid; max-width: 20em;";
|
private string BlockStyle => $"border-width: 2px; border-color: {this.BorderColor}; border-radius: 12px; border-style: solid; max-width: 20em;";
|
||||||
|
|
||||||
private bool IsVisible => this.SettingsManager.IsAssistantVisible(this.Component, assistantName: this.Name, requiredPreviewFeature: this.RequiredPreviewFeature);
|
private bool IsVisible => this.SettingsManager.IsAssistantVisible(this.Component, assistantName: this.Name, requiredPreviewFeature: this.RequiredPreviewFeature);
|
||||||
|
|
||||||
|
private bool HasSettingsPanel => typeof(TSettings) != typeof(NoSettingsPanel);
|
||||||
}
|
}
|
||||||
@ -13,6 +13,8 @@ public partial class Changelog
|
|||||||
|
|
||||||
public static readonly Log[] LOGS =
|
public static readonly Log[] LOGS =
|
||||||
[
|
[
|
||||||
|
new (234, "v26.2.2, build 234 (2026-02-22 14:16 UTC)", "v26.2.2.md"),
|
||||||
|
new (233, "v26.2.1, build 233 (2026-02-01 19:16 UTC)", "v26.2.1.md"),
|
||||||
new (232, "v26.1.2, build 232 (2026-01-25 14:05 UTC)", "v26.1.2.md"),
|
new (232, "v26.1.2, build 232 (2026-01-25 14:05 UTC)", "v26.1.2.md"),
|
||||||
new (231, "v26.1.1, build 231 (2026-01-11 15:53 UTC)", "v26.1.1.md"),
|
new (231, "v26.1.1, build 231 (2026-01-11 15:53 UTC)", "v26.1.1.md"),
|
||||||
new (230, "v0.10.0, build 230 (2025-12-31 14:04 UTC)", "v0.10.0.md"),
|
new (230, "v0.10.0, build 230 (2025-12-31 14:04 UTC)", "v0.10.0.md"),
|
||||||
|
|||||||
@ -6,4 +6,4 @@
|
|||||||
}
|
}
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
|
|
||||||
<MudMarkdown Value="@this.LogContent" Props="Markdown.DefaultConfig"/>
|
<MudMarkdown Value="@this.LogContent" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
@ -16,6 +16,7 @@
|
|||||||
@if (!block.HideFromUser)
|
@if (!block.HideFromUser)
|
||||||
{
|
{
|
||||||
<ContentBlockComponent
|
<ContentBlockComponent
|
||||||
|
@key="@block"
|
||||||
Role="@block.Role"
|
Role="@block.Role"
|
||||||
Type="@block.ContentType"
|
Type="@block.ContentType"
|
||||||
Time="@block.Time"
|
Time="@block.Time"
|
||||||
@ -66,7 +67,7 @@
|
|||||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY)
|
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY)
|
||||||
{
|
{
|
||||||
<MudTooltip Text="@T("Save chat")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="@T("Save chat")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="@(() => this.SaveThread())" Disabled="@(!this.CanThreadBeSaved)"/>
|
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="@(() => this.SaveThread())" Disabled="@(!this.CanThreadBeSaved || this.isStreaming)"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
private bool autoSaveEnabled;
|
private bool autoSaveEnabled;
|
||||||
private string currentWorkspaceName = string.Empty;
|
private string currentWorkspaceName = string.Empty;
|
||||||
private Guid currentWorkspaceId = Guid.Empty;
|
private Guid currentWorkspaceId = Guid.Empty;
|
||||||
|
private Guid currentChatThreadId = Guid.Empty;
|
||||||
private CancellationTokenSource? cancellationTokenSource;
|
private CancellationTokenSource? cancellationTokenSource;
|
||||||
private HashSet<FileAttachment> chatDocumentPaths = [];
|
private HashSet<FileAttachment> chatDocumentPaths = [];
|
||||||
|
|
||||||
@ -197,8 +198,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
//
|
//
|
||||||
if (this.ChatThread is not null)
|
if (this.ChatThread is not null)
|
||||||
{
|
{
|
||||||
|
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceName(this.ChatThread.WorkspaceId);
|
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +216,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
this.mustStoreChat = false;
|
this.mustStoreChat = false;
|
||||||
|
|
||||||
if(this.Workspaces is not null)
|
if(this.Workspaces is not null)
|
||||||
await this.Workspaces.StoreChat(this.ChatThread);
|
await this.Workspaces.StoreChatAsync(this.ChatThread);
|
||||||
else
|
else
|
||||||
await WorkspaceBehaviour.StoreChat(this.ChatThread);
|
await WorkspaceBehaviour.StoreChatAsync(this.ChatThread);
|
||||||
|
|
||||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceName(this.ChatThread.WorkspaceId);
|
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,14 +229,14 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
{
|
{
|
||||||
this.Logger.LogInformation($"Try to load the chat '{this.loadChat.ChatId}' now.");
|
this.Logger.LogInformation($"Try to load the chat '{this.loadChat.ChatId}' now.");
|
||||||
this.mustLoadChat = false;
|
this.mustLoadChat = false;
|
||||||
this.ChatThread = await WorkspaceBehaviour.LoadChat(this.loadChat);
|
this.ChatThread = await WorkspaceBehaviour.LoadChatAsync(this.loadChat);
|
||||||
|
|
||||||
if(this.ChatThread is not null)
|
if(this.ChatThread is not null)
|
||||||
{
|
{
|
||||||
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
|
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
|
||||||
this.Logger.LogInformation($"The chat '{this.ChatThread!.ChatId}' with title '{this.ChatThread.Name}' ({this.ChatThread.Blocks.Count} messages) was loaded successfully.");
|
this.Logger.LogInformation($"The chat '{this.ChatThread!.ChatId}' with title '{this.ChatThread.Name}' ({this.ChatThread.Blocks.Count} messages) was loaded successfully.");
|
||||||
|
|
||||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceName(this.ChatThread.WorkspaceId);
|
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
await this.SelectProviderWhenLoadingChat();
|
await this.SelectProviderWhenLoadingChat();
|
||||||
}
|
}
|
||||||
@ -260,8 +262,50 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
await base.OnAfterRenderAsync(firstRender);
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||||
|
await base.OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private async Task SyncWorkspaceHeaderWithChatThreadAsync()
|
||||||
|
{
|
||||||
|
if (this.ChatThread is null)
|
||||||
|
{
|
||||||
|
if (this.currentChatThreadId != Guid.Empty || this.currentWorkspaceId != Guid.Empty || !string.IsNullOrWhiteSpace(this.currentWorkspaceName))
|
||||||
|
{
|
||||||
|
this.currentChatThreadId = Guid.Empty;
|
||||||
|
this.currentWorkspaceId = Guid.Empty;
|
||||||
|
this.currentWorkspaceName = string.Empty;
|
||||||
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guard: If ChatThread ID and WorkspaceId haven't changed, skip entirely.
|
||||||
|
// Using ID-based comparison instead of name-based to correctly handle
|
||||||
|
// temporary chats where the workspace name is always empty.
|
||||||
|
if (this.currentChatThreadId == this.ChatThread.ChatId
|
||||||
|
&& this.currentWorkspaceId == this.ChatThread.WorkspaceId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||||
|
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||||
|
var loadedWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
|
|
||||||
|
// Only notify the parent when the name actually changed to prevent
|
||||||
|
// an infinite render loop: WorkspaceName → UpdateWorkspaceName →
|
||||||
|
// StateHasChanged → re-render → OnParametersSetAsync → WorkspaceName → ...
|
||||||
|
if (this.currentWorkspaceName != loadedWorkspaceName)
|
||||||
|
{
|
||||||
|
this.currentWorkspaceName = loadedWorkspaceName;
|
||||||
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsProviderSelected => this.Provider.UsedLLMProvider != LLMProviders.NONE;
|
private bool IsProviderSelected => this.Provider.UsedLLMProvider != LLMProviders.NONE;
|
||||||
|
|
||||||
private string ProviderPlaceholder => this.IsProviderSelected ? T("Type your input here...") : T("Select a provider first");
|
private string ProviderPlaceholder => this.IsProviderSelected ? T("Type your input here...") : T("Select a provider first");
|
||||||
@ -428,8 +472,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
if(!this.ChatThread.IsLLMProviderAllowed(this.Provider))
|
if(!this.ChatThread.IsLLMProviderAllowed(this.Provider))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We need to blur the focus away from the input field
|
// Blur the focus away from the input field to be able to clear it:
|
||||||
// to be able to clear the field:
|
|
||||||
await this.inputField.BlurAsync();
|
await this.inputField.BlurAsync();
|
||||||
|
|
||||||
// Create a new chat thread if necessary:
|
// Create a new chat thread if necessary:
|
||||||
@ -520,8 +563,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
|
|
||||||
// Clear the input field:
|
// Clear the input field:
|
||||||
await this.inputField.FocusAsync();
|
await this.inputField.FocusAsync();
|
||||||
|
|
||||||
this.userInput = string.Empty;
|
this.userInput = string.Empty;
|
||||||
this.chatDocumentPaths.Clear();
|
this.chatDocumentPaths.Clear();
|
||||||
|
|
||||||
await this.inputField.BlurAsync();
|
await this.inputField.BlurAsync();
|
||||||
|
|
||||||
// Enable the stream state for the chat component:
|
// Enable the stream state for the chat component:
|
||||||
@ -583,9 +628,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
// the workspace gets updated automatically when the chat is saved.
|
// the workspace gets updated automatically when the chat is saved.
|
||||||
//
|
//
|
||||||
if (this.Workspaces is not null)
|
if (this.Workspaces is not null)
|
||||||
await this.Workspaces.StoreChat(this.ChatThread);
|
await this.Workspaces.StoreChatAsync(this.ChatThread);
|
||||||
else
|
else
|
||||||
await WorkspaceBehaviour.StoreChat(this.ChatThread);
|
await WorkspaceBehaviour.StoreChatAsync(this.ChatThread);
|
||||||
|
|
||||||
this.hasUnsavedChanges = false;
|
this.hasUnsavedChanges = false;
|
||||||
}
|
}
|
||||||
@ -621,9 +666,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
chatPath = Path.Join(SettingsManager.DataDirectory, "workspaces", this.ChatThread.WorkspaceId.ToString(), this.ChatThread.ChatId.ToString());
|
chatPath = Path.Join(SettingsManager.DataDirectory, "workspaces", this.ChatThread.WorkspaceId.ToString(), this.ChatThread.ChatId.ToString());
|
||||||
|
|
||||||
if(this.Workspaces is null)
|
if(this.Workspaces is null)
|
||||||
await WorkspaceBehaviour.DeleteChat(this.DialogService, this.ChatThread.WorkspaceId, this.ChatThread.ChatId, askForConfirmation: false);
|
await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, this.ChatThread.WorkspaceId, this.ChatThread.ChatId, askForConfirmation: false);
|
||||||
else
|
else
|
||||||
await this.Workspaces.DeleteChat(chatPath, askForConfirmation: false, unloadChat: true);
|
await this.Workspaces.DeleteChatAsync(chatPath, askForConfirmation: false, unloadChat: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -665,6 +710,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
// to reset the chat thread:
|
// to reset the chat thread:
|
||||||
//
|
//
|
||||||
this.ChatThread = null;
|
this.ChatThread = null;
|
||||||
|
this.currentChatThreadId = Guid.Empty;
|
||||||
this.currentWorkspaceId = Guid.Empty;
|
this.currentWorkspaceId = Guid.Empty;
|
||||||
this.currentWorkspaceName = string.Empty;
|
this.currentWorkspaceName = string.Empty;
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
@ -739,13 +785,13 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Delete the chat from the current workspace or the temporary storage:
|
// Delete the chat from the current workspace or the temporary storage:
|
||||||
await WorkspaceBehaviour.DeleteChat(this.DialogService, this.ChatThread!.WorkspaceId, this.ChatThread.ChatId, askForConfirmation: false);
|
await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, this.ChatThread!.WorkspaceId, this.ChatThread.ChatId, askForConfirmation: false);
|
||||||
|
|
||||||
this.ChatThread!.WorkspaceId = workspaceId;
|
this.ChatThread!.WorkspaceId = workspaceId;
|
||||||
await this.SaveThread();
|
await this.SaveThread();
|
||||||
|
|
||||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceName(this.ChatThread.WorkspaceId);
|
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,12 +804,14 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
if (this.ChatThread is not null)
|
if (this.ChatThread is not null)
|
||||||
{
|
{
|
||||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceName(this.ChatThread.WorkspaceId);
|
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
|
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||||
this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources);
|
this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.currentChatThreadId = Guid.Empty;
|
||||||
this.currentWorkspaceId = Guid.Empty;
|
this.currentWorkspaceId = Guid.Empty;
|
||||||
this.currentWorkspaceName = string.Empty;
|
this.currentWorkspaceName = string.Empty;
|
||||||
this.WorkspaceName(this.currentWorkspaceName);
|
this.WorkspaceName(this.currentWorkspaceName);
|
||||||
@ -785,6 +833,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
this.isStreaming = false;
|
this.isStreaming = false;
|
||||||
this.hasUnsavedChanges = false;
|
this.hasUnsavedChanges = false;
|
||||||
this.userInput = string.Empty;
|
this.userInput = string.Empty;
|
||||||
|
this.currentChatThreadId = Guid.Empty;
|
||||||
this.currentWorkspaceId = Guid.Empty;
|
this.currentWorkspaceId = Guid.Empty;
|
||||||
|
|
||||||
this.currentWorkspaceName = string.Empty;
|
this.currentWorkspaceName = string.Empty;
|
||||||
@ -912,6 +961,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Event.CHAT_STREAMING_DONE:
|
case Event.CHAT_STREAMING_DONE:
|
||||||
|
// Streaming mutates the last AI block over time.
|
||||||
|
// In manual storage mode, a save during streaming must not
|
||||||
|
// mark the final streamed state as already persisted.
|
||||||
|
this.hasUnsavedChanges = true;
|
||||||
if(this.autoSaveEnabled)
|
if(this.autoSaveEnabled)
|
||||||
await this.SaveThread();
|
await this.SaveThread();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
<MudText Typo="Typo.h6">
|
<MudText Typo="Typo.h6">
|
||||||
@T("Description")
|
@T("Description")
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudMarkdown Value="@this.currentConfidence.Description"/>
|
<MudMarkdown Value="@this.currentConfidence.Description" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
|
|
||||||
@if (this.currentConfidence.Sources.Count > 0)
|
@if (this.currentConfidence.Sources.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
10
app/MindWork AI Studio/Components/ConfigInfoRow.razor
Normal file
10
app/MindWork AI Studio/Components/ConfigInfoRow.razor
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div style="display: flex; align-items: center; gap: 8px; @this.Item.Style">
|
||||||
|
<MudIcon Icon="@this.Item.Icon"/>
|
||||||
|
<span>
|
||||||
|
@this.Item.Text
|
||||||
|
</span>
|
||||||
|
@if (!string.IsNullOrWhiteSpace(this.Item.CopyValue))
|
||||||
|
{
|
||||||
|
<MudCopyClipboardButton TooltipMessage="@this.Item.CopyTooltip" StringContent="@this.Item.CopyValue"/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
9
app/MindWork AI Studio/Components/ConfigInfoRow.razor.cs
Normal file
9
app/MindWork AI Studio/Components/ConfigInfoRow.razor.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public partial class ConfigInfoRow : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public ConfigInfoRowItem Item { get; set; } = new(Icons.Material.Filled.ArrowRightAlt, string.Empty, string.Empty, string.Empty, string.Empty);
|
||||||
|
}
|
||||||
9
app/MindWork AI Studio/Components/ConfigInfoRowItem.cs
Normal file
9
app/MindWork AI Studio/Components/ConfigInfoRowItem.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public sealed record ConfigInfoRowItem(
|
||||||
|
string Icon,
|
||||||
|
string Text,
|
||||||
|
string CopyValue,
|
||||||
|
string CopyTooltip,
|
||||||
|
string Style = ""
|
||||||
|
);
|
||||||
21
app/MindWork AI Studio/Components/ConfigPluginInfoCard.razor
Normal file
21
app/MindWork AI Studio/Components/ConfigPluginInfoCard.razor
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<MudPaper Outlined="true" Class="@this.Class">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
|
||||||
|
<MudIcon Icon="@this.HeaderIcon" Size="Size.Small"/>
|
||||||
|
<MudText Typo="Typo.subtitle2">
|
||||||
|
@this.HeaderText
|
||||||
|
</MudText>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach (var item in this.Items)
|
||||||
|
{
|
||||||
|
<ConfigInfoRow Item="@item"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (this.ShowWarning)
|
||||||
|
{
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px; margin-top: 4px;">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Warning" Size="Size.Small" Color="Color.Warning"/>
|
||||||
|
<MudText Typo="Typo.subtitle2">@this.WarningText</MudText>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</MudPaper>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public partial class ConfigPluginInfoCard : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public string HeaderIcon { get; set; } = Icons.Material.Filled.Extension;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string HeaderText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public IEnumerable<ConfigInfoRowItem> Items { get; set; } = [];
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool ShowWarning { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string WarningText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Class { get; set; } = "pa-3 mt-2 mb-2";
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
@using AIStudio.Settings
|
@using AIStudio.Settings
|
||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
<ConfigurationSelect IsLocked="this.IsLocked" Disabled="this.Disabled" OptionDescription="@T("Select a minimum confidence level")" SelectedValue="@this.FilteredSelectedValue" Data="@ConfigurationSelectDataFactory.GetConfidenceLevelsData(this.SettingsManager, this.RestrictToGlobalMinimumConfidence)" SelectionUpdate="@this.SelectionUpdate" OptionHelp="@T("Choose the minimum confidence level that all LLM providers must meet. This way, you can ensure that only trustworthy providers are used. You cannot use any provider that falls below this level.")"/>
|
<ConfigurationSelect IsLocked="this.IsLocked" Disabled="this.Disabled" OptionDescription="@T("Select a minimum confidence level")" SelectedValue="@this.FilteredSelectedValue" Data="@ConfigurationSelectDataFactory.GetConfidenceLevelsData(this.SettingsManager, this.RestrictToGlobalMinimumConfidence)" SelectionUpdate="@this.SelectionUpdate" SelectionUpdateAsync="@this.SelectionUpdateAsync" OptionHelp="@T("Choose the minimum confidence level that all LLM providers must meet. This way, you can ensure that only trustworthy providers are used. You cannot use any provider that falls below this level.")"/>
|
||||||
@ -18,6 +18,12 @@ public partial class ConfigurationMinConfidenceSelection : MSGComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<ConfidenceLevel> SelectionUpdate { get; set; } = _ => { };
|
public Action<ConfidenceLevel> SelectionUpdate { get; set; } = _ => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An asynchronous action that is called when the selection changes.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Func<ConfidenceLevel, Task> SelectionUpdateAsync { get; set; } = _ => Task.CompletedTask;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Boolean value indicating whether the selection is restricted to a global minimum confidence level.
|
/// Boolean value indicating whether the selection is restricted to a global minimum confidence level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -14,8 +14,22 @@
|
|||||||
SelectedValuesChanged="@this.OptionChanged">
|
SelectedValuesChanged="@this.OptionChanged">
|
||||||
@foreach (var data in this.Data)
|
@foreach (var data in this.Data)
|
||||||
{
|
{
|
||||||
<MudSelectItemExtended Value="@data.Value">
|
var isLockedValue = this.IsLockedValue(data.Value);
|
||||||
@data.Name
|
<MudSelectItemExtended Value="@data.Value" Disabled="@isLockedValue" Style="@(isLockedValue ? "pointer-events:auto !important;" : null)">
|
||||||
|
@if (isLockedValue)
|
||||||
|
{
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.FlexStart" Wrap="Wrap.NoWrap">
|
||||||
|
@* MudTooltip.RootStyle is set as a workaround for issue -> https://github.com/MudBlazor/MudBlazor/issues/10882 *@
|
||||||
|
<MudTooltip Text="@this.LockedTooltip()" Arrow="true" Placement="Placement.Right" RootStyle="display:inline-flex;">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Lock" Color="Color.Error" Size="Size.Small" Class="mr-1"/>
|
||||||
|
</MudTooltip>
|
||||||
|
@data.Name
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@data.Name
|
||||||
|
}
|
||||||
</MudSelectItemExtended>
|
</MudSelectItemExtended>
|
||||||
}
|
}
|
||||||
</MudSelectExtended>
|
</MudSelectExtended>
|
||||||
@ -28,6 +28,12 @@ public partial class ConfigurationMultiSelect<TData> : ConfigurationBaseCore
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<HashSet<TData>> SelectionUpdate { get; set; } = _ => { };
|
public Action<HashSet<TData>> SelectionUpdate { get; set; } = _ => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether a specific item is locked by a configuration plugin.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Func<TData, bool> IsItemLocked { get; set; } = _ => false;
|
||||||
|
|
||||||
#region Overrides of ConfigurationBase
|
#region Overrides of ConfigurationBase
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -62,4 +68,12 @@ public partial class ConfigurationMultiSelect<TData> : ConfigurationBaseCore
|
|||||||
|
|
||||||
return string.Format(T("You have selected {0} preview features."), selectedValues.Count);
|
return string.Format(T("You have selected {0} preview features."), selectedValues.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsLockedValue(TData value) => this.IsItemLocked(value);
|
||||||
|
|
||||||
|
private string LockedTooltip() =>
|
||||||
|
this.T(
|
||||||
|
"This feature is managed by your organization and has therefore been disabled.",
|
||||||
|
typeof(ConfigurationBase).Namespace,
|
||||||
|
nameof(ConfigurationBase));
|
||||||
}
|
}
|
||||||
@ -26,6 +26,9 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Tools.Components Component { get; set; } = Tools.Components.NONE;
|
public Tools.Components Component { get; set; } = Tools.Components.NONE;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public ConfidenceLevel ExplicitMinimumConfidence { get; set; } = ConfidenceLevel.UNKNOWN;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<bool> Disabled { get; set; } = () => false;
|
public Func<bool> Disabled { get; set; } = () => false;
|
||||||
|
|
||||||
@ -38,7 +41,14 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
|
|||||||
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)
|
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)
|
||||||
yield return new(T("Use app default"), string.Empty);
|
yield return new(T("Use app default"), string.Empty);
|
||||||
|
|
||||||
|
// Get the minimum confidence level for this component, and/or the enforced global minimum confidence level:
|
||||||
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.Component);
|
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.Component);
|
||||||
|
|
||||||
|
// Apply the explicit minimum confidence level if set and higher than the current minimum level:
|
||||||
|
if (this.ExplicitMinimumConfidence is not ConfidenceLevel.UNKNOWN && this.ExplicitMinimumConfidence > minimumLevel)
|
||||||
|
minimumLevel = this.ExplicitMinimumConfidence;
|
||||||
|
|
||||||
|
// Filter the providers based on the minimum confidence level:
|
||||||
foreach (var providerId in this.Data)
|
foreach (var providerId in this.Data)
|
||||||
{
|
{
|
||||||
var provider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == providerId.Value);
|
var provider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == providerId.Value);
|
||||||
|
|||||||
@ -28,6 +28,12 @@ public partial class ConfigurationSelect<TConfig> : ConfigurationBaseCore
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<TConfig> SelectionUpdate { get; set; } = _ => { };
|
public Action<TConfig> SelectionUpdate { get; set; } = _ => { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An asynchronous action that is called when the selection changes.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Func<TConfig, Task> SelectionUpdateAsync { get; set; } = _ => Task.CompletedTask;
|
||||||
|
|
||||||
#region Overrides of ConfigurationBase
|
#region Overrides of ConfigurationBase
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -44,6 +50,7 @@ public partial class ConfigurationSelect<TConfig> : ConfigurationBaseCore
|
|||||||
private async Task OptionChanged(TConfig updatedValue)
|
private async Task OptionChanged(TConfig updatedValue)
|
||||||
{
|
{
|
||||||
this.SelectionUpdate(updatedValue);
|
this.SelectionUpdate(updatedValue);
|
||||||
|
await this.SelectionUpdateAsync(updatedValue);
|
||||||
await this.SettingsManager.StoreSettings();
|
await this.SettingsManager.StoreSettings();
|
||||||
await this.InformAboutChange();
|
await this.InformAboutChange();
|
||||||
}
|
}
|
||||||
|
|||||||
15
app/MindWork AI Studio/Components/EncryptionSecretInfo.razor
Normal file
15
app/MindWork AI Studio/Components/EncryptionSecretInfo.razor
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<MudText Typo="Typo.body1" Class="@this.Class">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
||||||
|
@if (this.IsConfigured)
|
||||||
|
{
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Small"/>
|
||||||
|
<span>@this.ConfiguredText</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Cancel" Color="Color.Error" Size="Size.Small"/>
|
||||||
|
<span>@this.NotConfiguredText</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</MudText>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public partial class EncryptionSecretInfo : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public bool IsConfigured { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ConfiguredText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string NotConfiguredText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Class { get; set; } = "mt-2 mb-2";
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
<MudText Typo="Typo.body1" Class="mb-3" Style="text-align: justify; hyphens: auto;">
|
<MudText Typo="Typo.body1" Class="mb-3" Style="text-align: justify; hyphens: auto;">
|
||||||
@T("Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time.")
|
@T("Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community.")
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<MudText Typo="Typo.h4">
|
<MudText Typo="Typo.h4">
|
||||||
@ -28,5 +28,13 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mb-3" Style="text-align: justify; hyphens: auto;">
|
<MudText Typo="Typo.body1" Class="mb-3" Style="text-align: justify; hyphens: auto;">
|
||||||
@T("Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices.")
|
@T("Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design.")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h4">
|
||||||
|
@T("Democratization of AI")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.body1" Class="mb-3" Style="text-align: justify; hyphens: auto;">
|
||||||
|
@T("We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge.")
|
||||||
</MudText>
|
</MudText>
|
||||||
@ -2,14 +2,14 @@
|
|||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
|
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Baseline" StretchItems="StretchItems.Start" Class="mb-3" Wrap="Wrap.NoWrap">
|
<MudStack Row="true" AlignItems="AlignItems.Baseline" StretchItems="StretchItems.Start" Class="mb-3" Wrap="Wrap.NoWrap">
|
||||||
<MudSelect T="Profile" Strict="@true" Value="@this.Profile" ValueChanged="@this.SelectionChanged" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person4" Margin="Margin.Dense" Label="@T("Select one of your profiles")" Variant="Variant.Outlined" Class="mb-3" Validation="@this.Validation">
|
<MudSelect T="Profile" Strict="@true" Disabled="@this.Disabled" Value="@this.Profile" ValueChanged="@this.SelectionChanged" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person4" Margin="Margin.Dense" Label="@T("Select one of your profiles")" Variant="Variant.Outlined" Class="mb-3" Validation="@this.Validation">
|
||||||
@foreach (var profile in this.SettingsManager.ConfigurationData.Profiles.GetAllProfiles())
|
@foreach (var profile in this.SettingsManager.ConfigurationData.Profiles.GetAllProfiles())
|
||||||
{
|
{
|
||||||
<MudSelectItem Value="profile">
|
<MudSelectItem Value="profile">
|
||||||
@profile.Name
|
@profile.GetSafeName()
|
||||||
</MudSelectItem>
|
</MudSelectItem>
|
||||||
}
|
}
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="() => this.OpenSettingsDialog()"/>
|
<MudIconButton Disabled="@this.Disabled" Icon="@Icons.Material.Filled.Settings" OnClick="() => this.OpenSettingsDialog()"/>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
@ -18,6 +18,9 @@ public partial class ProfileFormSelection : MSGComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<Profile, string?> Validation { get; set; } = _ => null;
|
public Func<Profile, string?> Validation { get; set; } = _ => null;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
public IDialogService DialogService { get; init; } = null!;
|
public IDialogService DialogService { get; init; } = null!;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using AIStudio.Assistants;
|
|
||||||
using AIStudio.Provider;
|
using AIStudio.Provider;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@ -10,7 +9,7 @@ namespace AIStudio.Components;
|
|||||||
public partial class ProviderSelection : MSGComponentBase
|
public partial class ProviderSelection : MSGComponentBase
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
public AssistantBase<NoComponent>? AssistantBase { get; set; }
|
public Tools.Components? Component { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public AIStudio.Settings.Provider ProviderSettings { get; set; } = AIStudio.Settings.Provider.NONE;
|
public AIStudio.Settings.Provider ProviderSettings { get; set; } = AIStudio.Settings.Provider.NONE;
|
||||||
@ -21,6 +20,12 @@ public partial class ProviderSelection : MSGComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<AIStudio.Settings.Provider, string?> ValidateProvider { get; set; } = _ => null;
|
public Func<AIStudio.Settings.Provider, string?> ValidateProvider { get; set; } = _ => null;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public ConfidenceLevel ExplicitMinimumConfidence { get; set; } = ConfidenceLevel.UNKNOWN;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private ILogger<ProviderSelection> Logger { get; init; } = null!;
|
||||||
|
|
||||||
private async Task SelectionChanged(AIStudio.Settings.Provider provider)
|
private async Task SelectionChanged(AIStudio.Settings.Provider provider)
|
||||||
{
|
{
|
||||||
this.ProviderSettings = provider;
|
this.ProviderSettings = provider;
|
||||||
@ -30,10 +35,31 @@ public partial class ProviderSelection : MSGComponentBase
|
|||||||
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
|
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
|
||||||
private IEnumerable<AIStudio.Settings.Provider> GetAvailableProviders()
|
private IEnumerable<AIStudio.Settings.Provider> GetAvailableProviders()
|
||||||
{
|
{
|
||||||
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.AssistantBase?.Component ?? Tools.Components.NONE);
|
switch (this.Component)
|
||||||
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
{
|
||||||
if (provider.UsedLLMProvider != LLMProviders.NONE)
|
case null:
|
||||||
if (provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
|
this.Logger.LogError("Component is null! Cannot filter providers based on component settings. Missed CascadingParameter?");
|
||||||
yield return provider;
|
yield break;
|
||||||
|
|
||||||
|
case Tools.Components.NONE:
|
||||||
|
this.Logger.LogError("Component is NONE! Cannot filter providers based on component settings. Used wrong component?");
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
case { } component:
|
||||||
|
|
||||||
|
// Get the minimum confidence level for this component, and/or the global minimum if enforced:
|
||||||
|
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(component);
|
||||||
|
|
||||||
|
// Override with the explicit minimum level if set and higher:
|
||||||
|
if (this.ExplicitMinimumConfidence is not ConfidenceLevel.UNKNOWN && this.ExplicitMinimumConfidence > minimumLevel)
|
||||||
|
minimumLevel = this.ExplicitMinimumConfidence;
|
||||||
|
|
||||||
|
// Filter providers based on the minimum confidence level:
|
||||||
|
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||||
|
if (provider.UsedLLMProvider != LLMProviders.NONE)
|
||||||
|
if (provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
|
||||||
|
yield return provider;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
<MudButton StartIcon="@Icons.Material.Filled.Description" OnClick="async () => await this.SelectFile()" Variant="Variant.Filled" Class="mb-3">
|
<MudButton StartIcon="@Icons.Material.Filled.Description" OnClick="@(async () => await this.SelectFile())" Variant="Variant.Filled" Class="mb-3" Disabled="@this.Disabled">
|
||||||
@if (string.IsNullOrWhiteSpace(this.Text))
|
@if (string.IsNullOrWhiteSpace(this.Text))
|
||||||
{
|
{
|
||||||
@T("Use file content as input")
|
@T("Use file content as input")
|
||||||
|
|||||||
@ -16,6 +16,9 @@ public partial class ReadFileContent : MSGComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<string> FileContentChanged { get; set; }
|
public EventCallback<string> FileContentChanged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private RustService RustService { get; init; } = null!;
|
private RustService RustService { get; init; } = null!;
|
||||||
|
|
||||||
@ -30,6 +33,9 @@ public partial class ReadFileContent : MSGComponentBase
|
|||||||
|
|
||||||
private async Task SelectFile()
|
private async Task SelectFile()
|
||||||
{
|
{
|
||||||
|
if (this.Disabled)
|
||||||
|
return;
|
||||||
|
|
||||||
// Ensure that Pandoc is installed and ready:
|
// Ensure that Pandoc is installed and ready:
|
||||||
var pandocState = await this.PandocAvailabilityService.EnsureAvailabilityAsync(
|
var pandocState = await this.PandocAvailabilityService.EnsureAvailabilityAsync(
|
||||||
showSuccessMessage: false,
|
showSuccessMessage: false,
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
<ConfigurationSelect OptionDescription="@T("Check for updates")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateInterval)" Data="@ConfigurationSelectDataFactory.GetUpdateIntervalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateInterval = selectedValue)" OptionHelp="@T("How often should we check for app updates?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UpdateInterval, out var meta) && meta.IsLocked"/>
|
<ConfigurationSelect OptionDescription="@T("Check for updates")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateInterval)" Data="@ConfigurationSelectDataFactory.GetUpdateIntervalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateInterval = selectedValue)" OptionHelp="@T("How often should we check for app updates?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UpdateInterval, out var meta) && meta.IsLocked"/>
|
||||||
<ConfigurationSelect OptionDescription="@T("Update installation method")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateInstallation)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviourData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateInstallation = selectedValue)" OptionHelp="@T("Should updates be installed automatically or manually?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UpdateInstallation, out var meta) && meta.IsLocked"/>
|
<ConfigurationSelect OptionDescription="@T("Update installation method")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateInstallation)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviourData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateInstallation = selectedValue)" OptionHelp="@T("Should updates be installed automatically or manually?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UpdateInstallation, out var meta) && meta.IsLocked"/>
|
||||||
<ConfigurationSelect OptionDescription="@T("Navigation bar behavior")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.NavigationBehavior = selectedValue)" OptionHelp="@T("Select the desired behavior for the navigation bar.")"/>
|
<ConfigurationSelect OptionDescription="@T("Navigation bar behavior")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.NavigationBehavior = selectedValue)" OptionHelp="@T("Select the desired behavior for the navigation bar.")"/>
|
||||||
|
<ConfigurationOption OptionDescription="@T("Show administration settings?")" LabelOn="@T("Administration settings are visible")" LabelOff="@T("Administration settings are not visible")" State="@(() => this.SettingsManager.ConfigurationData.App.ShowAdminSettings)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.ShowAdminSettings = updatedState)" OptionHelp="@T("When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.ShowAdminSettings, out var meta) && meta.IsLocked"/>
|
||||||
<ConfigurationSelect OptionDescription="@T("Preview feature visibility")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreviewVisibility)" Data="@ConfigurationSelectDataFactory.GetPreviewVisibility()" SelectionUpdate="@this.UpdatePreviewFeatures" OptionHelp="@T("Do you want to show preview features in the app?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.PreviewVisibility, out var meta) && meta.IsLocked"/>
|
<ConfigurationSelect OptionDescription="@T("Preview feature visibility")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreviewVisibility)" Data="@ConfigurationSelectDataFactory.GetPreviewVisibility()" SelectionUpdate="@this.UpdatePreviewFeatures" OptionHelp="@T("Do you want to show preview features in the app?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.PreviewVisibility, out var meta) && meta.IsLocked"/>
|
||||||
|
|
||||||
@if (this.SettingsManager.ConfigurationData.App.PreviewVisibility > PreviewVisibility.NONE)
|
@if (this.SettingsManager.ConfigurationData.App.PreviewVisibility > PreviewVisibility.NONE)
|
||||||
@ -24,11 +25,11 @@
|
|||||||
var availablePreviewFeatures = ConfigurationSelectDataFactory.GetPreviewFeaturesData(this.SettingsManager).ToList();
|
var availablePreviewFeatures = ConfigurationSelectDataFactory.GetPreviewFeaturesData(this.SettingsManager).ToList();
|
||||||
if (availablePreviewFeatures.Count > 0)
|
if (availablePreviewFeatures.Count > 0)
|
||||||
{
|
{
|
||||||
<ConfigurationMultiSelect OptionDescription="@T("Select preview features")" SelectedValues="@(() => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures.Where(x => !x.IsReleased()).ToHashSet())" Data="@availablePreviewFeatures" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = selectedValue)" OptionHelp="@T("Which preview features would you like to enable?")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) && meta.IsLocked"/>
|
<ConfigurationMultiSelect OptionDescription="@T("Select preview features")" SelectedValues="@this.GetSelectedPreviewFeatures" Data="@availablePreviewFeatures" SelectionUpdate="@this.UpdateEnabledPreviewFeatures" OptionHelp="@T("Which preview features would you like to enable?")" IsItemLocked="@this.IsPluginContributedPreviewFeature" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) && meta.IsLocked"/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<ConfigurationProviderSelection Component="Components.APP_SETTINGS" Data="@this.AvailableLLMProvidersFunc()" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProvider = selectedValue)" HelpText="@(() => T("Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."))"/>
|
<ConfigurationProviderSelection Component="Components.APP_SETTINGS" Data="@this.AvailableLLMProvidersFunc()" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProvider = selectedValue)" HelpText="@(() => T("Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."))" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.PreselectedProvider, out var meta) && meta.IsLocked"/>
|
||||||
<ConfigurationSelect OptionDescription="@T("Preselect one of your profiles?")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProfile = selectedValue)" OptionHelp="@T("Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.PreselectedProfile, out var meta) && meta.IsLocked"/>
|
<ConfigurationSelect OptionDescription="@T("Preselect one of your profiles?")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProfile = selectedValue)" OptionHelp="@T("Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.PreselectedProfile, out var meta) && meta.IsLocked"/>
|
||||||
|
|
||||||
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
|
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
|
||||||
@ -36,4 +37,25 @@
|
|||||||
<ConfigurationSelect OptionDescription="@T("Select a transcription provider")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider)" Data="@this.GetFilteredTranscriptionProviders()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider = selectedValue)" OptionHelp="@T("Select a transcription provider for transcribing your voice. Without a selected provider, dictation and transcription features will be disabled.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UseTranscriptionProvider, out var meta) && meta.IsLocked"/>
|
<ConfigurationSelect OptionDescription="@T("Select a transcription provider")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider)" Data="@this.GetFilteredTranscriptionProviders()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider = selectedValue)" OptionHelp="@T("Select a transcription provider for transcribing your voice. Without a selected provider, dictation and transcription features will be disabled.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UseTranscriptionProvider, out var meta) && meta.IsLocked"/>
|
||||||
<ConfigurationShortcut ShortcutId="Shortcut.VOICE_RECORDING_TOGGLE" OptionDescription="@T("Voice recording shortcut")" Shortcut="@(() => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording)" ShortcutUpdate="@(shortcut => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording = shortcut)" OptionHelp="@T("The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.ShortcutVoiceRecording, out var meta) && meta.IsLocked"/>
|
<ConfigurationShortcut ShortcutId="Shortcut.VOICE_RECORDING_TOGGLE" OptionDescription="@T("Voice recording shortcut")" Shortcut="@(() => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording)" ShortcutUpdate="@(shortcut => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording = shortcut)" OptionHelp="@T("The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.ShortcutVoiceRecording, out var meta) && meta.IsLocked"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h5" Class="mt-6 mb-3">
|
||||||
|
@T("Enterprise Administration")
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.body2" Class="mb-3">
|
||||||
|
@T("Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings.")
|
||||||
|
<MudLink Href="https://github.com/MindWorkAI/AI-Studio/blob/main/documentation/Enterprise%20IT.md" Target="_blank">
|
||||||
|
@T("Read the Enterprise IT documentation for details.")
|
||||||
|
</MudLink>
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudButton StartIcon="@Icons.Material.Filled.Key"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
OnClick="@this.GenerateEncryptionSecret">
|
||||||
|
@T("Generate an encryption secret and copy it to the clipboard")
|
||||||
|
</MudButton>
|
||||||
|
}
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
@ -6,6 +6,12 @@ namespace AIStudio.Components.Settings;
|
|||||||
|
|
||||||
public partial class SettingsPanelApp : SettingsPanelBase
|
public partial class SettingsPanelApp : SettingsPanelBase
|
||||||
{
|
{
|
||||||
|
private async Task GenerateEncryptionSecret()
|
||||||
|
{
|
||||||
|
var secret = EnterpriseEncryption.GenerateSecret();
|
||||||
|
await this.RustService.CopyText2Clipboard(this.Snackbar, secret);
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable<ConfigurationSelectData<string>> GetFilteredTranscriptionProviders()
|
private IEnumerable<ConfigurationSelectData<string>> GetFilteredTranscriptionProviders()
|
||||||
{
|
{
|
||||||
yield return new(T("Disable dictation and transcription"), string.Empty);
|
yield return new(T("Disable dictation and transcription"), string.Empty);
|
||||||
@ -21,7 +27,41 @@ public partial class SettingsPanelApp : SettingsPanelBase
|
|||||||
private void UpdatePreviewFeatures(PreviewVisibility previewVisibility)
|
private void UpdatePreviewFeatures(PreviewVisibility previewVisibility)
|
||||||
{
|
{
|
||||||
this.SettingsManager.ConfigurationData.App.PreviewVisibility = previewVisibility;
|
this.SettingsManager.ConfigurationData.App.PreviewVisibility = previewVisibility;
|
||||||
this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = previewVisibility.FilterPreviewFeatures(this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures);
|
var filtered = previewVisibility.FilterPreviewFeatures(this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures);
|
||||||
|
filtered.UnionWith(this.GetPluginContributedPreviewFeatures());
|
||||||
|
this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<PreviewFeatures> GetPluginContributedPreviewFeatures()
|
||||||
|
{
|
||||||
|
if (ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) && meta.HasPluginContribution)
|
||||||
|
return meta.PluginContribution.Where(x => !x.IsReleased()).ToHashSet();
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPluginContributedPreviewFeature(PreviewFeatures feature)
|
||||||
|
{
|
||||||
|
if (feature.IsReleased())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) || !meta.HasPluginContribution)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return meta.PluginContribution.Contains(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<PreviewFeatures> GetSelectedPreviewFeatures()
|
||||||
|
{
|
||||||
|
var enabled = this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures.Where(x => !x.IsReleased()).ToHashSet();
|
||||||
|
enabled.UnionWith(this.GetPluginContributedPreviewFeatures());
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateEnabledPreviewFeatures(HashSet<PreviewFeatures> selectedFeatures)
|
||||||
|
{
|
||||||
|
selectedFeatures.UnionWith(this.GetPluginContributedPreviewFeatures());
|
||||||
|
this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = selectedFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateLangBehaviour(LangBehavior behavior)
|
private async Task UpdateLangBehaviour(LangBehavior behavior)
|
||||||
|
|||||||
@ -15,4 +15,7 @@ public abstract class SettingsPanelBase : MSGComponentBase
|
|||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected RustService RustService { get; init; } = null!;
|
protected RustService RustService { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected ISnackbar Snackbar { get; init; } = null!;
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@using AIStudio.Provider
|
@using AIStudio.Provider
|
||||||
@using AIStudio.Settings.DataModel
|
@using AIStudio.Settings.DataModel
|
||||||
@inherits SettingsPanelBase
|
@inherits SettingsPanelProviderBase
|
||||||
|
|
||||||
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col/>
|
<col/>
|
||||||
<col style="width: 16em;"/>
|
<col style="width: 22em;"/>
|
||||||
</ColGroup>
|
</ColGroup>
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
<MudTh>#</MudTh>
|
<MudTh>#</MudTh>
|
||||||
@ -53,9 +53,18 @@
|
|||||||
<MudTooltip Text="@T("Edit")">
|
<MudTooltip Text="@T("Edit")">
|
||||||
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditEmbeddingProvider(context))"/>
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditEmbeddingProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Export configuration")">
|
||||||
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Dataset" OnClick="@(() => this.ExportEmbeddingProvider(context))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
<MudTooltip Text="@T("Delete")">
|
<MudTooltip Text="@T("Delete")">
|
||||||
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteEmbeddingProvider(context))"/>
|
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteEmbeddingProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
<MudTooltip Text="@T("Test")">
|
||||||
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Api" OnClick="@(() => this.TestEmbeddingProvider(context))"/>
|
||||||
|
</MudTooltip>
|
||||||
}
|
}
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
|
using System.Globalization;
|
||||||
using AIStudio.Dialogs;
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Provider;
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@ -7,7 +9,7 @@ using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
|||||||
|
|
||||||
namespace AIStudio.Components.Settings;
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
public partial class SettingsPanelEmbeddings : SettingsPanelBase
|
public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public List<ConfigurationSelectData<string>> AvailableEmbeddingProviders { get; set; } = new();
|
public List<ConfigurationSelectData<string>> AvailableEmbeddingProviders { get; set; } = new();
|
||||||
@ -115,6 +117,17 @@ public partial class SettingsPanelEmbeddings : SettingsPanelBase
|
|||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ExportEmbeddingProvider(EmbeddingProvider provider)
|
||||||
|
{
|
||||||
|
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (provider == EmbeddingProvider.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.ExportProvider(provider, SecretStoreType.EMBEDDING_PROVIDER, provider.ExportAsConfigurationSection);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task UpdateEmbeddingProviders()
|
private async Task UpdateEmbeddingProviders()
|
||||||
{
|
{
|
||||||
this.AvailableEmbeddingProviders.Clear();
|
this.AvailableEmbeddingProviders.Clear();
|
||||||
@ -123,4 +136,48 @@ public partial class SettingsPanelEmbeddings : SettingsPanelBase
|
|||||||
|
|
||||||
await this.AvailableEmbeddingProvidersChanged.InvokeAsync(this.AvailableEmbeddingProviders);
|
await this.AvailableEmbeddingProvidersChanged.InvokeAsync(this.AvailableEmbeddingProviders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task TestEmbeddingProvider(EmbeddingProvider provider)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<SingleInputDialog>
|
||||||
|
{
|
||||||
|
{ x => x.ConfirmText, T("Embed text") },
|
||||||
|
{ x => x.InputHeaderText, T("Add text that should be embedded:") },
|
||||||
|
{ x => x.UserInput, T("Example text to embed") },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<SingleInputDialog>(T("Test Embedding Provider"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var inputText = dialogResult.Data as string;
|
||||||
|
if (string.IsNullOrWhiteSpace(inputText))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var embeddingProvider = provider.CreateProvider();
|
||||||
|
var embeddings = await embeddingProvider.EmbedTextAsync(provider.Model, this.SettingsManager, default, new List<string> { inputText });
|
||||||
|
|
||||||
|
if (embeddings.Count == 0)
|
||||||
|
{
|
||||||
|
await this.DialogService.ShowMessageBox(T("Embedding Result"), T("No embedding was returned."), T("Close"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var vector = embeddings.FirstOrDefault();
|
||||||
|
if (vector is null || vector.Count == 0)
|
||||||
|
{
|
||||||
|
await this.DialogService.ShowMessageBox(T("Embedding Result"), T("No embedding was returned."), T("Close"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultText = string.Join(Environment.NewLine, vector.Select(value => value.ToString("G9", CultureInfo.InvariantCulture)));
|
||||||
|
var resultParameters = new DialogParameters<EmbeddingResultDialog>
|
||||||
|
{
|
||||||
|
{ x => x.ResultText, resultText },
|
||||||
|
{ x => x.ResultLabel, T("Embedding Vector (one dimension per line)") },
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.DialogService.ShowAsync<EmbeddingResultDialog>(T("Embedding Result"), resultParameters, DialogOptions.FULLSCREEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Tools.PluginSystem;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public abstract class SettingsPanelProviderBase : SettingsPanelBase
|
||||||
|
{
|
||||||
|
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(SettingsPanelProviderBase).Namespace, nameof(SettingsPanelProviderBase));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exports the provider configuration as Lua code, optionally including the encrypted API key if the provider has one
|
||||||
|
/// configured and the user agrees to include it. The exportFunc should generate the Lua code based on the provided
|
||||||
|
/// encrypted API key (which may be null if the user chose not to include it or if encryption is not available).
|
||||||
|
/// The generated Lua code is then copied to the clipboard for easy sharing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID of the provider to check for an API key.</param>
|
||||||
|
/// <param name="storeType">The type of secret store to check for the API key (e.g., LLM provider, transcription provider, etc.).</param>
|
||||||
|
/// <param name="exportFunc">The function that generates the Lua code for the provider configuration, given the optional encrypted API key.</param>
|
||||||
|
protected async Task ExportProvider(ISecretId secretId, SecretStoreType storeType, Func<string?, string> exportFunc)
|
||||||
|
{
|
||||||
|
string? encryptedApiKey = null;
|
||||||
|
|
||||||
|
// Check if the provider has an API key stored:
|
||||||
|
var apiKeyResponse = await this.RustService.GetAPIKey(secretId, storeType, isTrying: true);
|
||||||
|
if (apiKeyResponse.Success)
|
||||||
|
{
|
||||||
|
// Ask the user if they want to export the API key:
|
||||||
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
|
{
|
||||||
|
{ x => x.Message, TB("This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key.") },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(TB("Export API Key?"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is { Canceled: false })
|
||||||
|
{
|
||||||
|
// User wants to export the API key - encrypt it:
|
||||||
|
var encryption = PluginFactory.EnterpriseEncryption;
|
||||||
|
if (encryption?.IsAvailable == true)
|
||||||
|
{
|
||||||
|
var decryptedApiKey = await apiKeyResponse.Secret.Decrypt(Program.ENCRYPTION);
|
||||||
|
if (encryption.TryEncrypt(decryptedApiKey, out var encrypted))
|
||||||
|
encryptedApiKey = encrypted;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No encryption secret available - inform the user:
|
||||||
|
this.Snackbar.Add(TB("Cannot export the encrypted API key: No enterprise encryption secret is configured."), Severity.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var luaCode = exportFunc(encryptedApiKey);
|
||||||
|
if (string.IsNullOrWhiteSpace(luaCode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@using AIStudio.Provider
|
@using AIStudio.Provider
|
||||||
@using AIStudio.Settings
|
@using AIStudio.Settings
|
||||||
@inherits SettingsPanelBase
|
@inherits SettingsPanelProviderBase
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="@T("Configure LLM Providers")">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="@T("Configure LLM Providers")">
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">
|
<MudText Typo="Typo.h4" Class="mb-3">
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col/>
|
<col/>
|
||||||
<col style="width: 16em;"/>
|
<col style="width: 22em;"/>
|
||||||
</ColGroup>
|
</ColGroup>
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
<MudTh>#</MudTh>
|
<MudTh>#</MudTh>
|
||||||
@ -45,6 +45,12 @@
|
|||||||
<MudTooltip Text="@T("Edit")">
|
<MudTooltip Text="@T("Edit")">
|
||||||
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditLLMProvider(context))"/>
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditLLMProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Export configuration")">
|
||||||
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Dataset" OnClick="@(() => this.ExportLLMProvider(context))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
<MudTooltip Text="@T("Delete")">
|
<MudTooltip Text="@T("Delete")">
|
||||||
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteLLMProvider(context))"/>
|
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteLLMProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
@ -98,7 +104,7 @@
|
|||||||
@context.ToName()
|
@context.ToName()
|
||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd>
|
<MudTd>
|
||||||
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description"/>
|
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd Style="vertical-align: top;">
|
<MudTd Style="vertical-align: top;">
|
||||||
<MudMenu StartIcon="@Icons.Material.Filled.Security" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@this.GetCurrentConfidenceLevelName(context)" Variant="Variant.Filled" Style="@this.SetCurrentConfidenceLevelColorStyle(context)">
|
<MudMenu StartIcon="@Icons.Material.Filled.Security" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@this.GetCurrentConfidenceLevelName(context)" Variant="Variant.Filled" Style="@this.SetCurrentConfidenceLevelColorStyle(context)">
|
||||||
|
|||||||
@ -10,7 +10,7 @@ using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
|||||||
|
|
||||||
namespace AIStudio.Components.Settings;
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
public partial class SettingsPanelProviders : SettingsPanelBase
|
public partial class SettingsPanelProviders : SettingsPanelProviderBase
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public List<ConfigurationSelectData<string>> AvailableLLMProviders { get; set; } = new();
|
public List<ConfigurationSelectData<string>> AvailableLLMProviders { get; set; } = new();
|
||||||
@ -134,6 +134,17 @@ public partial class SettingsPanelProviders : SettingsPanelBase
|
|||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ExportLLMProvider(AIStudio.Settings.Provider provider)
|
||||||
|
{
|
||||||
|
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (provider == AIStudio.Settings.Provider.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.ExportProvider(provider, SecretStoreType.LLM_PROVIDER, provider.ExportAsConfigurationSection);
|
||||||
|
}
|
||||||
|
|
||||||
private string GetLLMProviderModelName(AIStudio.Settings.Provider provider)
|
private string GetLLMProviderModelName(AIStudio.Settings.Provider provider)
|
||||||
{
|
{
|
||||||
// For system models, return localized text:
|
// For system models, return localized text:
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
@using AIStudio.Provider
|
@using AIStudio.Provider
|
||||||
@using AIStudio.Settings.DataModel
|
@using AIStudio.Settings.DataModel
|
||||||
@inherits SettingsPanelBase
|
@inherits SettingsPanelProviderBase
|
||||||
|
|
||||||
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
|
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
|
||||||
{
|
{
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.VoiceChat" HeaderText="@T("Configure Transcription Providers")">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.VoiceChat" HeaderText="@T("Configure Transcription Providers")">
|
||||||
<PreviewPrototype ApplyInnerScrollingFix="true"/>
|
<PreviewBeta ApplyInnerScrollingFix="true"/>
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">
|
<MudText Typo="Typo.h4" Class="mb-3">
|
||||||
@T("Configured Transcription Providers")
|
@T("Configured Transcription Providers")
|
||||||
</MudText>
|
</MudText>
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col style="width: 12em;"/>
|
<col style="width: 12em;"/>
|
||||||
<col/>
|
<col/>
|
||||||
<col style="width: 16em;"/>
|
<col style="width: 22em;"/>
|
||||||
</ColGroup>
|
</ColGroup>
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
<MudTh>#</MudTh>
|
<MudTh>#</MudTh>
|
||||||
@ -50,6 +50,12 @@
|
|||||||
<MudTooltip Text="@T("Edit")">
|
<MudTooltip Text="@T("Edit")">
|
||||||
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditTranscriptionProvider(context))"/>
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Edit" OnClick="@(() => this.EditTranscriptionProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Export configuration")">
|
||||||
|
<MudIconButton Color="Color.Info" Icon="@Icons.Material.Filled.Dataset" OnClick="@(() => this.ExportTranscriptionProvider(context))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
<MudTooltip Text="@T("Delete")">
|
<MudTooltip Text="@T("Delete")">
|
||||||
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteTranscriptionProvider(context))"/>
|
<MudIconButton Color="Color.Error" Icon="@Icons.Material.Filled.Delete" OnClick="@(() => this.DeleteTranscriptionProvider(context))"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
|||||||
|
|
||||||
namespace AIStudio.Components.Settings;
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
public partial class SettingsPanelTranscription : SettingsPanelBase
|
public partial class SettingsPanelTranscription : SettingsPanelProviderBase
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public List<ConfigurationSelectData<string>> AvailableTranscriptionProviders { get; set; } = new();
|
public List<ConfigurationSelectData<string>> AvailableTranscriptionProviders { get; set; } = new();
|
||||||
@ -115,6 +115,17 @@ public partial class SettingsPanelTranscription : SettingsPanelBase
|
|||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ExportTranscriptionProvider(TranscriptionProvider provider)
|
||||||
|
{
|
||||||
|
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (provider == TranscriptionProvider.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.ExportProvider(provider, SecretStoreType.TRANSCRIPTION_PROVIDER, provider.ExportAsConfigurationSection);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task UpdateTranscriptionProviders()
|
private async Task UpdateTranscriptionProviders()
|
||||||
{
|
{
|
||||||
this.AvailableTranscriptionProviders.Clear();
|
this.AvailableTranscriptionProviders.Clear();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ public enum TreeItemType
|
|||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
|
|
||||||
|
LOADING,
|
||||||
CHAT,
|
CHAT,
|
||||||
WORKSPACE,
|
WORKSPACE,
|
||||||
}
|
}
|
||||||
@ -19,6 +19,7 @@ public partial class Vision : MSGComponentBase
|
|||||||
this.itemsVision =
|
this.itemsVision =
|
||||||
[
|
[
|
||||||
new(T("Meet your needs"), T("Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.")),
|
new(T("Meet your needs"), T("Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.")),
|
||||||
|
new(T("Democratization of AI"), T("We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge.")),
|
||||||
new(T("Integrating your data"), T("You'll be able to integrate your data into AI Studio, like your PDF or Office files, or your Markdown notes.")),
|
new(T("Integrating your data"), T("You'll be able to integrate your data into AI Studio, like your PDF or Office files, or your Markdown notes.")),
|
||||||
new(T("Integration of enterprise data"), T("It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.")),
|
new(T("Integration of enterprise data"), T("It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.")),
|
||||||
new(T("Useful assistants"), T("We'll develop more assistants for everyday tasks.")),
|
new(T("Useful assistants"), T("We'll develop more assistants for everyday tasks.")),
|
||||||
|
|||||||
@ -1,93 +1,114 @@
|
|||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
<MudTreeView T="ITreeItem" Items="@this.treeItems" SelectionMode="SelectionMode.SingleSelection" Hover="@true" ExpandOnClick="@true" Class="ma-3">
|
@if (this.isInitialLoading)
|
||||||
<ItemTemplate Context="item">
|
{
|
||||||
@switch (item.Value)
|
<MudStack Class="ma-3" Spacing="1">
|
||||||
|
<MudSkeleton Width="40%" Height="30px"/>
|
||||||
|
@for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
case TreeDivider:
|
<MudSkeleton Width="95%" Height="26px"/>
|
||||||
<li style="min-height: 1em;">
|
|
||||||
<MudDivider Style="margin-top: 1em; width: 90%; border-width: 3pt;"/>
|
|
||||||
</li>
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TreeItemData treeItem:
|
|
||||||
@if (treeItem.Type is TreeItemType.CHAT)
|
|
||||||
{
|
|
||||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="@(() => this.LoadChat(treeItem.Path, true))">
|
|
||||||
<BodyContent>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
|
||||||
<MudText Style="justify-self: start;">
|
|
||||||
@if (string.IsNullOrWhiteSpace(treeItem.Text))
|
|
||||||
{
|
|
||||||
@T("Empty chat")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@treeItem.ShortenedText
|
|
||||||
}
|
|
||||||
</MudText>
|
|
||||||
<div style="justify-self: end;">
|
|
||||||
|
|
||||||
<MudTooltip Text="@T("Move to workspace")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.MoveChat(treeItem.Path))"/>
|
|
||||||
</MudTooltip>
|
|
||||||
|
|
||||||
<MudTooltip Text="@T("Rename")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.RenameChat(treeItem.Path))"/>
|
|
||||||
</MudTooltip>
|
|
||||||
|
|
||||||
<MudTooltip Text="@T("Delete")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.DeleteChat(treeItem.Path))"/>
|
|
||||||
</MudTooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</BodyContent>
|
|
||||||
</MudTreeViewItem>
|
|
||||||
}
|
|
||||||
else if (treeItem.Type is TreeItemType.WORKSPACE)
|
|
||||||
{
|
|
||||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children">
|
|
||||||
<BodyContent>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
|
||||||
<MudText Style="justify-self: start;">
|
|
||||||
@treeItem.Text
|
|
||||||
</MudText>
|
|
||||||
<div style="justify-self: end;">
|
|
||||||
<MudTooltip Text="@T("Rename")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.RenameWorkspace(treeItem.Path))"/>
|
|
||||||
</MudTooltip>
|
|
||||||
|
|
||||||
<MudTooltip Text="@T("Delete")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.DeleteWorkspace(treeItem.Path))"/>
|
|
||||||
</MudTooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</BodyContent>
|
|
||||||
</MudTreeViewItem>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children">
|
|
||||||
<BodyContent>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
|
||||||
<MudText Style="justify-self: start;">
|
|
||||||
@treeItem.Text
|
|
||||||
</MudText>
|
|
||||||
</div>
|
|
||||||
</BodyContent>
|
|
||||||
</MudTreeViewItem>
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TreeButton treeButton:
|
|
||||||
<li>
|
|
||||||
<div class="mud-treeview-item-content" style="background-color: unset;">
|
|
||||||
<div class="mud-treeview-item-arrow"></div>
|
|
||||||
<MudButton StartIcon="@treeButton.Icon" Variant="Variant.Filled" OnClick="@treeButton.Action">
|
|
||||||
@treeButton.Text
|
|
||||||
</MudButton>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
</ItemTemplate>
|
</MudStack>
|
||||||
</MudTreeView>
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudTreeView T="ITreeItem" Items="@this.treeItems" SelectionMode="SelectionMode.SingleSelection" Hover="@true" ExpandOnClick="@true" Class="ma-3">
|
||||||
|
<ItemTemplate Context="item">
|
||||||
|
@switch (item.Value)
|
||||||
|
{
|
||||||
|
case TreeDivider:
|
||||||
|
<li style="min-height: 1em;">
|
||||||
|
<MudDivider Style="margin-top: 1em; width: 90%; border-width: 3pt;"/>
|
||||||
|
</li>
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TreeItemData treeItem:
|
||||||
|
@if (treeItem.Type is TreeItemType.LOADING)
|
||||||
|
{
|
||||||
|
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@false" Items="@treeItem.Children">
|
||||||
|
<BodyContent>
|
||||||
|
<MudSkeleton Width="85%" Height="22px"/>
|
||||||
|
</BodyContent>
|
||||||
|
</MudTreeViewItem>
|
||||||
|
}
|
||||||
|
else if (treeItem.Type is TreeItemType.CHAT)
|
||||||
|
{
|
||||||
|
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="@(() => this.LoadChatAsync(treeItem.Path, true))">
|
||||||
|
<BodyContent>
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||||
|
<MudText Style="justify-self: start;">
|
||||||
|
@if (string.IsNullOrWhiteSpace(treeItem.Text))
|
||||||
|
{
|
||||||
|
@T("Empty chat")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@treeItem.ShortenedText
|
||||||
|
}
|
||||||
|
</MudText>
|
||||||
|
<div style="justify-self: end;">
|
||||||
|
|
||||||
|
<MudTooltip Text="@T("Move to workspace")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.MoveChatAsync(treeItem.Path))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
|
||||||
|
<MudTooltip Text="@T("Rename")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.RenameChatAsync(treeItem.Path))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
|
||||||
|
<MudTooltip Text="@T("Delete")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" Color="Color.Error" OnClick="@(() => this.DeleteChatAsync(treeItem.Path))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BodyContent>
|
||||||
|
</MudTreeViewItem>
|
||||||
|
}
|
||||||
|
else if (treeItem.Type is TreeItemType.WORKSPACE)
|
||||||
|
{
|
||||||
|
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="@(() => this.OnWorkspaceClicked(treeItem))">
|
||||||
|
<BodyContent>
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||||
|
<MudText Style="justify-self: start;">
|
||||||
|
@treeItem.Text
|
||||||
|
</MudText>
|
||||||
|
<div style="justify-self: end;">
|
||||||
|
<MudTooltip Text="@T("Rename")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" OnClick="@(() => this.RenameWorkspaceAsync(treeItem.Path))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
|
||||||
|
<MudTooltip Text="@T("Delete")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" Color="Color.Error" OnClick="@(() => this.DeleteWorkspaceAsync(treeItem.Path))"/>
|
||||||
|
</MudTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BodyContent>
|
||||||
|
</MudTreeViewItem>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children">
|
||||||
|
<BodyContent>
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||||
|
<MudText Style="justify-self: start;">
|
||||||
|
@treeItem.Text
|
||||||
|
</MudText>
|
||||||
|
</div>
|
||||||
|
</BodyContent>
|
||||||
|
</MudTreeViewItem>
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TreeButton treeButton:
|
||||||
|
<li>
|
||||||
|
<div class="mud-treeview-item-content" style="background-color: unset;">
|
||||||
|
<div class="mud-treeview-item-arrow"></div>
|
||||||
|
<MudButton StartIcon="@treeButton.Icon" Variant="Variant.Filled" OnClick="@treeButton.Action">
|
||||||
|
@treeButton.Text
|
||||||
|
</MudButton>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
</ItemTemplate>
|
||||||
|
</MudTreeView>
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
@ -29,31 +29,64 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
public bool ExpandRootNodes { get; set; } = true;
|
public bool ExpandRootNodes { get; set; } = true;
|
||||||
|
|
||||||
private const Placement WORKSPACE_ITEM_TOOLTIP_PLACEMENT = Placement.Bottom;
|
private const Placement WORKSPACE_ITEM_TOOLTIP_PLACEMENT = Placement.Bottom;
|
||||||
|
private readonly SemaphoreSlim treeLoadingSemaphore = new(1, 1);
|
||||||
|
private readonly List<TreeItemData<ITreeItem>> treeItems = [];
|
||||||
|
private readonly HashSet<Guid> loadingWorkspaceChatLists = [];
|
||||||
|
|
||||||
private readonly List<TreeItemData<ITreeItem>> treeItems = new();
|
private CancellationTokenSource? prefetchCancellationTokenSource;
|
||||||
|
private bool isInitialLoading = true;
|
||||||
|
private bool isDisposed;
|
||||||
|
|
||||||
#region Overrides of ComponentBase
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
|
_ = this.LoadTreeItemsAsync(startPrefetch: true);
|
||||||
//
|
|
||||||
// Notice: In order to get the server-based loading to work, we need to respect the following rules:
|
|
||||||
// - We must have initial tree items
|
|
||||||
// - Those initial tree items cannot have children
|
|
||||||
// - When assigning the tree items to the MudTreeViewItem component, we must set the Value property to the value of the item
|
|
||||||
//
|
|
||||||
// We won't await the loading of the tree items here,
|
|
||||||
// to avoid blocking the UI thread:
|
|
||||||
_ = this.LoadTreeItems();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private async Task LoadTreeItems()
|
private async Task LoadTreeItemsAsync(bool startPrefetch = true, bool forceReload = false)
|
||||||
|
{
|
||||||
|
await this.treeLoadingSemaphore.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (this.isDisposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (forceReload)
|
||||||
|
await WorkspaceBehaviour.ForceReloadWorkspaceTreeAsync();
|
||||||
|
|
||||||
|
var snapshot = await WorkspaceBehaviour.GetOrLoadWorkspaceTreeShellAsync();
|
||||||
|
this.BuildTreeItems(snapshot);
|
||||||
|
this.isInitialLoading = false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.treeLoadingSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.SafeStateHasChanged();
|
||||||
|
|
||||||
|
if (startPrefetch)
|
||||||
|
await this.StartPrefetchAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildTreeItems(WorkspaceTreeCacheSnapshot snapshot)
|
||||||
{
|
{
|
||||||
this.treeItems.Clear();
|
this.treeItems.Clear();
|
||||||
|
|
||||||
|
var workspaceChildren = new List<TreeItemData<ITreeItem>>();
|
||||||
|
foreach (var workspace in snapshot.Workspaces)
|
||||||
|
workspaceChildren.Add(this.CreateWorkspaceTreeItem(workspace));
|
||||||
|
|
||||||
|
workspaceChildren.Add(new TreeItemData<ITreeItem>
|
||||||
|
{
|
||||||
|
Expandable = false,
|
||||||
|
Value = new TreeButton(WorkspaceBranch.WORKSPACES, 1, T("Add workspace"), Icons.Material.Filled.LibraryAdd, this.AddWorkspaceAsync),
|
||||||
|
});
|
||||||
|
|
||||||
this.treeItems.Add(new TreeItemData<ITreeItem>
|
this.treeItems.Add(new TreeItemData<ITreeItem>
|
||||||
{
|
{
|
||||||
Expanded = this.ExpandRootNodes,
|
Expanded = this.ExpandRootNodes,
|
||||||
@ -66,7 +99,7 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
Icon = Icons.Material.Filled.Folder,
|
Icon = Icons.Material.Filled.Folder,
|
||||||
Expandable = true,
|
Expandable = true,
|
||||||
Path = "root",
|
Path = "root",
|
||||||
Children = await this.LoadWorkspaces(),
|
Children = workspaceChildren,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -76,7 +109,10 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
Value = new TreeDivider(),
|
Value = new TreeDivider(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.InvokeAsync(this.StateHasChanged);
|
var temporaryChatsChildren = new List<TreeItemData<ITreeItem>>();
|
||||||
|
foreach (var temporaryChat in snapshot.TemporaryChats.OrderByDescending(x => x.LastEditTime))
|
||||||
|
temporaryChatsChildren.Add(CreateChatTreeItem(temporaryChat, WorkspaceBranch.TEMPORARY_CHATS, depth: 1, icon: Icons.Material.Filled.Timer));
|
||||||
|
|
||||||
this.treeItems.Add(new TreeItemData<ITreeItem>
|
this.treeItems.Add(new TreeItemData<ITreeItem>
|
||||||
{
|
{
|
||||||
Expanded = this.ExpandRootNodes,
|
Expanded = this.ExpandRootNodes,
|
||||||
@ -89,227 +125,212 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
Icon = Icons.Material.Filled.Timer,
|
Icon = Icons.Material.Filled.Timer,
|
||||||
Expandable = true,
|
Expandable = true,
|
||||||
Path = "temp",
|
Path = "temp",
|
||||||
Children = await this.LoadTemporaryChats(),
|
Children = temporaryChatsChildren,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeItemData<ITreeItem> CreateWorkspaceTreeItem(WorkspaceTreeWorkspace workspace)
|
||||||
|
{
|
||||||
|
var children = new List<TreeItemData<ITreeItem>>();
|
||||||
|
if (workspace.ChatsLoaded)
|
||||||
|
{
|
||||||
|
foreach (var workspaceChat in workspace.Chats.OrderByDescending(x => x.LastEditTime))
|
||||||
|
children.Add(CreateChatTreeItem(workspaceChat, WorkspaceBranch.WORKSPACES, depth: 2, icon: Icons.Material.Filled.Chat));
|
||||||
|
}
|
||||||
|
else if (this.loadingWorkspaceChatLists.Contains(workspace.WorkspaceId))
|
||||||
|
children.AddRange(this.CreateLoadingRows(workspace.WorkspacePath));
|
||||||
|
|
||||||
|
children.Add(new TreeItemData<ITreeItem>
|
||||||
|
{
|
||||||
|
Expandable = false,
|
||||||
|
Value = new TreeButton(WorkspaceBranch.WORKSPACES, 2, T("Add chat"), Icons.Material.Filled.AddComment, () => this.AddChatAsync(workspace.WorkspacePath)),
|
||||||
|
});
|
||||||
|
|
||||||
|
return new TreeItemData<ITreeItem>
|
||||||
|
{
|
||||||
|
Expandable = true,
|
||||||
|
Value = new TreeItemData
|
||||||
|
{
|
||||||
|
Type = TreeItemType.WORKSPACE,
|
||||||
|
Depth = 1,
|
||||||
|
Branch = WorkspaceBranch.WORKSPACES,
|
||||||
|
Text = workspace.Name,
|
||||||
|
Icon = Icons.Material.Filled.Description,
|
||||||
|
Expandable = true,
|
||||||
|
Path = workspace.WorkspacePath,
|
||||||
|
Children = children,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IReadOnlyCollection<TreeItemData<ITreeItem>> CreateLoadingRows(string workspacePath)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
[
|
||||||
|
this.CreateLoadingTreeItem(workspacePath, "loading_1"),
|
||||||
|
this.CreateLoadingTreeItem(workspacePath, "loading_2"),
|
||||||
|
this.CreateLoadingTreeItem(workspacePath, "loading_3"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeItemData<ITreeItem> CreateLoadingTreeItem(string workspacePath, string suffix)
|
||||||
|
{
|
||||||
|
return new TreeItemData<ITreeItem>
|
||||||
|
{
|
||||||
|
Expandable = false,
|
||||||
|
Value = new TreeItemData
|
||||||
|
{
|
||||||
|
Type = TreeItemType.LOADING,
|
||||||
|
Depth = 2,
|
||||||
|
Branch = WorkspaceBranch.WORKSPACES,
|
||||||
|
Text = T("Loading chats..."),
|
||||||
|
Icon = Icons.Material.Filled.HourglassTop,
|
||||||
|
Expandable = false,
|
||||||
|
Path = Path.Join(workspacePath, suffix),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TreeItemData<ITreeItem> CreateChatTreeItem(WorkspaceTreeChat chat, WorkspaceBranch branch, int depth, string icon)
|
||||||
|
{
|
||||||
|
return new TreeItemData<ITreeItem>
|
||||||
|
{
|
||||||
|
Expandable = false,
|
||||||
|
Value = new TreeItemData
|
||||||
|
{
|
||||||
|
Type = TreeItemType.CHAT,
|
||||||
|
Depth = depth,
|
||||||
|
Branch = branch,
|
||||||
|
Text = chat.Name,
|
||||||
|
Icon = icon,
|
||||||
|
Expandable = false,
|
||||||
|
Path = chat.ChatPath,
|
||||||
|
LastEditTime = chat.LastEditTime,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SafeStateHasChanged()
|
||||||
|
{
|
||||||
|
if (this.isDisposed)
|
||||||
|
return;
|
||||||
|
|
||||||
await this.InvokeAsync(this.StateHasChanged);
|
await this.InvokeAsync(this.StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IReadOnlyCollection<TreeItemData<ITreeItem>>> LoadTemporaryChats()
|
private async Task StartPrefetchAsync()
|
||||||
{
|
{
|
||||||
var tempChildren = new List<TreeItemData>();
|
if (this.prefetchCancellationTokenSource is not null)
|
||||||
|
|
||||||
// Get the temp root directory:
|
|
||||||
var temporaryDirectories = Path.Join(SettingsManager.DataDirectory, "tempChats");
|
|
||||||
|
|
||||||
// Ensure the directory exists:
|
|
||||||
Directory.CreateDirectory(temporaryDirectories);
|
|
||||||
|
|
||||||
// Enumerate the chat directories:
|
|
||||||
foreach (var tempChatDirPath in Directory.EnumerateDirectories(temporaryDirectories))
|
|
||||||
{
|
{
|
||||||
// Read or create the `name` file (self-heal):
|
await this.prefetchCancellationTokenSource.CancelAsync();
|
||||||
var chatNamePath = Path.Join(tempChatDirPath, "name");
|
this.prefetchCancellationTokenSource.Dispose();
|
||||||
string chatName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!File.Exists(chatNamePath))
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
await File.WriteAllTextAsync(chatNamePath, chatName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8);
|
|
||||||
if (string.IsNullOrWhiteSpace(chatName))
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
await File.WriteAllTextAsync(chatNamePath, chatName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the last change time of the chat:
|
|
||||||
var chatThreadPath = Path.Join(tempChatDirPath, "thread.json");
|
|
||||||
var lastEditTime = File.GetLastWriteTimeUtc(chatThreadPath);
|
|
||||||
|
|
||||||
tempChildren.Add(new TreeItemData
|
|
||||||
{
|
|
||||||
Type = TreeItemType.CHAT,
|
|
||||||
Depth = 1,
|
|
||||||
Branch = WorkspaceBranch.TEMPORARY_CHATS,
|
|
||||||
Text = chatName,
|
|
||||||
Icon = Icons.Material.Filled.Timer,
|
|
||||||
Expandable = false,
|
|
||||||
Path = tempChatDirPath,
|
|
||||||
LastEditTime = lastEditTime,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<TreeItemData<ITreeItem>>(tempChildren.OrderByDescending(n => n.LastEditTime).Select(n => new TreeItemData<ITreeItem>
|
this.prefetchCancellationTokenSource = new CancellationTokenSource();
|
||||||
{
|
await this.PrefetchWorkspaceChatsAsync(this.prefetchCancellationTokenSource.Token);
|
||||||
Expandable = false,
|
|
||||||
Value = n,
|
|
||||||
}));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IReadOnlyCollection<TreeItemData<ITreeItem>>> LoadWorkspaces()
|
private async Task PrefetchWorkspaceChatsAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var workspaces = new List<TreeItemData<ITreeItem>>();
|
try
|
||||||
|
|
||||||
//
|
|
||||||
// Search for workspace folders in the data directory:
|
|
||||||
//
|
|
||||||
|
|
||||||
// Get the workspace root directory:
|
|
||||||
var workspaceDirectories = Path.Join(SettingsManager.DataDirectory, "workspaces");
|
|
||||||
|
|
||||||
// Ensure the directory exists:
|
|
||||||
Directory.CreateDirectory(workspaceDirectories);
|
|
||||||
|
|
||||||
// Enumerate the workspace directories:
|
|
||||||
foreach (var workspaceDirPath in Directory.EnumerateDirectories(workspaceDirectories))
|
|
||||||
{
|
{
|
||||||
// Read or create the `name` file (self-heal):
|
await WorkspaceBehaviour.TryPrefetchRemainingChatsAsync(async _ =>
|
||||||
var workspaceNamePath = Path.Join(workspaceDirPath, "name");
|
|
||||||
string workspaceName;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (!File.Exists(workspaceNamePath))
|
if (this.isDisposed || cancellationToken.IsCancellationRequested)
|
||||||
{
|
return;
|
||||||
workspaceName = T("Unnamed workspace");
|
|
||||||
await File.WriteAllTextAsync(workspaceNamePath, workspaceName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8);
|
|
||||||
if (string.IsNullOrWhiteSpace(workspaceName))
|
|
||||||
{
|
|
||||||
workspaceName = T("Unnamed workspace");
|
|
||||||
await File.WriteAllTextAsync(workspaceNamePath, workspaceName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
workspaceName = T("Unnamed workspace");
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaces.Add(new TreeItemData<ITreeItem>
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
{
|
}, cancellationToken);
|
||||||
Expandable = true,
|
}
|
||||||
Value = new TreeItemData
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
Type = TreeItemType.WORKSPACE,
|
// Expected when the component is hidden or disposed.
|
||||||
Depth = 1,
|
}
|
||||||
Branch = WorkspaceBranch.WORKSPACES,
|
catch (Exception ex)
|
||||||
Text = workspaceName,
|
{
|
||||||
Icon = Icons.Material.Filled.Description,
|
this.Logger.LogWarning(ex, "Failed while prefetching workspace chats.");
|
||||||
Expandable = true,
|
}
|
||||||
Path = workspaceDirPath,
|
}
|
||||||
Children = await this.LoadWorkspaceChats(workspaceDirPath),
|
|
||||||
},
|
private async Task OnWorkspaceClicked(TreeItemData treeItem)
|
||||||
});
|
{
|
||||||
|
if (treeItem.Type is not TreeItemType.WORKSPACE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!Guid.TryParse(Path.GetFileName(treeItem.Path), out var workspaceId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.EnsureWorkspaceChatsLoadedAsync(workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EnsureWorkspaceChatsLoadedAsync(Guid workspaceId)
|
||||||
|
{
|
||||||
|
var snapshot = await WorkspaceBehaviour.GetOrLoadWorkspaceTreeShellAsync();
|
||||||
|
var hasWorkspace = false;
|
||||||
|
var chatsLoaded = false;
|
||||||
|
|
||||||
|
foreach (var workspace in snapshot.Workspaces)
|
||||||
|
{
|
||||||
|
if (workspace.WorkspaceId != workspaceId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hasWorkspace = true;
|
||||||
|
chatsLoaded = workspace.ChatsLoaded;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
workspaces.Add(new TreeItemData<ITreeItem>
|
if (!hasWorkspace || chatsLoaded || !this.loadingWorkspaceChatLists.Add(workspaceId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Expandable = false,
|
await WorkspaceBehaviour.GetWorkspaceChatsAsync(workspaceId);
|
||||||
Value = new TreeButton(WorkspaceBranch.WORKSPACES, 1, T("Add workspace"),Icons.Material.Filled.LibraryAdd, this.AddWorkspace),
|
}
|
||||||
});
|
finally
|
||||||
return workspaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IReadOnlyCollection<TreeItemData<ITreeItem>>> LoadWorkspaceChats(string workspacePath)
|
|
||||||
{
|
|
||||||
var workspaceChats = new List<TreeItemData>();
|
|
||||||
|
|
||||||
// Enumerate the workspace directory:
|
|
||||||
foreach (var chatPath in Directory.EnumerateDirectories(workspacePath))
|
|
||||||
{
|
{
|
||||||
// Read or create the `name` file (self-heal):
|
this.loadingWorkspaceChatLists.Remove(workspaceId);
|
||||||
var chatNamePath = Path.Join(chatPath, "name");
|
|
||||||
string chatName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!File.Exists(chatNamePath))
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
await File.WriteAllTextAsync(chatNamePath, chatName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8);
|
|
||||||
if (string.IsNullOrWhiteSpace(chatName))
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
await File.WriteAllTextAsync(chatNamePath, chatName, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
chatName = T("Unnamed chat");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the last change time of the chat:
|
|
||||||
var chatThreadPath = Path.Join(chatPath, "thread.json");
|
|
||||||
var lastEditTime = File.GetLastWriteTimeUtc(chatThreadPath);
|
|
||||||
|
|
||||||
workspaceChats.Add(new TreeItemData
|
|
||||||
{
|
|
||||||
Type = TreeItemType.CHAT,
|
|
||||||
Depth = 2,
|
|
||||||
Branch = WorkspaceBranch.WORKSPACES,
|
|
||||||
Text = chatName,
|
|
||||||
Icon = Icons.Material.Filled.Chat,
|
|
||||||
Expandable = false,
|
|
||||||
Path = chatPath,
|
|
||||||
LastEditTime = lastEditTime,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<TreeItemData<ITreeItem>>(workspaceChats.OrderByDescending(n => n.LastEditTime).Select(n => new TreeItemData<ITreeItem>
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
{
|
|
||||||
Expandable = false,
|
|
||||||
Value = n,
|
|
||||||
}));
|
|
||||||
|
|
||||||
result.Add(new()
|
|
||||||
{
|
|
||||||
Expandable = false,
|
|
||||||
Value = new TreeButton(WorkspaceBranch.WORKSPACES, 2, T("Add chat"),Icons.Material.Filled.AddComment, () => this.AddChat(workspacePath)),
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StoreChat(ChatThread chat, bool reloadTreeItems = true)
|
public async Task ForceRefreshFromDiskAsync()
|
||||||
{
|
{
|
||||||
await WorkspaceBehaviour.StoreChat(chat);
|
if (this.prefetchCancellationTokenSource is not null)
|
||||||
|
{
|
||||||
|
await this.prefetchCancellationTokenSource.CancelAsync();
|
||||||
|
this.prefetchCancellationTokenSource.Dispose();
|
||||||
|
this.prefetchCancellationTokenSource = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Reload the tree items:
|
this.loadingWorkspaceChatLists.Clear();
|
||||||
if(reloadTreeItems)
|
this.isInitialLoading = true;
|
||||||
await this.LoadTreeItems();
|
|
||||||
|
|
||||||
this.StateHasChanged();
|
await this.SafeStateHasChanged();
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: true, forceReload: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ChatThread?> LoadChat(string? chatPath, bool switchToChat)
|
public async Task StoreChatAsync(ChatThread chat, bool reloadTreeItems = false)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(chatPath))
|
await WorkspaceBehaviour.StoreChatAsync(chat);
|
||||||
|
|
||||||
|
if (reloadTreeItems)
|
||||||
|
this.loadingWorkspaceChatLists.Clear();
|
||||||
|
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ChatThread?> LoadChatAsync(string? chatPath, bool switchToChat)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(chatPath))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if(!Directory.Exists(chatPath))
|
if (!Directory.Exists(chatPath))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Check if the chat has unsaved changes:
|
|
||||||
if (switchToChat && await MessageBus.INSTANCE.SendMessageUseFirstResult<bool, bool>(this, Event.HAS_CHAT_UNSAVED_CHANGES))
|
if (switchToChat && await MessageBus.INSTANCE.SendMessageUseFirstResult<bool, bool>(this, Event.HAS_CHAT_UNSAVED_CHANGES))
|
||||||
{
|
{
|
||||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
@ -344,15 +365,15 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteChat(string? chatPath, bool askForConfirmation = true, bool unloadChat = true)
|
public async Task DeleteChatAsync(string? chatPath, bool askForConfirmation = true, bool unloadChat = true)
|
||||||
{
|
{
|
||||||
var chat = await this.LoadChat(chatPath, false);
|
var chat = await this.LoadChatAsync(chatPath, false);
|
||||||
if (chat is null)
|
if (chat is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (askForConfirmation)
|
if (askForConfirmation)
|
||||||
{
|
{
|
||||||
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceName(chat.WorkspaceId);
|
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(chat.WorkspaceId);
|
||||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -370,16 +391,10 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string chatDirectory;
|
await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, chat.WorkspaceId, chat.ChatId, askForConfirmation: false);
|
||||||
if (chat.WorkspaceId == Guid.Empty)
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
chatDirectory = Path.Join(SettingsManager.DataDirectory, "tempChats", chat.ChatId.ToString());
|
|
||||||
else
|
|
||||||
chatDirectory = Path.Join(SettingsManager.DataDirectory, "workspaces", chat.WorkspaceId.ToString(), chat.ChatId.ToString());
|
|
||||||
|
|
||||||
Directory.Delete(chatDirectory, true);
|
if (unloadChat && this.CurrentChatThread?.ChatId == chat.ChatId)
|
||||||
await this.LoadTreeItems();
|
|
||||||
|
|
||||||
if(unloadChat && this.CurrentChatThread?.ChatId == chat.ChatId)
|
|
||||||
{
|
{
|
||||||
this.CurrentChatThread = null;
|
this.CurrentChatThread = null;
|
||||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||||
@ -387,9 +402,9 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RenameChat(string? chatPath)
|
private async Task RenameChatAsync(string? chatPath)
|
||||||
{
|
{
|
||||||
var chat = await this.LoadChat(chatPath, false);
|
var chat = await this.LoadChatAsync(chatPath, false);
|
||||||
if (chat is null)
|
if (chat is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -410,24 +425,24 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
chat.Name = (dialogResult.Data as string)!;
|
chat.Name = (dialogResult.Data as string)!;
|
||||||
if(this.CurrentChatThread?.ChatId == chat.ChatId)
|
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
||||||
{
|
{
|
||||||
this.CurrentChatThread.Name = chat.Name;
|
this.CurrentChatThread.Name = chat.Name;
|
||||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||||
await MessageBus.INSTANCE.SendMessage<bool>(this, Event.WORKSPACE_LOADED_CHAT_CHANGED);
|
await MessageBus.INSTANCE.SendMessage<bool>(this, Event.WORKSPACE_LOADED_CHAT_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.StoreChat(chat);
|
await WorkspaceBehaviour.StoreChatAsync(chat);
|
||||||
await this.LoadTreeItems();
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RenameWorkspace(string? workspacePath)
|
private async Task RenameWorkspaceAsync(string? workspacePath)
|
||||||
{
|
{
|
||||||
if(workspacePath is null)
|
if (workspacePath is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var workspaceId = Guid.Parse(Path.GetFileName(workspacePath));
|
var workspaceId = Guid.Parse(Path.GetFileName(workspacePath));
|
||||||
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceName(workspaceId);
|
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(workspaceId);
|
||||||
var dialogParameters = new DialogParameters<SingleInputDialog>
|
var dialogParameters = new DialogParameters<SingleInputDialog>
|
||||||
{
|
{
|
||||||
{ x => x.Message, string.Format(T("Please enter a new or edit the name for your workspace '{0}':"), workspaceName) },
|
{ x => x.Message, string.Format(T("Please enter a new or edit the name for your workspace '{0}':"), workspaceName) },
|
||||||
@ -447,10 +462,11 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
var alteredWorkspaceName = (dialogResult.Data as string)!;
|
var alteredWorkspaceName = (dialogResult.Data as string)!;
|
||||||
var workspaceNamePath = Path.Join(workspacePath, "name");
|
var workspaceNamePath = Path.Join(workspacePath, "name");
|
||||||
await File.WriteAllTextAsync(workspaceNamePath, alteredWorkspaceName, Encoding.UTF8);
|
await File.WriteAllTextAsync(workspaceNamePath, alteredWorkspaceName, Encoding.UTF8);
|
||||||
await this.LoadTreeItems();
|
await WorkspaceBehaviour.UpdateWorkspaceNameInCacheAsync(workspaceId, alteredWorkspaceName);
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddWorkspace()
|
private async Task AddWorkspaceAsync()
|
||||||
{
|
{
|
||||||
var dialogParameters = new DialogParameters<SingleInputDialog>
|
var dialogParameters = new DialogParameters<SingleInputDialog>
|
||||||
{
|
{
|
||||||
@ -472,23 +488,23 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
var workspacePath = Path.Join(SettingsManager.DataDirectory, "workspaces", workspaceId.ToString());
|
var workspacePath = Path.Join(SettingsManager.DataDirectory, "workspaces", workspaceId.ToString());
|
||||||
Directory.CreateDirectory(workspacePath);
|
Directory.CreateDirectory(workspacePath);
|
||||||
|
|
||||||
|
var workspaceName = (dialogResult.Data as string)!;
|
||||||
var workspaceNamePath = Path.Join(workspacePath, "name");
|
var workspaceNamePath = Path.Join(workspacePath, "name");
|
||||||
await File.WriteAllTextAsync(workspaceNamePath, (dialogResult.Data as string)!, Encoding.UTF8);
|
await File.WriteAllTextAsync(workspaceNamePath, workspaceName, Encoding.UTF8);
|
||||||
|
await WorkspaceBehaviour.AddWorkspaceToCacheAsync(workspaceId, workspacePath, workspaceName);
|
||||||
|
|
||||||
await this.LoadTreeItems();
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteWorkspace(string? workspacePath)
|
private async Task DeleteWorkspaceAsync(string? workspacePath)
|
||||||
{
|
{
|
||||||
if(workspacePath is null)
|
if (workspacePath is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var workspaceId = Guid.Parse(Path.GetFileName(workspacePath));
|
var workspaceId = Guid.Parse(Path.GetFileName(workspacePath));
|
||||||
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceName(workspaceId);
|
var workspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(workspaceId);
|
||||||
|
|
||||||
// Determine how many chats are in the workspace:
|
|
||||||
var chatCount = Directory.EnumerateDirectories(workspacePath).Count();
|
var chatCount = Directory.EnumerateDirectories(workspacePath).Count();
|
||||||
|
|
||||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
{
|
{
|
||||||
{ x => x.Message, string.Format(T("Are you sure you want to delete the workspace '{0}'? This will also delete {1} chat(s) in this workspace."), workspaceName, chatCount) },
|
{ x => x.Message, string.Format(T("Are you sure you want to delete the workspace '{0}'? This will also delete {1} chat(s) in this workspace."), workspaceName, chatCount) },
|
||||||
@ -500,12 +516,13 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Directory.Delete(workspacePath, true);
|
Directory.Delete(workspacePath, true);
|
||||||
await this.LoadTreeItems();
|
await WorkspaceBehaviour.RemoveWorkspaceFromCacheAsync(workspaceId);
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task MoveChat(string? chatPath)
|
private async Task MoveChatAsync(string? chatPath)
|
||||||
{
|
{
|
||||||
var chat = await this.LoadChat(chatPath, false);
|
var chat = await this.LoadChatAsync(chatPath, false);
|
||||||
if (chat is null)
|
if (chat is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -525,22 +542,9 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
if (workspaceId == Guid.Empty)
|
if (workspaceId == Guid.Empty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Delete the chat from the current workspace or the temporary storage:
|
await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, chat.WorkspaceId, chat.ChatId, askForConfirmation: false);
|
||||||
if (chat.WorkspaceId == Guid.Empty)
|
|
||||||
{
|
|
||||||
// Case: The chat is stored in the temporary storage:
|
|
||||||
await this.DeleteChat(Path.Join(SettingsManager.DataDirectory, "tempChats", chat.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Case: The chat is stored in a workspace.
|
|
||||||
await this.DeleteChat(Path.Join(SettingsManager.DataDirectory, "workspaces", chat.WorkspaceId.ToString(), chat.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the chat's workspace:
|
|
||||||
chat.WorkspaceId = workspaceId;
|
chat.WorkspaceId = workspaceId;
|
||||||
|
|
||||||
// Handle the case where the chat is the active chat:
|
|
||||||
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
||||||
{
|
{
|
||||||
this.CurrentChatThread = chat;
|
this.CurrentChatThread = chat;
|
||||||
@ -548,12 +552,12 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
await MessageBus.INSTANCE.SendMessage<bool>(this, Event.WORKSPACE_LOADED_CHAT_CHANGED);
|
await MessageBus.INSTANCE.SendMessage<bool>(this, Event.WORKSPACE_LOADED_CHAT_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.StoreChat(chat);
|
await WorkspaceBehaviour.StoreChatAsync(chat);
|
||||||
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddChat(string workspacePath)
|
private async Task AddChatAsync(string workspacePath)
|
||||||
{
|
{
|
||||||
// Check if the chat has unsaved changes:
|
|
||||||
if (await MessageBus.INSTANCE.SendMessageUseFirstResult<bool, bool>(this, Event.HAS_CHAT_UNSAVED_CHANGES))
|
if (await MessageBus.INSTANCE.SendMessageUseFirstResult<bool, bool>(this, Event.HAS_CHAT_UNSAVED_CHANGES))
|
||||||
{
|
{
|
||||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||||
@ -579,9 +583,9 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
|
|
||||||
var chatPath = Path.Join(workspacePath, chat.ChatId.ToString());
|
var chatPath = Path.Join(workspacePath, chat.ChatId.ToString());
|
||||||
|
|
||||||
await this.StoreChat(chat);
|
await WorkspaceBehaviour.StoreChatAsync(chat);
|
||||||
await this.LoadChat(chatPath, switchToChat: true);
|
await this.LoadChatAsync(chatPath, switchToChat: true);
|
||||||
await this.LoadTreeItems();
|
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of MSGComponentBase
|
#region Overrides of MSGComponentBase
|
||||||
@ -591,11 +595,20 @@ public partial class Workspaces : MSGComponentBase
|
|||||||
switch (triggeredEvent)
|
switch (triggeredEvent)
|
||||||
{
|
{
|
||||||
case Event.PLUGINS_RELOADED:
|
case Event.PLUGINS_RELOADED:
|
||||||
await this.LoadTreeItems();
|
await this.ForceRefreshFromDiskAsync();
|
||||||
await this.InvokeAsync(this.StateHasChanged);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void DisposeResources()
|
||||||
|
{
|
||||||
|
this.isDisposed = true;
|
||||||
|
this.prefetchCancellationTokenSource?.Cancel();
|
||||||
|
this.prefetchCancellationTokenSource?.Dispose();
|
||||||
|
this.prefetchCancellationTokenSource = null;
|
||||||
|
|
||||||
|
base.DisposeResources();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@
|
|||||||
Class="ma-2 pe-4"
|
Class="ma-2 pe-4"
|
||||||
HelperText="@T("This is the content we loaded from your file — including headings, lists, and formatting. Use this to verify your file loads as expected.")">
|
HelperText="@T("This is the content we loaded from your file — including headings, lists, and formatting. Use this to verify your file loads as expected.")">
|
||||||
<div style="max-height: 40vh; overflow-y: auto;">
|
<div style="max-height: 40vh; overflow-y: auto;">
|
||||||
<MudMarkdown Value="@this.FileContent" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling"/>
|
<MudMarkdown Value="@this.FileContent" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</div>
|
</div>
|
||||||
</MudField>
|
</MudField>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
|
|||||||
22
app/MindWork AI Studio/Dialogs/EmbeddingResultDialog.razor
Normal file
22
app/MindWork AI Studio/Dialogs/EmbeddingResultDialog.razor
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@inherits MSGComponentBase
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
Text="@this.ResultText"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Lines="10"
|
||||||
|
AutoGrow="@true"
|
||||||
|
MaxLines="25"
|
||||||
|
ReadOnly="true"
|
||||||
|
Label="@this.ResultLabelText"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.DataObject"
|
||||||
|
Adornment="Adornment.Start"/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="@this.Close" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
|
@T("Close")
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
using AIStudio.Components;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Dialogs;
|
||||||
|
|
||||||
|
public partial class EmbeddingResultDialog : MSGComponentBase
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ResultText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ResultLabel { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
private string ResultLabelText => string.IsNullOrWhiteSpace(this.ResultLabel) ? T("Embedding Vector") : this.ResultLabel;
|
||||||
|
|
||||||
|
private void Close() => this.MudDialog.Close();
|
||||||
|
}
|
||||||
@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
else if (!string.IsNullOrWhiteSpace(this.licenseText))
|
else if (!string.IsNullOrWhiteSpace(this.licenseText))
|
||||||
{
|
{
|
||||||
<MudMarkdown Value="@this.licenseText" Props="Markdown.DefaultConfig"/>
|
<MudMarkdown Value="@this.licenseText" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
}
|
}
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
@namespace AIStudio.Dialogs.Settings
|
||||||
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
@using AIStudio.Settings
|
|
||||||
@inherits SettingsDialogBase
|
|
||||||
|
|
||||||
<MudDialog>
|
|
||||||
<TitleContent>
|
|
||||||
<PreviewPrototype/>
|
|
||||||
<MudText Typo="Typo.h6" Class="d-flex align-center">
|
|
||||||
<MudIcon Icon="@Icons.Material.Filled.DocumentScanner" Class="mr-2"/>
|
|
||||||
@T("Assistant: Document Analysis")
|
|
||||||
</MudText>
|
|
||||||
</TitleContent>
|
|
||||||
<DialogContent>
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="@T("Preselect document analysis options?")" LabelOn="@T("Document analysis options are preselected")" LabelOff="@T("No document analysis options are preselected")" State="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.ERI.PreselectOptions = updatedState)" OptionHelp="@T("When enabled, you can preselect some document analysis options.")"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="@T("Preselect one of your profiles?")" Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile = selectedValue)" OptionHelp="@T("Would you like to preselect one of your profiles?")"/>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mb-3">
|
|
||||||
@T("Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.")
|
|
||||||
</MudText>
|
|
||||||
</MudPaper>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<MudButton OnClick="@this.Close" Variant="Variant.Filled">
|
|
||||||
@T("Close")
|
|
||||||
</MudButton>
|
|
||||||
</DialogActions>
|
|
||||||
</MudDialog>
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
namespace AIStudio.Dialogs.Settings;
|
|
||||||
|
|
||||||
public partial class SettingsDialogDocumentAnalysis : SettingsDialogBase;
|
|
||||||
@ -1,11 +1,21 @@
|
|||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
<MudDialog>
|
<MudDialog DefaultFocus="DefaultFocus.FirstChild">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<MudText Typo="Typo.body1">
|
<MudText Typo="Typo.body1">
|
||||||
@this.Message
|
@this.Message
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudForm @ref="this.form" Class="mt-4">
|
<MudForm @ref="this.form" Class="mt-4">
|
||||||
<MudTextField T="string" @bind-Text="@this.UserInput" Variant="Variant.Outlined" AutoGrow="@false" Lines="1" Label="@this.GetInputHeaderText" AutoFocus="@true" UserAttributes="@USER_INPUT_ATTRIBUTES" Validation="@this.ValidateUserInput" />
|
<MudTextField T="string"
|
||||||
|
@bind-Text="@this.UserInput"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
AutoGrow="@false"
|
||||||
|
Lines="1"
|
||||||
|
Label="@this.GetInputHeaderText"
|
||||||
|
AutoFocus="@true"
|
||||||
|
Immediate="@true"
|
||||||
|
OnKeyDown="@this.HandleUserInputKeyDown"
|
||||||
|
UserAttributes="@USER_INPUT_ATTRIBUTES"
|
||||||
|
Validation="@this.ValidateUserInput" />
|
||||||
</MudForm>
|
</MudForm>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using AIStudio.Components;
|
using AIStudio.Components;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
|
||||||
namespace AIStudio.Dialogs;
|
namespace AIStudio.Dialogs;
|
||||||
|
|
||||||
@ -57,6 +58,19 @@ public partial class SingleInputDialog : MSGComponentBase
|
|||||||
|
|
||||||
private void Cancel() => this.MudDialog.Cancel();
|
private void Cancel() => this.MudDialog.Cancel();
|
||||||
|
|
||||||
|
private async Task HandleUserInputKeyDown(KeyboardEventArgs keyEvent)
|
||||||
|
{
|
||||||
|
var key = keyEvent.Key.ToLowerInvariant();
|
||||||
|
var code = keyEvent.Code.ToLowerInvariant();
|
||||||
|
if (key is not "enter" && code is not "enter" and not "numpadenter")
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (keyEvent is { AltKey: true } or { CtrlKey: true } or { MetaKey: true })
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.Confirm();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Confirm()
|
private async Task Confirm()
|
||||||
{
|
{
|
||||||
await this.form.Validate();
|
await this.form.Validate();
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<MudIcon Icon="@Icons.Material.Filled.Update" Size="Size.Large" Class="mr-3"/>
|
<MudIcon Icon="@Icons.Material.Filled.Update" Size="Size.Large" Class="mr-3"/>
|
||||||
@this.HeaderText
|
@this.HeaderText
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudMarkdown Value="@this.UpdateResponse.Changelog" Props="Markdown.DefaultConfig"/>
|
<MudMarkdown Value="@this.UpdateResponse.Changelog" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">
|
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using System.Text;
|
|
||||||
|
|
||||||
using AIStudio.Components;
|
using AIStudio.Components;
|
||||||
using AIStudio.Settings;
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
@ -30,24 +27,9 @@ public partial class WorkspaceSelectionDialog : MSGComponentBase
|
|||||||
{
|
{
|
||||||
this.selectedWorkspace = this.SelectedWorkspace;
|
this.selectedWorkspace = this.SelectedWorkspace;
|
||||||
|
|
||||||
// Get the workspace root directory:
|
var snapshot = await WorkspaceBehaviour.GetOrLoadWorkspaceTreeShellAsync();
|
||||||
var workspaceDirectories = Path.Join(SettingsManager.DataDirectory, "workspaces");
|
foreach (var workspace in snapshot.Workspaces)
|
||||||
if(!Directory.Exists(workspaceDirectories))
|
this.workspaces[workspace.Name] = workspace.WorkspaceId;
|
||||||
{
|
|
||||||
await base.OnInitializedAsync();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerate the workspace directories:
|
|
||||||
foreach (var workspaceDirPath in Directory.EnumerateDirectories(workspaceDirectories))
|
|
||||||
{
|
|
||||||
// Read the `name` file:
|
|
||||||
var workspaceNamePath = Path.Join(workspaceDirPath, "name");
|
|
||||||
var workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8);
|
|
||||||
|
|
||||||
// Add the workspace to the list:
|
|
||||||
this.workspaces.Add(workspaceName, Guid.Parse(Path.GetFileName(workspaceDirPath)));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.StateHasChanged();
|
this.StateHasChanged();
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
|
|||||||
@ -211,9 +211,35 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
|||||||
//
|
//
|
||||||
// Check if there is an enterprise configuration plugin to download:
|
// Check if there is an enterprise configuration plugin to download:
|
||||||
//
|
//
|
||||||
var enterpriseEnvironment = this.MessageBus.CheckDeferredMessages<EnterpriseEnvironment>(Event.STARTUP_ENTERPRISE_ENVIRONMENT).FirstOrDefault();
|
var enterpriseEnvironments = this.MessageBus
|
||||||
if (enterpriseEnvironment != default)
|
.CheckDeferredMessages<EnterpriseEnvironment>(Event.STARTUP_ENTERPRISE_ENVIRONMENT)
|
||||||
await PluginFactory.TryDownloadingConfigPluginAsync(enterpriseEnvironment.ConfigurationId, enterpriseEnvironment.ConfigurationServerUrl);
|
.Where(env => env != default)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var failedDeferredConfigIds = new HashSet<Guid>();
|
||||||
|
foreach (var env in enterpriseEnvironments)
|
||||||
|
{
|
||||||
|
var wasDownloadSuccessful = await PluginFactory.TryDownloadingConfigPluginAsync(env.ConfigurationId, env.ConfigurationServerUrl);
|
||||||
|
if (!wasDownloadSuccessful)
|
||||||
|
{
|
||||||
|
failedDeferredConfigIds.Add(env.ConfigurationId);
|
||||||
|
this.Logger.LogWarning("Failed to download deferred enterprise configuration '{ConfigId}' during startup. Keeping managed plugins unchanged.", env.ConfigurationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnterpriseEnvironmentService.HasValidEnterpriseSnapshot)
|
||||||
|
{
|
||||||
|
var activeConfigIds = EnterpriseEnvironmentService.CURRENT_ENVIRONMENTS
|
||||||
|
.Select(env => env.ConfigurationId)
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
PluginFactory.RemoveUnreferencedManagedConfigurationPlugins(activeConfigIds);
|
||||||
|
if (failedDeferredConfigIds.Count > 0)
|
||||||
|
this.Logger.LogWarning("Deferred startup updates failed for {FailedCount} enterprise configuration(s). Those configurations were kept unchanged.", failedDeferredConfigIds.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the enterprise encryption service for decrypting API keys:
|
||||||
|
await PluginFactory.InitializeEnterpriseEncryption(this.RustService);
|
||||||
|
|
||||||
// Load (but not start) all plugins without waiting for them:
|
// Load (but not start) all plugins without waiting for them:
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.12" />
|
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.12" />
|
||||||
<PackageReference Include="MudBlazor" Version="8.15.0" />
|
<PackageReference Include="MudBlazor" Version="8.15.0" />
|
||||||
<PackageReference Include="MudBlazor.Markdown" Version="8.11.0" />
|
<PackageReference Include="MudBlazor.Markdown" Version="8.11.0" />
|
||||||
|
<PackageReference Include="Qdrant.Client" Version="1.17.0" />
|
||||||
<PackageReference Include="ReverseMarkdown" Version="5.0.0" />
|
<PackageReference Include="ReverseMarkdown" Version="5.0.0" />
|
||||||
<PackageReference Include="LuaCSharp" Version="0.5.3" />
|
<PackageReference Include="LuaCSharp" Version="0.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -81,6 +82,7 @@
|
|||||||
<MetaAppCommitHash>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 8 ])</MetaAppCommitHash>
|
<MetaAppCommitHash>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 8 ])</MetaAppCommitHash>
|
||||||
<MetaArchitecture>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 9 ])</MetaArchitecture>
|
<MetaArchitecture>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 9 ])</MetaArchitecture>
|
||||||
<MetaPdfiumVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 10 ])</MetaPdfiumVersion>
|
<MetaPdfiumVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 10 ])</MetaPdfiumVersion>
|
||||||
|
<MetaQdrantVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 11 ])</MetaQdrantVersion>
|
||||||
|
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
|
|
||||||
@ -108,6 +110,9 @@
|
|||||||
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataLibraries">
|
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataLibraries">
|
||||||
<_Parameter1>$(MetaPdfiumVersion)</_Parameter1>
|
<_Parameter1>$(MetaPdfiumVersion)</_Parameter1>
|
||||||
</AssemblyAttribute>
|
</AssemblyAttribute>
|
||||||
|
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataDatabases">
|
||||||
|
<_Parameter1>$(MetaQdrantVersion)</_Parameter1>
|
||||||
|
</AssemblyAttribute>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Target>
|
</Target>
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
||||||
<AssistantBlock TSettings="SettingsDialogWritingEMails" Component="Components.EMAIL_ASSISTANT" Name="@T("E-Mail")" Description="@T("Generate an e-mail for a given context.")" Icon="@Icons.Material.Filled.Email" Link="@Routes.ASSISTANT_EMAIL"/>
|
<AssistantBlock TSettings="SettingsDialogWritingEMails" Component="Components.EMAIL_ASSISTANT" Name="@T("E-Mail")" Description="@T("Generate an e-mail for a given context.")" Icon="@Icons.Material.Filled.Email" Link="@Routes.ASSISTANT_EMAIL"/>
|
||||||
<AssistantBlock TSettings="SettingsDialogDocumentAnalysis" Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" RequiredPreviewFeature="PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025" Name="@T("Document Analysis")" Description="@T("Analyze a document regarding defined rules and extract key information.")" Icon="@Icons.Material.Filled.DocumentScanner" Link="@Routes.ASSISTANT_DOCUMENT_ANALYSIS"/>
|
<AssistantBlock TSettings="NoSettingsPanel" Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" RequiredPreviewFeature="PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025" Name="@T("Document Analysis")" Description="@T("Analyze a document regarding defined rules and extract key information.")" Icon="@Icons.Material.Filled.DocumentScanner" Link="@Routes.ASSISTANT_DOCUMENT_ANALYSIS"/>
|
||||||
<AssistantBlock TSettings="SettingsDialogMyTasks" Component="Components.MY_TASKS_ASSISTANT" Name="@T("My Tasks")" Description="@T("Analyze a text or an email for tasks you need to complete.")" Icon="@Icons.Material.Filled.Task" Link="@Routes.ASSISTANT_MY_TASKS"/>
|
<AssistantBlock TSettings="SettingsDialogMyTasks" Component="Components.MY_TASKS_ASSISTANT" Name="@T("My Tasks")" Description="@T("Analyze a text or an email for tasks you need to complete.")" Icon="@Icons.Material.Filled.Task" Link="@Routes.ASSISTANT_MY_TASKS"/>
|
||||||
<AssistantBlock TSettings="SettingsDialogAgenda" Component="Components.AGENDA_ASSISTANT" Name="@T("Agenda Planner")" Description="@T("Generate an agenda for a given meeting, seminar, etc.")" Icon="@Icons.Material.Filled.CalendarToday" Link="@Routes.ASSISTANT_AGENDA"/>
|
<AssistantBlock TSettings="SettingsDialogAgenda" Component="Components.AGENDA_ASSISTANT" Name="@T("Agenda Planner")" Description="@T("Generate an agenda for a given meeting, seminar, etc.")" Icon="@Icons.Material.Filled.CalendarToday" Link="@Routes.ASSISTANT_AGENDA"/>
|
||||||
<AssistantBlock TSettings="SettingsDialogJobPostings" Component="Components.JOB_POSTING_ASSISTANT" Name="@T("Job Posting")" Description="@T("Generate a job posting for a given job description.")" Icon="@Icons.Material.Filled.Work" Link="@Routes.ASSISTANT_JOB_POSTING"/>
|
<AssistantBlock TSettings="SettingsDialogJobPostings" Component="Components.JOB_POSTING_ASSISTANT" Name="@T("Job Posting")" Description="@T("Generate a job posting for a given job description.")" Icon="@Icons.Material.Filled.Work" Link="@Routes.ASSISTANT_JOB_POSTING"/>
|
||||||
|
|||||||
@ -29,7 +29,9 @@
|
|||||||
</MudToolBar>
|
</MudToolBar>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
|
<CascadingValue Value="Components.CHAT">
|
||||||
|
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
|
||||||
|
</CascadingValue>
|
||||||
@if (this.AreWorkspacesVisible)
|
@if (this.AreWorkspacesVisible)
|
||||||
{
|
{
|
||||||
<MudSplitter Dimension="@this.ReadSplitterPosition" DimensionChanged="this.SplitterChanged" EnableSlide="@this.AreWorkspacesVisible" EnableMargin="@false" StartContentStyle="margin-right: 1em;" BarStyle="" EndContentStyle="margin-left: 1em;">
|
<MudSplitter Dimension="@this.ReadSplitterPosition" DimensionChanged="this.SplitterChanged" EnableSlide="@this.AreWorkspacesVisible" EnableMargin="@false" StartContentStyle="margin-right: 1em;" BarStyle="" EndContentStyle="margin-left: 1em;">
|
||||||
@ -46,6 +48,9 @@
|
|||||||
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
<MudTooltip Text="@T("Reload your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Refresh" Size="Size.Medium" OnClick="@this.RefreshWorkspaces"/>
|
||||||
|
</MudTooltip>
|
||||||
<MudTooltip Text="@T("Hide your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="@T("Hide your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
<MudIconButton Size="Size.Medium" Icon="@this.WorkspaceSidebarToggleIcon" Class="me-1" OnClick="@(() => this.ToggleWorkspaceSidebar())"/>
|
<MudIconButton Size="Size.Medium" Icon="@this.WorkspaceSidebarToggleIcon" Class="me-1" OnClick="@(() => this.ToggleWorkspaceSidebar())"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
@ -69,6 +74,9 @@
|
|||||||
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
<MudTooltip Text="@T("Reload your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Refresh" Size="Size.Medium" OnClick="@this.RefreshWorkspaces"/>
|
||||||
|
</MudTooltip>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</HeaderContent>
|
</HeaderContent>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
@ -135,6 +143,9 @@
|
|||||||
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="@T("Configure your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Medium" OnClick="@(async () => await this.OpenWorkspacesSettingsDialog())"/>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
|
<MudTooltip Text="@T("Reload your workspaces")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Refresh" Size="Size.Medium" OnClick="@this.RefreshWorkspaces"/>
|
||||||
|
</MudTooltip>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Close" Color="Color.Error" Size="Size.Medium" OnClick="@(() => this.ToggleWorkspacesOverlay())"/>
|
<MudIconButton Icon="@Icons.Material.Filled.Close" Color="Color.Error" Size="Size.Medium" OnClick="@(() => this.ToggleWorkspacesOverlay())"/>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</MudDrawerHeader>
|
</MudDrawerHeader>
|
||||||
|
|||||||
@ -98,6 +98,14 @@ public partial class Chat : MSGComponentBase
|
|||||||
await this.DialogService.ShowAsync<SettingsDialogWorkspaces>(T("Open Workspaces Configuration"), dialogParameters, DialogOptions.FULLSCREEN);
|
await this.DialogService.ShowAsync<SettingsDialogWorkspaces>(T("Open Workspaces Configuration"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task RefreshWorkspaces()
|
||||||
|
{
|
||||||
|
if (this.workspaces is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await this.workspaces.ForceRefreshFromDiskAsync();
|
||||||
|
}
|
||||||
|
|
||||||
#region Overrides of MSGComponentBase
|
#region Overrides of MSGComponentBase
|
||||||
|
|
||||||
protected override void DisposeResources()
|
protected override void DisposeResources()
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.EventNote" HeaderText="@T("Last Changelog")">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.EventNote" HeaderText="@T("Last Changelog")">
|
||||||
<MudMarkdown Value="@this.LastChangeContent" Props="Markdown.DefaultConfig"/>
|
<MudMarkdown Value="@this.LastChangeContent" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Lightbulb" HeaderText="@T("Vision")">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Lightbulb" HeaderText="@T("Vision")">
|
||||||
@ -35,7 +35,7 @@
|
|||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.RocketLaunch" HeaderText="@T("Quick Start Guide")">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.RocketLaunch" HeaderText="@T("Quick Start Guide")">
|
||||||
<MudMarkdown Props="Markdown.DefaultConfig" Value="@QUICK_START_GUIDE"/>
|
<MudMarkdown Props="Markdown.DefaultConfig" Value="@QUICK_START_GUIDE" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
</MudExpansionPanels>
|
</MudExpansionPanels>
|
||||||
|
|||||||
@ -31,6 +31,7 @@ public partial class Home : MSGComponentBase
|
|||||||
{
|
{
|
||||||
this.itemsAdvantages = [
|
this.itemsAdvantages = [
|
||||||
new(this.T("Free of charge"), this.T("The app is free to use, both for personal and commercial purposes.")),
|
new(this.T("Free of charge"), this.T("The app is free to use, both for personal and commercial purposes.")),
|
||||||
|
new(this.T("Democratization of AI"), this.T("We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 EUR such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models.")),
|
||||||
new(this.T("Independence"), this.T("You are not tied to any single provider. Instead, you might choose the provider that best suits your needs. Right now, we support OpenAI (GPT5, o1, etc.), Perplexity, Mistral, Anthropic (Claude), Google Gemini, xAI (Grok), DeepSeek, Alibaba Cloud (Qwen), OpenRouter, Hugging Face, and self-hosted models using vLLM, llama.cpp, ollama, LM Studio, Groq, or Fireworks. For scientists and employees of research institutions, we also support Helmholtz and GWDG AI services. These are available through federated logins like eduGAIN to all 18 Helmholtz Centers, the Max Planck Society, most German, and many international universities.")),
|
new(this.T("Independence"), this.T("You are not tied to any single provider. Instead, you might choose the provider that best suits your needs. Right now, we support OpenAI (GPT5, o1, etc.), Perplexity, Mistral, Anthropic (Claude), Google Gemini, xAI (Grok), DeepSeek, Alibaba Cloud (Qwen), OpenRouter, Hugging Face, and self-hosted models using vLLM, llama.cpp, ollama, LM Studio, Groq, or Fireworks. For scientists and employees of research institutions, we also support Helmholtz and GWDG AI services. These are available through federated logins like eduGAIN to all 18 Helmholtz Centers, the Max Planck Society, most German, and many international universities.")),
|
||||||
new(this.T("Assistants"), this.T("You just want to quickly translate a text? AI Studio has so-called assistants for such and other tasks. No prompting is necessary when working with these assistants.")),
|
new(this.T("Assistants"), this.T("You just want to quickly translate a text? AI Studio has so-called assistants for such and other tasks. No prompting is necessary when working with these assistants.")),
|
||||||
new(this.T("Unrestricted usage"), this.T("Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API.")),
|
new(this.T("Unrestricted usage"), this.T("Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API.")),
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
@attribute [Route(Routes.ABOUT)]
|
@attribute [Route(Routes.ABOUT)]
|
||||||
|
@using AIStudio.Tools.PluginSystem
|
||||||
@using AIStudio.Tools.Services
|
@using AIStudio.Tools.Services
|
||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
|
|
||||||
@ -19,15 +20,38 @@
|
|||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@this.VersionDotnetSdk"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@this.VersionDotnetSdk"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Memory" Text="@this.VersionDotnetRuntime"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Memory" Text="@this.VersionDotnetRuntime"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@this.VersionRust"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@this.VersionRust"/>
|
||||||
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Storage">
|
||||||
|
<MudText Typo="Typo.body1">
|
||||||
|
@this.VersionDatabase
|
||||||
|
</MudText>
|
||||||
|
<MudCollapse Expanded="@this.showDatabaseDetails">
|
||||||
|
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
||||||
|
@foreach (var item in this.databaseDisplayInfo)
|
||||||
|
{
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
||||||
|
<span>@item.Label: @item.Value</span>
|
||||||
|
<MudCopyClipboardButton TooltipMessage="@(T("Copies the following to the clipboard")+": "+item.Value)" StringContent=@item.Value/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</MudText>
|
||||||
|
</MudCollapse>
|
||||||
|
<MudButton StartIcon="@(this.showDatabaseDetails ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)"
|
||||||
|
Size="Size.Small"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
OnClick="@this.ToggleDatabaseDetails">
|
||||||
|
@(this.showDatabaseDetails ? T("Hide Details") : T("Show Details"))
|
||||||
|
</MudButton>
|
||||||
|
</MudListItem>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.DocumentScanner" Text="@this.VersionPdfium"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.DocumentScanner" Text="@this.VersionPdfium"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Article" Text="@this.versionPandoc"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Article" Text="@this.versionPandoc"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Widgets" Text="@MudBlazorVersion"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Widgets" Text="@MudBlazorVersion"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Memory" Text="@TauriVersion"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Memory" Text="@TauriVersion"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Translate" Text="@this.OSLanguage"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Translate" Text="@this.OSLanguage"/>
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Business">
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Business">
|
||||||
@switch (EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.IsActive)
|
@switch (HasAnyActiveEnvironment)
|
||||||
{
|
{
|
||||||
case false when this.configPlug is null:
|
case false when this.configPlugins.Count == 0:
|
||||||
<MudText Typo="Typo.body1">
|
<MudText Typo="Typo.body1">
|
||||||
@T("This is a private AI Studio installation. It runs without an enterprise configuration.")
|
@T("This is a private AI Studio installation. It runs without an enterprise configuration.")
|
||||||
</MudText>
|
</MudText>
|
||||||
@ -35,70 +59,119 @@
|
|||||||
|
|
||||||
case false:
|
case false:
|
||||||
<MudText Typo="Typo.body1">
|
<MudText Typo="Typo.body1">
|
||||||
@T("AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management.")
|
@T("AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management.")
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
@foreach (var plug in this.configPlugins)
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
{
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
<ConfigPluginInfoCard HeaderIcon="@Icons.Material.Filled.Extension"
|
||||||
<span>@T("Configuration plugin ID:") @this.configPlug!.Id</span>
|
HeaderText="@plug.Name"
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the configuration plugin ID to the clipboard")" StringContent=@this.configPlug!.Id.ToString()/>
|
Items="@([
|
||||||
</div>
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
</MudText>
|
$"{T("Configuration plugin ID:")} {plug.Id}",
|
||||||
|
plug.Id.ToString(),
|
||||||
|
T("Copies the configuration plugin ID to the clipboard"))
|
||||||
|
])"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<EncryptionSecretInfo IsConfigured="@(PluginFactory.EnterpriseEncryption?.IsAvailable is true)"
|
||||||
|
ConfiguredText="@T("Encryption secret: is configured")"
|
||||||
|
NotConfiguredText="@T("Encryption secret: is not configured")"/>
|
||||||
</MudCollapse>
|
</MudCollapse>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case true when this.configPlug is null:
|
case true when this.configPlugins.Count == 0:
|
||||||
<MudText Typo="Typo.body1">
|
<MudText Typo="Typo.body1">
|
||||||
@T("AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.")
|
@T("AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available.")
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
@foreach (var env in EnterpriseEnvironmentService.CURRENT_ENVIRONMENTS.Where(e => e.IsActive))
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
{
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
<ConfigPluginInfoCard HeaderIcon="@Icons.Material.Filled.HourglassBottom"
|
||||||
<span>@T("Enterprise configuration ID:") @EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationId</span>
|
HeaderText="@T("Waiting for the configuration plugin...")"
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the config ID to the clipboard")" StringContent=@EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationId.ToString()/>
|
Items="@([
|
||||||
</div>
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
</MudText>
|
$"{T("Enterprise configuration ID:")} {env.ConfigurationId}",
|
||||||
|
env.ConfigurationId.ToString(),
|
||||||
|
T("Copies the config ID to the clipboard")),
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
$"{T("Configuration server:")} {env.ConfigurationServerUrl}",
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
env.ConfigurationServerUrl,
|
||||||
<span>@T("Configuration server:") @EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationServerUrl</span>
|
T("Copies the server URL to the clipboard"),
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the server URL to the clipboard")" StringContent=@EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationServerUrl/>
|
"margin-top: 4px;")
|
||||||
</div>
|
])"/>
|
||||||
</MudText>
|
}
|
||||||
|
|
||||||
|
<EncryptionSecretInfo IsConfigured="@(PluginFactory.EnterpriseEncryption?.IsAvailable is true)"
|
||||||
|
ConfiguredText="@T("Encryption secret: is configured")"
|
||||||
|
NotConfiguredText="@T("Encryption secret: is not configured")"/>
|
||||||
</MudCollapse>
|
</MudCollapse>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case true:
|
case true:
|
||||||
<MudText Typo="Typo.body1">
|
@if (this.HasAnyLoadedEnterpriseConfigurationPlugin)
|
||||||
@T("AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.")
|
{
|
||||||
</MudText>
|
<MudText Typo="Typo.body1">
|
||||||
|
@T("AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active.")
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.body1">
|
||||||
|
@T("AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available.")
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
<MudCollapse Expanded="@this.showEnterpriseConfigDetails">
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
@foreach (var env in EnterpriseEnvironmentService.CURRENT_ENVIRONMENTS.Where(e => e.IsActive))
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
{
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
var matchingPlugin = this.FindManagedConfigurationPlugin(env.ConfigurationId);
|
||||||
<span>@T("Enterprise configuration ID:") @EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationId</span>
|
if (matchingPlugin is null)
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the config ID to the clipboard")" StringContent=@EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationId.ToString()/>
|
{
|
||||||
</div>
|
<ConfigPluginInfoCard HeaderIcon="@Icons.Material.Filled.HourglassBottom"
|
||||||
</MudText>
|
HeaderText="@T("Waiting for the configuration plugin...")"
|
||||||
|
Items="@([
|
||||||
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
|
$"{T("Enterprise configuration ID:")} {env.ConfigurationId}",
|
||||||
|
env.ConfigurationId.ToString(),
|
||||||
|
T("Copies the config ID to the clipboard")),
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
$"{T("Configuration server:")} {env.ConfigurationServerUrl}",
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
env.ConfigurationServerUrl,
|
||||||
<span>@T("Configuration server:") @EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationServerUrl</span>
|
T("Copies the server URL to the clipboard"),
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the server URL to the clipboard")" StringContent=@EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.ConfigurationServerUrl/>
|
"margin-top: 4px;")
|
||||||
</div>
|
])"/>
|
||||||
</MudText>
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
<ConfigPluginInfoCard HeaderIcon="@Icons.Material.Filled.Extension"
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
HeaderText="@matchingPlugin.Name"
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
Items="@([
|
||||||
<span>@T("Configuration plugin ID:") @this.configPlug!.Id</span>
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
<MudCopyClipboardButton TooltipMessage="@T("Copies the configuration plugin ID to the clipboard")" StringContent=@this.configPlug!.Id.ToString()/>
|
$"{T("Enterprise configuration ID:")} {env.ConfigurationId}",
|
||||||
</div>
|
env.ConfigurationId.ToString(),
|
||||||
</MudText>
|
T("Copies the config ID to the clipboard")),
|
||||||
|
|
||||||
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
|
$"{T("Configuration server:")} {env.ConfigurationServerUrl}",
|
||||||
|
env.ConfigurationServerUrl,
|
||||||
|
T("Copies the server URL to the clipboard"),
|
||||||
|
"margin-top: 4px;"),
|
||||||
|
|
||||||
|
new ConfigInfoRowItem(Icons.Material.Filled.ArrowRightAlt,
|
||||||
|
$"{T("Configuration plugin ID:")} {matchingPlugin.Id}",
|
||||||
|
matchingPlugin.Id.ToString(),
|
||||||
|
T("Copies the configuration plugin ID to the clipboard"),
|
||||||
|
"margin-top: 4px;")
|
||||||
|
])"
|
||||||
|
ShowWarning="@this.IsManagedConfigurationIdMismatch(matchingPlugin, env.ConfigurationId)"
|
||||||
|
WarningText="@T("ID mismatch: the plugin ID differs from the enterprise configuration ID.")"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<EncryptionSecretInfo IsConfigured="@(PluginFactory.EnterpriseEncryption?.IsAvailable is true)"
|
||||||
|
ConfiguredText="@T("Encryption secret: is configured")"
|
||||||
|
NotConfiguredText="@T("Encryption secret: is not configured")"/>
|
||||||
</MudCollapse>
|
</MudCollapse>
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -115,10 +188,10 @@
|
|||||||
</MudListItem>
|
</MudListItem>
|
||||||
</MudList>
|
</MudList>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Update" OnClick="() => this.CheckForUpdate()">
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Update" OnClick="@(() => this.CheckForUpdate())">
|
||||||
@T("Check for updates")
|
@T("Check for updates")
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Default" StartIcon="@Icons.Material.Filled.Download" OnClick="async () => await this.ShowPandocDialog()">
|
<MudButton Variant="Variant.Filled" Color="Color.Default" StartIcon="@Icons.Material.Filled.Download" OnClick="@(async () => await this.ShowPandocDialog())">
|
||||||
@this.PandocButtonText
|
@this.PandocButtonText
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
@ -126,7 +199,7 @@
|
|||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Custom.Brands.GitHub" HeaderText="@T("Community & Code")">
|
<ExpansionPanel HeaderIcon="@Icons.Custom.Brands.GitHub" HeaderText="@T("Community & Code")">
|
||||||
<MudList T="string" Class="mb-1">
|
<MudList T="string" Class="mb-1">
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Home" Target="_blank" Href="http://mindworkai.org/">
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Home" Target="_blank" Href="https://mindworkai.org/">
|
||||||
@T("Discover MindWork AI's mission and vision on our official homepage.")
|
@T("Discover MindWork AI's mission and vision on our official homepage.")
|
||||||
</MudListItem>
|
</MudListItem>
|
||||||
<MudListItem T="string" Icon="@Icons.Custom.Brands.GitHub" Target="_blank" Href="https://github.com/MindWorkAI/AI-Studio">
|
<MudListItem T="string" Icon="@Icons.Custom.Brands.GitHub" Target="_blank" Href="https://github.com/MindWorkAI/AI-Studio">
|
||||||
@ -167,14 +240,14 @@
|
|||||||
@T("Startup log file")
|
@T("Startup log file")
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudList T="string" Class="mb-3">
|
<MudList T="string" Class="mb-3">
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Folder" Text="@this.logPaths.LogStartupPath" OnClick="() => this.CopyStartupLogPath()"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Folder" Text="@this.logPaths.LogStartupPath" OnClick="@(() => this.CopyStartupLogPath())"/>
|
||||||
</MudList>
|
</MudList>
|
||||||
|
|
||||||
<MudText Typo="Typo.h4">
|
<MudText Typo="Typo.h4">
|
||||||
@T("Usage log file")
|
@T("Usage log file")
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudList T="string" Class="mb-3">
|
<MudList T="string" Class="mb-3">
|
||||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Folder" Text="@this.logPaths.LogAppPath" OnClick="() => this.CopyAppLogPath()"/>
|
<MudListItem T="string" Icon="@Icons.Material.Outlined.Folder" Text="@this.logPaths.LogAppPath" OnClick="@(() => this.CopyAppLogPath())"/>
|
||||||
</MudList>
|
</MudList>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
|
|
||||||
@ -194,6 +267,7 @@
|
|||||||
<ThirdPartyComponent Name="CodeBeam.MudBlazor.Extensions" Developer="Mehmet Can Karagöz & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions/blob/dev/LICENSE" RepositoryUrl="https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions" UseCase="@T("This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.")"/>
|
<ThirdPartyComponent Name="CodeBeam.MudBlazor.Extensions" Developer="Mehmet Can Karagöz & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions/blob/dev/LICENSE" RepositoryUrl="https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions" UseCase="@T("This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.")"/>
|
||||||
<ThirdPartyComponent Name="Rust" Developer="Graydon Hoare, Rust Foundation, Rust developers & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/rust-lang/rust/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/rust-lang/rust" UseCase="@T("The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.")"/>
|
<ThirdPartyComponent Name="Rust" Developer="Graydon Hoare, Rust Foundation, Rust developers & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/rust-lang/rust/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/rust-lang/rust" UseCase="@T("The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.")"/>
|
||||||
<ThirdPartyComponent Name="Tauri" Developer="Daniel Thompson-Yvetot, Lucas Nogueira, Tensor, Boscop, Serge Zaitsev, George Burton & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/tauri-apps/tauri/blob/dev/LICENSE_MIT" RepositoryUrl="https://github.com/tauri-apps/tauri" UseCase="@T("Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!")"/>
|
<ThirdPartyComponent Name="Tauri" Developer="Daniel Thompson-Yvetot, Lucas Nogueira, Tensor, Boscop, Serge Zaitsev, George Burton & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/tauri-apps/tauri/blob/dev/LICENSE_MIT" RepositoryUrl="https://github.com/tauri-apps/tauri" UseCase="@T("Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!")"/>
|
||||||
|
<ThirdPartyComponent Name="Qdrant" Developer="Andrey Vasnetsov, Tim Visée, Arnaud Gourlay, Luis Cossío, Ivan Pleshkov, Roman Titov, xzfc, JojiiOfficial & Open Source Community" LicenseName="Apache-2.0" LicenseUrl="https://github.com/qdrant/qdrant/blob/master/LICENSE" RepositoryUrl="https://github.com/qdrant/qdrant" UseCase="@T("Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG—retrieval-augmented generation—within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant.")"/>
|
||||||
<ThirdPartyComponent Name="Rocket" Developer="Sergio Benitez & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/rwf2/Rocket/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/rwf2/Rocket" UseCase="@T("We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.")"/>
|
<ThirdPartyComponent Name="Rocket" Developer="Sergio Benitez & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/rwf2/Rocket/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/rwf2/Rocket" UseCase="@T("We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.")"/>
|
||||||
<ThirdPartyComponent Name="serde" Developer="Erick Tryzelaar, David Tolnay & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/serde-rs/serde/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/serde-rs/serde" UseCase="@T("Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json.")"/>
|
<ThirdPartyComponent Name="serde" Developer="Erick Tryzelaar, David Tolnay & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/serde-rs/serde/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/serde-rs/serde" UseCase="@T("Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json.")"/>
|
||||||
<ThirdPartyComponent Name="strum_macros" Developer="Peter Glotfelty & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/Peternator7/strum/blob/master/LICENSE" RepositoryUrl="https://github.com/Peternator7/strum" UseCase="@T("This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.")"/>
|
<ThirdPartyComponent Name="strum_macros" Developer="Peter Glotfelty & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/Peternator7/strum/blob/master/LICENSE" RepositoryUrl="https://github.com/Peternator7/strum" UseCase="@T("This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.")"/>
|
||||||
@ -214,6 +288,8 @@
|
|||||||
<ThirdPartyComponent Name="PDFium" Developer="Lei Zhang, Tom Sepez, Dan Sinclair, and Foxit, Google, Chromium, Collabora, Ada, DocsCorp, Dropbox, Microsoft, and PSPDFKit Teams & Open Source Community" LicenseName="Apache-2.0" LicenseUrl="https://pdfium.googlesource.com/pdfium/+/refs/heads/main/LICENSE" RepositoryUrl="https://pdfium.googlesource.com/pdfium" UseCase="@T("This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.")"/>
|
<ThirdPartyComponent Name="PDFium" Developer="Lei Zhang, Tom Sepez, Dan Sinclair, and Foxit, Google, Chromium, Collabora, Ada, DocsCorp, Dropbox, Microsoft, and PSPDFKit Teams & Open Source Community" LicenseName="Apache-2.0" LicenseUrl="https://pdfium.googlesource.com/pdfium/+/refs/heads/main/LICENSE" RepositoryUrl="https://pdfium.googlesource.com/pdfium" UseCase="@T("This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.")"/>
|
||||||
<ThirdPartyComponent Name="pdfium-render" Developer="Alastair Carey, Dorian Rudolph & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/ajrcarey/pdfium-render/blob/master/LICENSE.md" RepositoryUrl="https://github.com/ajrcarey/pdfium-render" UseCase="@T("This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.")"/>
|
<ThirdPartyComponent Name="pdfium-render" Developer="Alastair Carey, Dorian Rudolph & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/ajrcarey/pdfium-render/blob/master/LICENSE.md" RepositoryUrl="https://github.com/ajrcarey/pdfium-render" UseCase="@T("This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.")"/>
|
||||||
<ThirdPartyComponent Name="sys-locale" Developer="1Password Team, ComplexSpaces & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/1Password/sys-locale/blob/main/LICENSE-MIT" RepositoryUrl="https://github.com/1Password/sys-locale" UseCase="@T("This library is used to determine the language of the operating system. This is necessary to set the language of the user interface.")"/>
|
<ThirdPartyComponent Name="sys-locale" Developer="1Password Team, ComplexSpaces & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/1Password/sys-locale/blob/main/LICENSE-MIT" RepositoryUrl="https://github.com/1Password/sys-locale" UseCase="@T("This library is used to determine the language of the operating system. This is necessary to set the language of the user interface.")"/>
|
||||||
|
<ThirdPartyComponent Name="sysinfo" Developer="Guillaume Gomez & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/GuillaumeGomez/sysinfo/blob/main/LICENSE" RepositoryUrl="https://github.com/GuillaumeGomez/sysinfo" UseCase="@T("This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated.")"/>
|
||||||
|
<ThirdPartyComponent Name="tempfile" Developer="Steven Allen, Ashley Mannix & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/Stebalien/tempfile/blob/master/LICENSE-MIT" RepositoryUrl="https://github.com/Stebalien/tempfile" UseCase="@T("This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant.")"/>
|
||||||
<ThirdPartyComponent Name="Lua-CSharp" Developer="Yusuke Nakada & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/nuskey8/Lua-CSharp/blob/main/LICENSE" RepositoryUrl="https://github.com/nuskey8/Lua-CSharp" UseCase="@T("We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.")" />
|
<ThirdPartyComponent Name="Lua-CSharp" Developer="Yusuke Nakada & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/nuskey8/Lua-CSharp/blob/main/LICENSE" RepositoryUrl="https://github.com/nuskey8/Lua-CSharp" UseCase="@T("We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.")" />
|
||||||
<ThirdPartyComponent Name="HtmlAgilityPack" Developer="ZZZ Projects & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE" RepositoryUrl="https://github.com/zzzprojects/html-agility-pack" UseCase="@T("We use the HtmlAgilityPack to extract content from the web. This is necessary, e.g., when you provide a URL as input for an assistant.")"/>
|
<ThirdPartyComponent Name="HtmlAgilityPack" Developer="ZZZ Projects & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE" RepositoryUrl="https://github.com/zzzprojects/html-agility-pack" UseCase="@T("We use the HtmlAgilityPack to extract content from the web. This is necessary, e.g., when you provide a URL as input for an assistant.")"/>
|
||||||
<ThirdPartyComponent Name="ReverseMarkdown" Developer="Babu Annamalai & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/mysticmind/reversemarkdown-net/blob/master/LICENSE" RepositoryUrl="https://github.com/mysticmind/reversemarkdown-net" UseCase="@T("This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.")"/>
|
<ThirdPartyComponent Name="ReverseMarkdown" Developer="Babu Annamalai & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/mysticmind/reversemarkdown-net/blob/master/LICENSE" RepositoryUrl="https://github.com/mysticmind/reversemarkdown-net" UseCase="@T("This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.")"/>
|
||||||
@ -221,7 +297,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Verified" HeaderText="License: FSL-1.1-MIT">
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Verified" HeaderText="License: FSL-1.1-MIT">
|
||||||
<MudMarkdown Value="@LICENSE" Props="Markdown.DefaultConfig"/>
|
<MudMarkdown Value="@LICENSE" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
</MudExpansionPanels>
|
</MudExpansionPanels>
|
||||||
</InnerScrolling>
|
</InnerScrolling>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ using System.Reflection;
|
|||||||
|
|
||||||
using AIStudio.Components;
|
using AIStudio.Components;
|
||||||
using AIStudio.Dialogs;
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Tools.Databases;
|
||||||
using AIStudio.Tools.Metadata;
|
using AIStudio.Tools.Metadata;
|
||||||
using AIStudio.Tools.PluginSystem;
|
using AIStudio.Tools.PluginSystem;
|
||||||
using AIStudio.Tools.Rust;
|
using AIStudio.Tools.Rust;
|
||||||
@ -26,10 +27,14 @@ public partial class Information : MSGComponentBase
|
|||||||
[Inject]
|
[Inject]
|
||||||
private ISnackbar Snackbar { get; init; } = null!;
|
private ISnackbar Snackbar { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private DatabaseClient DatabaseClient { get; init; } = null!;
|
||||||
|
|
||||||
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
|
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
|
||||||
private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute<MetaDataAttribute>()!;
|
private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute<MetaDataAttribute>()!;
|
||||||
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
|
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
|
||||||
private static readonly MetaDataLibrariesAttribute META_DATA_LIBRARIES = ASSEMBLY.GetCustomAttribute<MetaDataLibrariesAttribute>()!;
|
private static readonly MetaDataLibrariesAttribute META_DATA_LIBRARIES = ASSEMBLY.GetCustomAttribute<MetaDataLibrariesAttribute>()!;
|
||||||
|
private static readonly MetaDataDatabasesAttribute META_DATA_DATABASES = ASSEMBLY.GetCustomAttribute<MetaDataDatabasesAttribute>()!;
|
||||||
|
|
||||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(Information).Namespace, nameof(Information));
|
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(Information).Namespace, nameof(Information));
|
||||||
|
|
||||||
@ -53,6 +58,8 @@ public partial class Information : MSGComponentBase
|
|||||||
|
|
||||||
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
|
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
|
||||||
|
|
||||||
|
private string VersionDatabase => $"{T("Database version")}: {this.DatabaseClient.Name} v{META_DATA_DATABASES.DatabaseVersion}";
|
||||||
|
|
||||||
private string versionPandoc = TB("Determine Pandoc version, please wait...");
|
private string versionPandoc = TB("Determine Pandoc version, please wait...");
|
||||||
private PandocInstallation pandocInstallation;
|
private PandocInstallation pandocInstallation;
|
||||||
|
|
||||||
@ -60,7 +67,22 @@ public partial class Information : MSGComponentBase
|
|||||||
|
|
||||||
private bool showEnterpriseConfigDetails;
|
private bool showEnterpriseConfigDetails;
|
||||||
|
|
||||||
private IPluginMetadata? configPlug = PluginFactory.AvailablePlugins.FirstOrDefault(x => x.Type is PluginType.CONFIGURATION);
|
private bool showDatabaseDetails;
|
||||||
|
|
||||||
|
private List<IAvailablePlugin> configPlugins = PluginFactory.AvailablePlugins
|
||||||
|
.Where(x => x.Type is PluginType.CONFIGURATION)
|
||||||
|
.OfType<IAvailablePlugin>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
private sealed record DatabaseDisplayInfo(string Label, string Value);
|
||||||
|
|
||||||
|
private readonly List<DatabaseDisplayInfo> databaseDisplayInfo = new();
|
||||||
|
|
||||||
|
private static bool HasAnyActiveEnvironment => EnterpriseEnvironmentService.CURRENT_ENVIRONMENTS.Any(e => e.IsActive);
|
||||||
|
|
||||||
|
private bool HasAnyLoadedEnterpriseConfigurationPlugin => EnterpriseEnvironmentService.CURRENT_ENVIRONMENTS
|
||||||
|
.Where(e => e.IsActive)
|
||||||
|
.Any(env => this.FindManagedConfigurationPlugin(env.ConfigurationId) is not null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the enterprise configuration has details that can be shown/hidden.
|
/// Determines whether the enterprise configuration has details that can be shown/hidden.
|
||||||
@ -70,16 +92,16 @@ public partial class Information : MSGComponentBase
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return EnterpriseEnvironmentService.CURRENT_ENVIRONMENT.IsActive switch
|
return HasAnyActiveEnvironment switch
|
||||||
{
|
{
|
||||||
// Case 1: No enterprise config and no plugin - no details available
|
// Case 1: No enterprise config and no plugin - no details available
|
||||||
false when this.configPlug is null => false,
|
false when this.configPlugins.Count == 0 => false,
|
||||||
|
|
||||||
// Case 2: Enterprise config with plugin but no central management - has details
|
// Case 2: Enterprise config with plugin but no central management - has details
|
||||||
false => true,
|
false => true,
|
||||||
|
|
||||||
// Case 3: Enterprise config active but no plugin - has details
|
// Case 3: Enterprise config active but no plugin - has details
|
||||||
true when this.configPlug is null => true,
|
true when this.configPlugins.Count == 0 => true,
|
||||||
|
|
||||||
// Case 4: Enterprise config active with plugin - has details
|
// Case 4: Enterprise config active with plugin - has details
|
||||||
true => true
|
true => true
|
||||||
@ -96,6 +118,11 @@ public partial class Information : MSGComponentBase
|
|||||||
this.osLanguage = await this.RustService.ReadUserLanguage();
|
this.osLanguage = await this.RustService.ReadUserLanguage();
|
||||||
this.logPaths = await this.RustService.GetLogPaths();
|
this.logPaths = await this.RustService.GetLogPaths();
|
||||||
|
|
||||||
|
await foreach (var (label, value) in this.DatabaseClient.GetDisplayInfo())
|
||||||
|
{
|
||||||
|
this.databaseDisplayInfo.Add(new DatabaseDisplayInfo(label, value));
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the Pandoc version may take some time, so we start it here
|
// Determine the Pandoc version may take some time, so we start it here
|
||||||
// without waiting for the result:
|
// without waiting for the result:
|
||||||
_ = this.DeterminePandocVersion();
|
_ = this.DeterminePandocVersion();
|
||||||
@ -110,7 +137,10 @@ public partial class Information : MSGComponentBase
|
|||||||
switch (triggeredEvent)
|
switch (triggeredEvent)
|
||||||
{
|
{
|
||||||
case Event.PLUGINS_RELOADED:
|
case Event.PLUGINS_RELOADED:
|
||||||
this.configPlug = PluginFactory.AvailablePlugins.FirstOrDefault(x => x.Type is PluginType.CONFIGURATION);
|
this.configPlugins = PluginFactory.AvailablePlugins
|
||||||
|
.Where(x => x.Type is PluginType.CONFIGURATION)
|
||||||
|
.OfType<IAvailablePlugin>()
|
||||||
|
.ToList();
|
||||||
await this.InvokeAsync(this.StateHasChanged);
|
await this.InvokeAsync(this.StateHasChanged);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -171,6 +201,23 @@ public partial class Information : MSGComponentBase
|
|||||||
this.showEnterpriseConfigDetails = !this.showEnterpriseConfigDetails;
|
this.showEnterpriseConfigDetails = !this.showEnterpriseConfigDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleDatabaseDetails()
|
||||||
|
{
|
||||||
|
this.showDatabaseDetails = !this.showDatabaseDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IAvailablePlugin? FindManagedConfigurationPlugin(Guid configurationId)
|
||||||
|
{
|
||||||
|
return this.configPlugins.FirstOrDefault(plugin => plugin.ManagedConfigurationId == configurationId)
|
||||||
|
// Backward compatibility for already downloaded plugins without ManagedConfigurationId.
|
||||||
|
?? this.configPlugins.FirstOrDefault(plugin => plugin.ManagedConfigurationId is null && plugin.Id == configurationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsManagedConfigurationIdMismatch(IAvailablePlugin plugin, Guid configurationId)
|
||||||
|
{
|
||||||
|
return plugin.ManagedConfigurationId == configurationId && plugin.Id != configurationId;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CopyStartupLogPath()
|
private async Task CopyStartupLogPath()
|
||||||
{
|
{
|
||||||
await this.RustService.CopyText2Clipboard(this.Snackbar, this.logPaths.LogStartupPath);
|
await this.RustService.CopyText2Clipboard(this.Snackbar, this.logPaths.LogStartupPath);
|
||||||
|
|||||||
@ -63,13 +63,33 @@
|
|||||||
</MudStack>
|
</MudStack>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd>
|
<MudTd>
|
||||||
@if (context is { IsInternal: false, Type: not PluginType.CONFIGURATION })
|
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
|
||||||
{
|
@if (context is { IsInternal: false, Type: not PluginType.CONFIGURATION })
|
||||||
var isEnabled = this.SettingsManager.IsPluginEnabled(context);
|
{
|
||||||
<MudTooltip Text="@(isEnabled ? T("Disable plugin") : T("Enable plugin"))">
|
var isEnabled = this.SettingsManager.IsPluginEnabled(context);
|
||||||
<MudSwitch T="bool" Value="@isEnabled" ValueChanged="@(_ => this.PluginActivationStateChanged(context))"/>
|
<MudTooltip Text="@(isEnabled ? T("Disable plugin") : T("Enable plugin"))">
|
||||||
</MudTooltip>
|
<MudSwitch T="bool" Value="@isEnabled" ValueChanged="@(_ => this.PluginActivationStateChanged(context))"/>
|
||||||
}
|
</MudTooltip>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (context is { IsInternal: false } && !string.IsNullOrWhiteSpace(context.SourceURL))
|
||||||
|
{
|
||||||
|
var sourceUrl = context.SourceURL;
|
||||||
|
var isSendingMail = IsSendingMail(sourceUrl);
|
||||||
|
if(isSendingMail)
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Send a mail")">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Email" Href="@sourceUrl" Target="_blank" Size="Size.Medium"/>
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Open website")">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.OpenInBrowser" Href="@sourceUrl" Target="_blank" Size="Size.Medium"/>
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
|
|||||||
@ -50,6 +50,8 @@ public partial class Plugins : MSGComponentBase
|
|||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsSendingMail(string sourceUrl) => sourceUrl.TrimStart().StartsWith("mailto:", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
#region Overrides of MSGComponentBase
|
#region Overrides of MSGComponentBase
|
||||||
|
|
||||||
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||||
|
|||||||
@ -7,7 +7,9 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
<PreviewExperimental ApplyInnerScrollingFix="true"/>
|
<PreviewExperimental ApplyInnerScrollingFix="true"/>
|
||||||
|
|
||||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
|
<CascadingValue Value="Components.WRITER">
|
||||||
|
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
|
||||||
|
</CascadingValue>
|
||||||
<InnerScrolling>
|
<InnerScrolling>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
<MudTextField
|
<MudTextField
|
||||||
|
|||||||
@ -24,13 +24,21 @@ VERSION = "1.0.0"
|
|||||||
-- The type of the plugin:
|
-- The type of the plugin:
|
||||||
TYPE = "CONFIGURATION"
|
TYPE = "CONFIGURATION"
|
||||||
|
|
||||||
|
-- True when this plugin is deployed by an enterprise configuration server:
|
||||||
|
DEPLOYED_USING_CONFIG_SERVER = false
|
||||||
|
|
||||||
-- The authors of the plugin:
|
-- The authors of the plugin:
|
||||||
AUTHORS = {"<Company Name>"}
|
AUTHORS = {"<Company Name>"}
|
||||||
|
|
||||||
-- The support contact for the plugin:
|
-- The support contact for the plugin:
|
||||||
SUPPORT_CONTACT = "<IT Department of Company Name>"
|
SUPPORT_CONTACT = "<IT Department of Company Name>"
|
||||||
|
|
||||||
-- The source URL for the plugin:
|
-- The source URL for the plugin. Can be a HTTP(S) URL or an mailto link.
|
||||||
|
-- You may link to an internal documentation page, a Git repository, or
|
||||||
|
-- to a support or wiki page.
|
||||||
|
--
|
||||||
|
-- A mailto link could look like:
|
||||||
|
-- SOURCE_URL = "mailto:helpdesk@company.org?subject=Help"
|
||||||
SOURCE_URL = "<Any internal Git repository>"
|
SOURCE_URL = "<Any internal Git repository>"
|
||||||
|
|
||||||
-- The categories for the plugin:
|
-- The categories for the plugin:
|
||||||
@ -49,26 +57,40 @@ CONFIG = {}
|
|||||||
CONFIG["LLM_PROVIDERS"] = {}
|
CONFIG["LLM_PROVIDERS"] = {}
|
||||||
|
|
||||||
-- An example of a configuration for a self-hosted server:
|
-- An example of a configuration for a self-hosted server:
|
||||||
CONFIG["LLM_PROVIDERS"][#CONFIG["LLM_PROVIDERS"]+1] = {
|
-- CONFIG["LLM_PROVIDERS"][#CONFIG["LLM_PROVIDERS"]+1] = {
|
||||||
["Id"] = "00000000-0000-0000-0000-000000000000",
|
-- ["Id"] = "00000000-0000-0000-0000-000000000000",
|
||||||
["InstanceName"] = "<user-friendly name for the combination of server and model>",
|
-- ["InstanceName"] = "<user-friendly name for the combination of server and model>",
|
||||||
["UsedLLMProvider"] = "SELF_HOSTED",
|
-- ["UsedLLMProvider"] = "SELF_HOSTED",
|
||||||
|
--
|
||||||
-- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, and VLLM
|
-- -- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, and VLLM
|
||||||
["Host"] = "OLLAMA",
|
-- ["Host"] = "OLLAMA",
|
||||||
["Hostname"] = "<https address of the server>",
|
-- ["Hostname"] = "<https address of the server>",
|
||||||
|
--
|
||||||
-- Optional: Additional parameters for the API.
|
-- -- Optional: Additional parameters for the API.
|
||||||
-- Please refer to the documentation of the selected host for details.
|
-- -- Please refer to the documentation of the selected host for details.
|
||||||
-- Might be something like ... \"temperature\": 0.5 ... for one parameter.
|
-- -- Might be something like ... \"temperature\": 0.5 ... for one parameter.
|
||||||
-- Could be something like ... \"temperature\": 0.5, \"max_tokens\": 1000 ... for multiple parameters.
|
-- -- Could be something like ... \"temperature\": 0.5, \"max_tokens\": 1000 ... for multiple parameters.
|
||||||
-- Please do not add the enclosing curly braces {} here. Also, no trailing comma is allowed.
|
-- -- Please do not add the enclosing curly braces {} here. Also, no trailing comma is allowed.
|
||||||
["AdditionalJsonApiParameters"] = "",
|
-- ["AdditionalJsonApiParameters"] = "",
|
||||||
["Model"] = {
|
--
|
||||||
["Id"] = "<the model ID>",
|
-- -- Optional: Hugging Face inference provider. Only relevant for UsedLLMProvider = HUGGINGFACE.
|
||||||
["DisplayName"] = "<user-friendly name of the model>",
|
-- -- Allowed values are: CEREBRAS, NEBIUS_AI_STUDIO, SAMBANOVA, NOVITA, HYPERBOLIC, TOGETHER_AI, FIREWORKS, HF_INFERENCE_API
|
||||||
}
|
-- -- ["HFInferenceProvider"] = "NOVITA",
|
||||||
}
|
--
|
||||||
|
-- -- Optional: Encrypted API key for cloud providers or secured on-premise models.
|
||||||
|
-- -- The API key must be encrypted using the enterprise encryption secret.
|
||||||
|
-- -- Format: "ENC:v1:<base64-encoded encrypted data>"
|
||||||
|
-- -- The encryption secret must be configured via:
|
||||||
|
-- -- Windows Registry: HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT\config_encryption_secret
|
||||||
|
-- -- Environment variable: MINDWORK_AI_STUDIO_ENTERPRISE_CONFIG_ENCRYPTION_SECRET
|
||||||
|
-- -- You can export an encrypted API key from an existing provider using the export button in the settings.
|
||||||
|
-- -- ["APIKey"] = "ENC:v1:<base64-encoded encrypted data>",
|
||||||
|
--
|
||||||
|
-- ["Model"] = {
|
||||||
|
-- ["Id"] = "<the model ID>",
|
||||||
|
-- ["DisplayName"] = "<user-friendly name of the model>",
|
||||||
|
-- }
|
||||||
|
-- }
|
||||||
|
|
||||||
-- Transcription providers for voice-to-text functionality:
|
-- Transcription providers for voice-to-text functionality:
|
||||||
CONFIG["TRANSCRIPTION_PROVIDERS"] = {}
|
CONFIG["TRANSCRIPTION_PROVIDERS"] = {}
|
||||||
@ -82,6 +104,10 @@ CONFIG["TRANSCRIPTION_PROVIDERS"] = {}
|
|||||||
-- -- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, VLLM, and WHISPER_CPP
|
-- -- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, VLLM, and WHISPER_CPP
|
||||||
-- ["Host"] = "WHISPER_CPP",
|
-- ["Host"] = "WHISPER_CPP",
|
||||||
-- ["Hostname"] = "<https address of the server>",
|
-- ["Hostname"] = "<https address of the server>",
|
||||||
|
--
|
||||||
|
-- -- Optional: Encrypted API key (see LLM_PROVIDERS example for details)
|
||||||
|
-- -- ["APIKey"] = "ENC:v1:<base64-encoded encrypted data>",
|
||||||
|
--
|
||||||
-- ["Model"] = {
|
-- ["Model"] = {
|
||||||
-- ["Id"] = "<the model ID>",
|
-- ["Id"] = "<the model ID>",
|
||||||
-- ["DisplayName"] = "<user-friendly name of the model>",
|
-- ["DisplayName"] = "<user-friendly name of the model>",
|
||||||
@ -100,6 +126,10 @@ CONFIG["EMBEDDING_PROVIDERS"] = {}
|
|||||||
-- -- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, and VLLM
|
-- -- Allowed values for Host are: LM_STUDIO, LLAMACPP, OLLAMA, and VLLM
|
||||||
-- ["Host"] = "OLLAMA",
|
-- ["Host"] = "OLLAMA",
|
||||||
-- ["Hostname"] = "<https address of the server>",
|
-- ["Hostname"] = "<https address of the server>",
|
||||||
|
--
|
||||||
|
-- -- Optional: Encrypted API key (see LLM_PROVIDERS example for details)
|
||||||
|
-- -- ["APIKey"] = "ENC:v1:<base64-encoded encrypted data>",
|
||||||
|
--
|
||||||
-- ["Model"] = {
|
-- ["Model"] = {
|
||||||
-- ["Id"] = "<the model ID, e.g., nomic-embed-text>",
|
-- ["Id"] = "<the model ID, e.g., nomic-embed-text>",
|
||||||
-- ["DisplayName"] = "<user-friendly name of the model>",
|
-- ["DisplayName"] = "<user-friendly name of the model>",
|
||||||
@ -120,6 +150,10 @@ CONFIG["SETTINGS"] = {}
|
|||||||
-- Allowed values are: true, false
|
-- Allowed values are: true, false
|
||||||
-- CONFIG["SETTINGS"]["DataApp.AllowUserToAddProvider"] = false
|
-- CONFIG["SETTINGS"]["DataApp.AllowUserToAddProvider"] = false
|
||||||
|
|
||||||
|
-- Configure whether administration settings are visible in the UI:
|
||||||
|
-- Allowed values are: true, false
|
||||||
|
-- CONFIG["SETTINGS"]["DataApp.ShowAdminSettings"] = true
|
||||||
|
|
||||||
-- Configure the visibility of preview features:
|
-- Configure the visibility of preview features:
|
||||||
-- Allowed values are: NONE, RELEASE_CANDIDATE, BETA, ALPHA, PROTOTYPE, EXPERIMENTAL
|
-- Allowed values are: NONE, RELEASE_CANDIDATE, BETA, ALPHA, PROTOTYPE, EXPERIMENTAL
|
||||||
-- Please note:
|
-- Please note:
|
||||||
@ -132,6 +166,11 @@ CONFIG["SETTINGS"] = {}
|
|||||||
-- Examples are PRE_WRITER_MODE_2024, PRE_RAG_2024, PRE_DOCUMENT_ANALYSIS_2025.
|
-- Examples are PRE_WRITER_MODE_2024, PRE_RAG_2024, PRE_DOCUMENT_ANALYSIS_2025.
|
||||||
-- CONFIG["SETTINGS"]["DataApp.EnabledPreviewFeatures"] = { "PRE_RAG_2024", "PRE_DOCUMENT_ANALYSIS_2025" }
|
-- CONFIG["SETTINGS"]["DataApp.EnabledPreviewFeatures"] = { "PRE_RAG_2024", "PRE_DOCUMENT_ANALYSIS_2025" }
|
||||||
|
|
||||||
|
-- Configure the preselected provider.
|
||||||
|
-- It must be one of the provider IDs defined in CONFIG["LLM_PROVIDERS"].
|
||||||
|
-- Please note: using an empty string ("") will lock the preselected provider selection, even though no valid preselected provider is found.
|
||||||
|
-- CONFIG["SETTINGS"]["DataApp.PreselectedProvider"] = "00000000-0000-0000-0000-000000000000"
|
||||||
|
|
||||||
-- Configure the preselected profile.
|
-- Configure the preselected profile.
|
||||||
-- It must be one of the profile IDs defined in CONFIG["PROFILES"].
|
-- It must be one of the profile IDs defined in CONFIG["PROFILES"].
|
||||||
-- Please note: using an empty string ("") will lock the preselected profile selection, even though no valid preselected profile is found.
|
-- Please note: using an empty string ("") will lock the preselected profile selection, even though no valid preselected profile is found.
|
||||||
@ -167,60 +206,97 @@ CONFIG["SETTINGS"] = {}
|
|||||||
CONFIG["CHAT_TEMPLATES"] = {}
|
CONFIG["CHAT_TEMPLATES"] = {}
|
||||||
|
|
||||||
-- A simple example chat template:
|
-- A simple example chat template:
|
||||||
CONFIG["CHAT_TEMPLATES"][#CONFIG["CHAT_TEMPLATES"]+1] = {
|
-- CONFIG["CHAT_TEMPLATES"][#CONFIG["CHAT_TEMPLATES"]+1] = {
|
||||||
["Id"] = "00000000-0000-0000-0000-000000000000",
|
-- ["Id"] = "00000000-0000-0000-0000-000000000000",
|
||||||
["Name"] = "<user-friendly name of the chat template>",
|
-- ["Name"] = "<user-friendly name of the chat template>",
|
||||||
["SystemPrompt"] = "You are <Company Name>'s helpful AI assistant for <Department Name>. Your task is ...",
|
-- ["SystemPrompt"] = "You are <Company Name>'s helpful AI assistant for <Department Name>. Your task is ...",
|
||||||
["PredefinedUserPrompt"] = "Please help me with ...",
|
-- ["PredefinedUserPrompt"] = "Please help me with ...",
|
||||||
["AllowProfileUsage"] = true,
|
-- ["AllowProfileUsage"] = true,
|
||||||
["ExampleConversation"] = {
|
-- ["ExampleConversation"] = {
|
||||||
{
|
-- {
|
||||||
-- Allowed values are: USER, AI, SYSTEM
|
-- -- Allowed values are: USER, AI, SYSTEM
|
||||||
["Role"] = "USER",
|
-- ["Role"] = "USER",
|
||||||
["Content"] = "Hello! Can you help me with a quick task?"
|
-- ["Content"] = "Hello! Can you help me with a quick task?"
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
-- Allowed values are: USER, AI, SYSTEM
|
-- -- Allowed values are: USER, AI, SYSTEM
|
||||||
["Role"] = "AI",
|
-- ["Role"] = "AI",
|
||||||
["Content"] = "Of course. What do you need?"
|
-- ["Content"] = "Of course. What do you need?"
|
||||||
}
|
-- }
|
||||||
}
|
-- }
|
||||||
}
|
-- }
|
||||||
|
|
||||||
-- An example chat template with file attachments:
|
-- An example chat template with file attachments:
|
||||||
-- This template automatically attaches specified files when the user selects it.
|
-- This template automatically attaches specified files when the user selects it.
|
||||||
CONFIG["CHAT_TEMPLATES"][#CONFIG["CHAT_TEMPLATES"]+1] = {
|
-- CONFIG["CHAT_TEMPLATES"][#CONFIG["CHAT_TEMPLATES"]+1] = {
|
||||||
["Id"] = "00000000-0000-0000-0000-000000000001",
|
-- ["Id"] = "00000000-0000-0000-0000-000000000001",
|
||||||
["Name"] = "Document Analysis Template",
|
-- ["Name"] = "Document Analysis Template",
|
||||||
["SystemPrompt"] = "You are an expert document analyst. Please analyze the attached documents and provide insights.",
|
-- ["SystemPrompt"] = "You are an expert document analyst. Please analyze the attached documents and provide insights.",
|
||||||
["PredefinedUserPrompt"] = "Please analyze the attached company guidelines and summarize the key points.",
|
-- ["PredefinedUserPrompt"] = "Please analyze the attached company guidelines and summarize the key points.",
|
||||||
["AllowProfileUsage"] = true,
|
-- ["AllowProfileUsage"] = true,
|
||||||
-- Optional: Pre-attach files that will be automatically included when using this template.
|
-- -- Optional: Pre-attach files that will be automatically included when using this template.
|
||||||
-- These files will be loaded when the user selects this chat template.
|
-- -- These files will be loaded when the user selects this chat template.
|
||||||
-- Note: File paths must be absolute paths and accessible to all users.
|
-- -- Note: File paths must be absolute paths and accessible to all users.
|
||||||
["FileAttachments"] = {
|
-- ["FileAttachments"] = {
|
||||||
"G:\\Company\\Documents\\Guidelines.pdf",
|
-- "G:\\Company\\Documents\\Guidelines.pdf",
|
||||||
"G:\\Company\\Documents\\CompanyPolicies.docx"
|
-- "G:\\Company\\Documents\\CompanyPolicies.docx"
|
||||||
},
|
-- },
|
||||||
["ExampleConversation"] = {
|
-- ["ExampleConversation"] = {
|
||||||
{
|
-- {
|
||||||
["Role"] = "USER",
|
-- ["Role"] = "USER",
|
||||||
["Content"] = "I have attached the company documents for analysis."
|
-- ["Content"] = "I have attached the company documents for analysis."
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
["Role"] = "AI",
|
-- ["Role"] = "AI",
|
||||||
["Content"] = "Thank you. I'll analyze the documents and provide a comprehensive summary."
|
-- ["Content"] = "Thank you. I'll analyze the documents and provide a comprehensive summary."
|
||||||
}
|
-- }
|
||||||
}
|
-- }
|
||||||
}
|
-- }
|
||||||
|
|
||||||
|
-- Document analysis policies for this configuration:
|
||||||
|
CONFIG["DOCUMENT_ANALYSIS_POLICIES"] = {}
|
||||||
|
|
||||||
|
-- An example document analysis policy:
|
||||||
|
-- CONFIG["DOCUMENT_ANALYSIS_POLICIES"][#CONFIG["DOCUMENT_ANALYSIS_POLICIES"]+1] = {
|
||||||
|
-- ["Id"] = "00000000-0000-0000-0000-000000000000",
|
||||||
|
-- ["PolicyName"] = "Compliance Summary Policy",
|
||||||
|
-- ["PolicyDescription"] = "Summarizes compliance-relevant clauses, obligations, and deadlines found in provided documents.",
|
||||||
|
--
|
||||||
|
-- ["AnalysisRules"] = [===[
|
||||||
|
-- Focus on compliance obligations, deadlines, and required actions.
|
||||||
|
-- Ignore marketing content and high-level summaries.
|
||||||
|
-- Flag any ambiguous or missing information.
|
||||||
|
-- ]===],
|
||||||
|
--
|
||||||
|
-- ["OutputRules"] = [===[
|
||||||
|
-- Provide a Markdown report with headings for Obligations, Deadlines,
|
||||||
|
-- and Open Questions.
|
||||||
|
-- ]===],
|
||||||
|
--
|
||||||
|
-- -- Optional: minimum provider confidence required for this policy.
|
||||||
|
-- -- Allowed values are: NONE, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
||||||
|
-- ["MinimumProviderConfidence"] = "MEDIUM",
|
||||||
|
--
|
||||||
|
-- -- Optional: preselect a provider or profile by ID.
|
||||||
|
-- -- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
|
||||||
|
-- ["PreselectedProvider"] = "00000000-0000-0000-0000-000000000000",
|
||||||
|
-- ["PreselectedProfile"] = "00000000-0000-0000-0000-000000000000",
|
||||||
|
--
|
||||||
|
-- -- Optional: hide the policy definition section in the UI.
|
||||||
|
-- -- When set to true, users will only see the document selection interface
|
||||||
|
-- -- and cannot view or modify the policy settings.
|
||||||
|
-- -- This is useful for enterprise configurations where policy details should remain hidden.
|
||||||
|
-- -- Allowed values are: true, false (default: false)
|
||||||
|
-- ["HidePolicyDefinition"] = false
|
||||||
|
-- }
|
||||||
|
|
||||||
-- Profiles for this configuration:
|
-- Profiles for this configuration:
|
||||||
CONFIG["PROFILES"] = {}
|
CONFIG["PROFILES"] = {}
|
||||||
|
|
||||||
-- A simple profile template:
|
-- A simple profile template:
|
||||||
CONFIG["PROFILES"][#CONFIG["PROFILES"]+1] = {
|
-- CONFIG["PROFILES"][#CONFIG["PROFILES"]+1] = {
|
||||||
["Id"] = "00000000-0000-0000-0000-000000000000",
|
-- ["Id"] = "00000000-0000-0000-0000-000000000000",
|
||||||
["Name"] = "<user-friendly name of the profile>",
|
-- ["Name"] = "<user-friendly name of the profile>",
|
||||||
["NeedToKnow"] = "I like to cook in my free time. My favorite meal is ...",
|
-- ["NeedToKnow"] = "I like to cook in my free time. My favorite meal is ...",
|
||||||
["Actions"] = "Please always ensure the portion size is ..."
|
-- ["Actions"] = "Please always ensure the portion size is ..."
|
||||||
}
|
-- }
|
||||||
|
|||||||
@ -399,9 +399,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Bitte geben Sie eine Beschreibung Ihrer Analyseregeln an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Dokumente analysiert werden sollen."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Bitte geben Sie eine Beschreibung Ihrer Analyseregeln an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Dokumente analysiert werden sollen."
|
||||||
|
|
||||||
-- Not implemented yet.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Noch nicht implementiert."
|
|
||||||
|
|
||||||
-- Yes, protect this policy
|
-- Yes, protect this policy
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Ja, dieses Regelwerk schützen"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Ja, dieses Regelwerk schützen"
|
||||||
|
|
||||||
@ -411,9 +408,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Bitte geben Sie eine Beschreibung für Ihr Regelwerk an. Diese Beschreibung wird verwendet, um Benutzer über den Zweck Ihres Regelwerks zur Dokumentenanalyse zu informieren."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Bitte geben Sie eine Beschreibung für Ihr Regelwerk an. Diese Beschreibung wird verwendet, um Benutzer über den Zweck Ihres Regelwerks zur Dokumentenanalyse zu informieren."
|
||||||
|
|
||||||
|
-- Hide the policy definition when distributed via configuration plugin?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1875622568"] = "Die Definition des Regelwerks ausblenden, wenn diese über ein Konfigurations-Plugin verteilt wird?"
|
||||||
|
|
||||||
-- Common settings
|
-- Common settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Allgemeine Einstellungen"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Allgemeine Einstellungen"
|
||||||
|
|
||||||
|
-- Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1984494439"] = "Hinweis: Diese Einstellung wird nur wirksam, wenn dieses Regelwerk exportiert und über ein Konfigurations-Plugin an andere Nutzer verteilt wird. Wenn sie aktiviert ist, sehen Nutzer nur die Oberfläche zur Dokumentauswahl und können die Details des Regelwerks weder anzeigen noch ändern. Diese Einstellung wirkt sich NICHT auf Ihre lokale Ansicht aus – Sie sehen bei von Ihnen erstellten Regelwerken immer die Definition."
|
||||||
|
|
||||||
|
-- This policy is managed by your organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2035084381"] = "Dieses Regelwerk wird von Ihrer Organisation verwaltet."
|
||||||
|
|
||||||
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "Der Assistent für Dokumentenanalyse hilft Ihnen dabei, Informationen aus Dokumenten basierend auf vordefinierten Regelwerken zu analysieren und zu extrahieren. Sie können Regelwerke für die Dokumentenanalyse erstellen, bearbeiten und verwalten, die festlegen, wie Dokumente verarbeitet werden und welche Informationen extrahiert werden sollen. Einige Regelwerke könnten durch Ihre Organisation geschützt sein und können nicht geändert oder gelöscht werden."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "Der Assistent für Dokumentenanalyse hilft Ihnen dabei, Informationen aus Dokumenten basierend auf vordefinierten Regelwerken zu analysieren und zu extrahieren. Sie können Regelwerke für die Dokumentenanalyse erstellen, bearbeiten und verwalten, die festlegen, wie Dokumente verarbeitet werden und welche Informationen extrahiert werden sollen. Einige Regelwerke könnten durch Ihre Organisation geschützt sein und können nicht geändert oder gelöscht werden."
|
||||||
|
|
||||||
@ -453,6 +459,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy name
|
-- Policy name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Name des Regelwerks"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Name des Regelwerks"
|
||||||
|
|
||||||
|
-- No policy is selected. Please select a policy to export.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2929693091"] = "Es ist kein Regelwerk ausgewählt. Bitte wählen Sie ein Regelwerk zum Exportieren aus."
|
||||||
|
|
||||||
-- Policy Description
|
-- Policy Description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Beschreibung des Regelwerks"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Beschreibung des Regelwerks"
|
||||||
|
|
||||||
@ -468,6 +477,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy {0}
|
-- Policy {0}
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Regelwerk {0}"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Regelwerk {0}"
|
||||||
|
|
||||||
|
-- No, show the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3166091879"] = "Nein, zeige die Definition des Regelwerks"
|
||||||
|
|
||||||
-- The description of your policy must be between 32 and 512 characters long.
|
-- The description of your policy must be between 32 and 512 characters long.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "Die Beschreibung des Regelwerks muss zwischen 32 und 512 Zeichen lang sein."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "Die Beschreibung des Regelwerks muss zwischen 32 und 512 Zeichen lang sein."
|
||||||
|
|
||||||
@ -510,6 +522,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "Nachdem die KI alle Dokumente verarbeitet hat, benötigt sie Ihre Anweisungen, wie das Ergebnis formatiert werden soll. Möchten Sie eine strukturierte Liste mit Schlüsselwörtern oder einen fließenden Text? Soll die Ausgabe Emojis enthalten oder in formeller Geschäftssprache verfasst sein? Alle diese Präferenzen können Sie in den Ausgaberegeln festlegen. Dort können Sie auch eine gewünschte Struktur vordefinieren – zum Beispiel durch Verwendung von Markdown-Formatierung, um Überschriften, Absätze oder Aufzählungspunkte zu definieren."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "Nachdem die KI alle Dokumente verarbeitet hat, benötigt sie Ihre Anweisungen, wie das Ergebnis formatiert werden soll. Möchten Sie eine strukturierte Liste mit Schlüsselwörtern oder einen fließenden Text? Soll die Ausgabe Emojis enthalten oder in formeller Geschäftssprache verfasst sein? Alle diese Präferenzen können Sie in den Ausgaberegeln festlegen. Dort können Sie auch eine gewünschte Struktur vordefinieren – zum Beispiel durch Verwendung von Markdown-Formatierung, um Überschriften, Absätze oder Aufzählungspunkte zu definieren."
|
||||||
|
|
||||||
|
-- The selected policy contains invalid data. Please fix the issues before exporting the policy.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T736334861"] = "Das ausgewählte Regelwerk enthält ungültige Daten. Bitte beheben Sie die Probleme, bevor Sie das Regelwerk exportieren."
|
||||||
|
|
||||||
-- Policy description
|
-- Policy description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Beschreibung des Regelwerks"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Beschreibung des Regelwerks"
|
||||||
|
|
||||||
@ -519,6 +534,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Hier haben Sie die Möglichkeit, verschiedene Regelwerke für unterschiedliche Dokumentenanalysen zu speichern und zwischen ihnen zu wechseln."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Hier haben Sie die Möglichkeit, verschiedene Regelwerke für unterschiedliche Dokumentenanalysen zu speichern und zwischen ihnen zu wechseln."
|
||||||
|
|
||||||
|
-- Yes, hide the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T940701960"] = "Ja, die Definition des Regelwerks ausblenden"
|
||||||
|
|
||||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Geben Sie eine Liste von Stichpunkten sowie einige Basisinformationen für eine E-Mail ein. Der Assistent erstellt anschließend eine E-Mail auf Grundlage ihrer Angaben."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Geben Sie eine Liste von Stichpunkten sowie einige Basisinformationen für eine E-Mail ein. Der Assistent erstellt anschließend eine E-Mail auf Grundlage ihrer Angaben."
|
||||||
|
|
||||||
@ -1780,7 +1798,7 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "
|
|||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Pandoc installieren"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Pandoc installieren"
|
||||||
|
|
||||||
-- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications.
|
-- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Da mein Arbeitgeber sowohl Windows als auch Linux am Arbeitsplatz nutzt, wollte ich eine plattformübergreifende Lösung, die nahtlos auf allen wichtigen Betriebssystemen, einschließlich macOS, funktioniert. Außerdem wollte ich zeigen, dass es möglich ist, moderne, effiziente und plattformübergreifende Anwendungen zu erstellen, ohne auf Software-Ballast, wie z.B. das Electron-Framework, zurückzugreifen. Die Kombination aus .NET und Rust mit Tauri hat sich dabei als hervorragender Technologiestapel für den Bau solch robuster Anwendungen erwiesen."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Da mein Arbeitgeber sowohl Windows als auch Linux am Arbeitsplatz nutzt, wollte ich eine plattformübergreifende Lösung, die nahtlos auf allen wichtigen Betriebssystemen, einschließlich macOS, funktioniert. Außerdem wollte ich zeigen, dass es möglich ist, moderne, effiziente und plattformübergreifende Anwendungen zu erstellen, ohne auf Software-Ballast, wie z.B. das Electron-Framework, zurückzugreifen. Die Kombination aus .NET und Rust mit Tauri hat sich dabei als hervorragender Technologie-Stack für den Bau solch robuster Anwendungen erwiesen."
|
||||||
|
|
||||||
-- Limitations of Existing Solutions
|
-- Limitations of Existing Solutions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Einschränkungen bestehender Lösungen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Einschränkungen bestehender Lösungen"
|
||||||
@ -1788,21 +1806,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Einschränku
|
|||||||
-- Personal Needs and Limitations of Web Services
|
-- Personal Needs and Limitations of Web Services
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Persönliche Bedürfnisse und Einschränkungen von Webdiensten"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Persönliche Bedürfnisse und Einschränkungen von Webdiensten"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1986314327"] = "Demokratisierung von KI"
|
||||||
|
|
||||||
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "Während ich nach passenden Lösungen suchte, stieß ich auf eine Desktop-Anwendung namens Anything LLM. Leider konnte sie meine spezifischen Anforderungen nicht erfüllen und entsprach auch nicht dem Benutzeroberflächendesign, das ich mir vorgestellt hatte. Für macOS gab es zwar mehrere Apps, die meiner Vorstellung ähnelten, aber sie waren allesamt kostenpflichtige Lösungen mit unklarer Herkunft. Die Identität der Entwickler und die Ursprünge dieser Apps waren nicht ersichtlich, was erhebliche Sicherheitsbedenken hervorrief. Berichte von Nutzern über gestohlene API-Schlüssel und unerwünschte Abbuchungen verstärkten meine Bedenken zusätzlich."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "Während ich nach passenden Lösungen suchte, stieß ich auf eine Desktop-Anwendung namens Anything LLM. Leider konnte sie meine spezifischen Anforderungen nicht erfüllen und entsprach auch nicht dem Benutzeroberflächendesign, das ich mir vorgestellt hatte. Für macOS gab es zwar mehrere Apps, die meiner Vorstellung ähnelten, aber sie waren allesamt kostenpflichtige Lösungen mit unklarer Herkunft. Die Identität der Entwickler und die Ursprünge dieser Apps waren nicht ersichtlich, was erhebliche Sicherheitsbedenken hervorrief. Berichte von Nutzern über gestohlene API-Schlüssel und unerwünschte Abbuchungen verstärkten meine Bedenken zusätzlich."
|
||||||
|
|
||||||
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time.
|
-- We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3569462457"] = "Hallo, mein Name ist Thorsten Sommer und ich bin der ursprüngliche Entwickler von MindWork AI Studio. Die Motivation zur Entwicklung dieser App entstand aus mehreren wichtigen Bedürfnissen und Beobachtungen, die ich im Laufe der Zeit gemacht habe."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3672974243"] = "Wir möchten auch zur Demokratisierung von KI beitragen. MindWork AI Studio läuft selbst auf kostengünstiger Hardware, einschließlich Computern für rund 100 € wie dem Raspberry Pi. Dadurch sind die App und ihr voller Funktionsumfang auch für Menschen und Familien mit begrenztem Budget zugänglich. Für Ihre ersten Schritte können Sie mit lokalen LLMs beginnen oder günstige Cloud-Modelle nutzen. MindWork AI Studio selbst ist kostenlos erhältlich."
|
||||||
|
|
||||||
-- Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3622193740"] = "Mit MindWork AI Studio möchte ich ein sicheres, flexibles und benutzerfreundliches Werkzeug bereitstellen, das für ein breites Publikum geeignet ist, ohne Kompromisse bei Funktionalität oder Design einzugehen. Diese App ist das Ergebnis meines Wunsches, persönliche Anforderungen zu erfüllen, bestehende Lücken auf dem Markt zu schließen und innovative Entwicklungsmethoden zu präsentieren."
|
|
||||||
|
|
||||||
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Sich auf Webdienste wie ChatGPT zu verlassen, war für mich keine nachhaltige Lösung. Ich brauchte eine KI, die auch direkt auf Dateien auf meinem Gerät zugreifen kann – eine Funktion, die Webdienste aus Sicherheits- und Datenschutzgründen grundsätzlich nicht bieten. Zwar hätte ich mir eine eigene Lösung in Python programmieren können, aber das wäre für den Alltag zu umständlich gewesen. Noch wichtiger war mir, eine Lösung zu entwickeln, die jeder nutzen kann, ganz ohne Programmierkenntnisse."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Sich auf Webdienste wie ChatGPT zu verlassen, war für mich keine nachhaltige Lösung. Ich brauchte eine KI, die auch direkt auf Dateien auf meinem Gerät zugreifen kann – eine Funktion, die Webdienste aus Sicherheits- und Datenschutzgründen grundsätzlich nicht bieten. Zwar hätte ich mir eine eigene Lösung in Python programmieren können, aber das wäre für den Alltag zu umständlich gewesen. Noch wichtiger war mir, eine Lösung zu entwickeln, die jeder nutzen kann, ganz ohne Programmierkenntnisse."
|
||||||
|
|
||||||
|
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T483341611"] = "Hallo, mein Name ist Thorsten Sommer und ich bin der initiale Entwickler von MindWork AI Studio. Ich habe dieses Projekt auf Grundlage von Bedürfnissen und Beobachtungen gestartet, die ich im Laufe der Zeit gemacht habe. Heute haben wir ein Kernteam von Entwicklern und Unterstützung aus der Open-Source-Community."
|
||||||
|
|
||||||
-- Cross-Platform and Modern Development
|
-- Cross-Platform and Modern Development
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Plattformübergreifende und moderne Entwicklung"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Plattformübergreifende und moderne Entwicklung"
|
||||||
|
|
||||||
|
-- Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T904941692"] = "Heute verfolgt unser Team das Ziel, ein sicheres, flexibles und benutzerfreundliches Tool bereitzustellen, das eine breite Zielgruppe anspricht, ohne dabei Kompromisse bei Funktionalität oder dem Design einzugehen."
|
||||||
|
|
||||||
-- Copies the content to the clipboard
|
-- Copies the content to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Kopiert den Inhalt in die Zwischenablage"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Kopiert den Inhalt in die Zwischenablage"
|
||||||
|
|
||||||
@ -2064,12 +2088,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1898060643"]
|
|||||||
-- Select the language for the app.
|
-- Select the language for the app.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Wählen Sie die Sprache für die App aus."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Wählen Sie die Sprache für die App aus."
|
||||||
|
|
||||||
|
-- When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2013281167"] = "Wenn diese Option aktiviert ist, werden zusätzliche Optionen für die Administration angezeigt. Diese Optionen sind für IT-Mitarbeitende vorgesehen, um organisationsweite Einstellungen zu verwalten, z. B. Anbieter für eine gesamte Organisation zu konfigurieren und zu exportieren."
|
||||||
|
|
||||||
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "Der globale Tastaturkurzbefehl zum Ein- und Ausschalten der Sprachaufnahme. Dieser Kurzbefehl funktioniert systemweit, auch wenn die App nicht im Vordergrund ist."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "Der globale Tastaturkurzbefehl zum Ein- und Ausschalten der Sprachaufnahme. Dieser Kurzbefehl funktioniert systemweit, auch wenn die App nicht im Vordergrund ist."
|
||||||
|
|
||||||
-- Disable dictation and transcription
|
-- Disable dictation and transcription
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Diktieren und Transkribieren deaktivieren"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Diktieren und Transkribieren deaktivieren"
|
||||||
|
|
||||||
|
-- Enterprise Administration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2277116008"] = "Unternehmensverwaltung"
|
||||||
|
|
||||||
-- Language behavior
|
-- Language behavior
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Sprachverhalten"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Sprachverhalten"
|
||||||
|
|
||||||
@ -2079,6 +2109,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T237706157"]
|
|||||||
-- Language
|
-- Language
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Sprache"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Sprache"
|
||||||
|
|
||||||
|
-- Administration settings are visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591866808"] = "Die Optionen für die Administration sind sichtbar."
|
||||||
|
|
||||||
-- Save energy?
|
-- Save energy?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Energie sparen?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Energie sparen?"
|
||||||
|
|
||||||
@ -2088,9 +2121,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3165555978"]
|
|||||||
-- App Options
|
-- App Options
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App-Einstellungen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App-Einstellungen"
|
||||||
|
|
||||||
|
-- Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T362833"] = "Generieren Sie ein 256‑Bit‑Geheimnis für die Verschlüsselung, um API‑Schlüssel in Konfigurations-Plugins zu verschlüsseln. Stellen Sie dieses Geheimnis über Gruppenrichtlinien (Windows-Registrierung) oder über Umgebungsvariablen auf Client-Geräten bereit. Anschließend können Anbieter über die Export-Schaltflächen in den Anbieter-Einstellungen mit verschlüsselten API‑Schlüsseln exportiert werden."
|
||||||
|
|
||||||
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "Wenn aktiviert, wird gestreamter Inhalt von der KI alle drei Sekunden aktualisiert. Wenn deaktiviert, wird gestreamter Inhalt sofort aktualisiert, sobald er verfügbar ist."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "Wenn aktiviert, wird gestreamter Inhalt von der KI alle drei Sekunden aktualisiert. Wenn deaktiviert, wird gestreamter Inhalt sofort aktualisiert, sobald er verfügbar ist."
|
||||||
|
|
||||||
|
-- Show administration settings?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3694781396"] = "Optionen für die Administration anzeigen?"
|
||||||
|
|
||||||
|
-- Read the Enterprise IT documentation for details.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3705451321"] = "Lesen Sie die Enterprise-IT-Dokumentation für die Details."
|
||||||
|
|
||||||
-- Enable spellchecking?
|
-- Enable spellchecking?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Rechtschreibprüfung aktivieren?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Rechtschreibprüfung aktivieren?"
|
||||||
|
|
||||||
@ -2124,9 +2166,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T817101267"]
|
|||||||
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Möchten Sie einen Anbieter als Standard für die gesamte App festlegen? Wenn Sie einen anderen Anbieter für einen Assistenten konfigurieren, hat dieser immer Vorrang."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Möchten Sie einen Anbieter als Standard für die gesamte App festlegen? Wenn Sie einen anderen Anbieter für einen Assistenten konfigurieren, hat dieser immer Vorrang."
|
||||||
|
|
||||||
|
-- Generate an encryption secret and copy it to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T922066419"] = "Geheimnis für die Verschlüsselung generieren und in die Zwischenablage kopieren"
|
||||||
|
|
||||||
|
-- Administration settings are not visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T929143445"] = "Die Optionen für die Administration sind nicht sichtbar."
|
||||||
|
|
||||||
|
-- Embedding Result
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1387042335"] = "Einbettungsergebnis"
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Löschen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Löschen"
|
||||||
|
|
||||||
|
-- Embed text
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1644934561"] = "Text einbetten"
|
||||||
|
|
||||||
|
-- Test Embedding Provider
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1655784761"] = "Anbieter für Einbettung testen"
|
||||||
|
|
||||||
-- Add Embedding
|
-- Add Embedding
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Einbettung hinzufügen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Einbettung hinzufügen"
|
||||||
|
|
||||||
@ -2139,6 +2196,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T18253
|
|||||||
-- Add Embedding Provider
|
-- Add Embedding Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Einbettungsanbieter hinzufügen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Einbettungsanbieter hinzufügen"
|
||||||
|
|
||||||
|
-- Add text that should be embedded:
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1992646324"] = "Text zum Einbetten eingeben:"
|
||||||
|
|
||||||
|
-- Embedding Vector (one dimension per line)
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2174876961"] = "Einbettungsvektor (eine Dimension pro Zeile)"
|
||||||
|
|
||||||
-- Model
|
-- Model
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Modell"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Modell"
|
||||||
|
|
||||||
@ -2148,6 +2211,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199
|
|||||||
-- Name
|
-- Name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
||||||
|
|
||||||
|
-- No embedding was returned.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T291969"] = "Es wurde keine Einbettung zurückgegeben."
|
||||||
|
|
||||||
-- Configured Embedding Providers
|
-- Configured Embedding Providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Konfigurierte Anbieter für Einbettungen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Konfigurierte Anbieter für Einbettungen"
|
||||||
|
|
||||||
@ -2157,6 +2223,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T32512
|
|||||||
-- Edit
|
-- Edit
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Bearbeiten"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Bearbeiten"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3448155331"] = "Schließen"
|
||||||
|
|
||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Aktionen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Aktionen"
|
||||||
|
|
||||||
@ -2178,9 +2247,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T51130
|
|||||||
-- Open Dashboard
|
-- Open Dashboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Dashboard öffnen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Dashboard öffnen"
|
||||||
|
|
||||||
|
-- Test
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T805092869"] = "Testen"
|
||||||
|
|
||||||
|
-- Example text to embed
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Beispieltext zum Einbetten"
|
||||||
|
|
||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Anbieter"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Anbieter"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Konfiguration exportieren"
|
||||||
|
|
||||||
|
-- Cannot export the encrypted API key: No enterprise encryption secret is configured.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Der verschlüsselte API-Schlüssel kann nicht exportiert werden: Es ist kein Geheimnis für die Verschlüsselung konfiguriert."
|
||||||
|
|
||||||
|
-- This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T3368145670"] = "Für diesen Anbieter ist ein API-Schlüssel konfiguriert. Möchten Sie den verschlüsselten API-Schlüssel in den Export aufnehmen? Hinweis: Der Empfänger benötigt dasselbe Geheimnis für die Verschlüsselung, um den API-Schlüssel verwenden zu können."
|
||||||
|
|
||||||
|
-- Export API Key?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T4010580285"] = "API-Schlüssel exportieren?"
|
||||||
|
|
||||||
-- Show provider's confidence level?
|
-- Show provider's confidence level?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Anzeigen, wie sicher sich der Anbieter ist?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Anzeigen, wie sicher sich der Anbieter ist?"
|
||||||
|
|
||||||
@ -2286,6 +2373,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Anbieter"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Anbieter"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Konfiguration exportieren"
|
||||||
|
|
||||||
-- No transcription provider configured yet.
|
-- No transcription provider configured yet.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "Es ist bisher kein Anbieter für Transkriptionen konfiguriert."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "Es ist bisher kein Anbieter für Transkriptionen konfiguriert."
|
||||||
|
|
||||||
@ -2340,6 +2430,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Anbieter"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Anbieter"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Konfiguration exportieren"
|
||||||
|
|
||||||
-- Copy {0} to the clipboard
|
-- Copy {0} to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Kopiere {0} in die Zwischenablage"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Kopiere {0} in die Zwischenablage"
|
||||||
|
|
||||||
@ -2376,9 +2469,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1648606751"] = "Sie können ihre
|
|||||||
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "Bald wird es möglich sein, Daten aus dem Firmennetzwerk über eine festgelegte Schnittstelle (External Retrieval Interface, kurz ERI) zu integrieren. Dafür wird voraussichtlich Entwicklungsaufwand seitens der jeweiligen Organisation nötig sein."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "Bald wird es möglich sein, Daten aus dem Firmennetzwerk über eine festgelegte Schnittstelle (External Retrieval Interface, kurz ERI) zu integrieren. Dafür wird voraussichtlich Entwicklungsaufwand seitens der jeweiligen Organisation nötig sein."
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1986314327"] = "Demokratisierung von KI"
|
||||||
|
|
||||||
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Was auch immer ihr Beruf oder ihre Aufgabe ist, MindWork AI Studio möchte ihre Bedürfnisse erfüllen: Egal, ob Sie Projektmanager, Wissenschaftler, Künstler, Autor, Softwareentwickler oder Spieleentwickler sind."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Was auch immer ihr Beruf oder ihre Aufgabe ist, MindWork AI Studio möchte ihre Bedürfnisse erfüllen: Egal, ob Sie Projektmanager, Wissenschaftler, Künstler, Autor, Softwareentwickler oder Spieleentwickler sind."
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2201645589"] = "Wir möchten zur Demokratisierung von KI beitragen. MindWork AI Studio läuft sogar auf kostengünstiger Hardware, einschließlich Computern für etwa 100 € wie dem Raspberry Pi. Dadurch werden die App und ihr voller Funktionsumfang auch für Menschen und Familien mit begrenztem Budget zugänglich. Sie können mit lokalen LLMs starten oder günstige Cloud-Modelle nutzen. MindWork AI Studio selbst ist kostenlos erhältlich."
|
||||||
|
|
||||||
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "Sie können ihre E-Mail-Postfächer mit AI Studio verbinden. Die KI liest ihre E-Mails und benachrichtigt Sie über wichtige Ereignisse. Außerdem haben Sie in ihren Chats Zugriff auf das Wissen aus ihren E-Mails."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "Sie können ihre E-Mail-Postfächer mit AI Studio verbinden. Die KI liest ihre E-Mails und benachrichtigt Sie über wichtige Ereignisse. Außerdem haben Sie in ihren Chats Zugriff auf das Wissen aus ihren E-Mails."
|
||||||
|
|
||||||
@ -2460,8 +2559,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Möchten Sie
|
|||||||
-- Move chat
|
-- Move chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Chat verschieben"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Chat verschieben"
|
||||||
|
|
||||||
-- Unnamed workspace
|
-- Loading chats...
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1307384014"] = "Unbenannter Arbeitsbereich"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1364857726"] = "Chats werden geladen..."
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Löschen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Löschen"
|
||||||
@ -2517,9 +2616,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T323280982"] = "Bitte geben S
|
|||||||
-- Please enter a workspace name.
|
-- Please enter a workspace name.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Bitte geben Sie einen Namen für diesen Arbeitsbereich ein."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Bitte geben Sie einen Namen für diesen Arbeitsbereich ein."
|
||||||
|
|
||||||
-- Unnamed chat
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3310482275"] = "Unbenannter Chat"
|
|
||||||
|
|
||||||
-- Rename
|
-- Rename
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Umbenennen"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Umbenennen"
|
||||||
|
|
||||||
@ -3258,6 +3354,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Anb
|
|||||||
-- Cancel
|
-- Cancel
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Abbrechen"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Abbrechen"
|
||||||
|
|
||||||
|
-- Embedding Vector
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T1173984541"] = "Einbettungsvektor"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T3448155331"] = "Schließen"
|
||||||
|
|
||||||
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Leider ist die GPL-Lizenz von Pandoc nicht mit der Lizenz von AI Studio kompatibel. Software unter der GPL-Lizenz ist jedoch kostenlos und frei nutzbar. Sie müssen die GPL-Lizenz akzeptieren, bevor wir Pandoc automatisch für Sie herunterladen und installieren können (empfohlen). Alternativ können Sie Pandoc auch selbst herunterladen – entweder mit den untenstehenden Anweisungen oder auf anderem Weg, zum Beispiel über den Paketmanager Ihres Betriebssystems."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Leider ist die GPL-Lizenz von Pandoc nicht mit der Lizenz von AI Studio kompatibel. Software unter der GPL-Lizenz ist jedoch kostenlos und frei nutzbar. Sie müssen die GPL-Lizenz akzeptieren, bevor wir Pandoc automatisch für Sie herunterladen und installieren können (empfohlen). Alternativ können Sie Pandoc auch selbst herunterladen – entweder mit den untenstehenden Anweisungen oder auf anderem Weg, zum Beispiel über den Paketmanager Ihres Betriebssystems."
|
||||||
|
|
||||||
@ -4029,33 +4131,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
|||||||
-- Local Directory
|
-- Local Directory
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Lokaler Ordner"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Lokaler Ordner"
|
||||||
|
|
||||||
-- Assistant: Document Analysis
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistent: Dokumentenanalyse"
|
|
||||||
|
|
||||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Die meisten Optionen für die Analyse von Dokumenten können im Assistenten angepasst und direkt gespeichert werden. Dafür verfügt der Assistent über eine automatische Speicherfunktion."
|
|
||||||
|
|
||||||
-- Would you like to preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Möchten Sie eines Ihrer Profile vorab auswählen?"
|
|
||||||
|
|
||||||
-- Preselect document analysis options?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Dokumentenanalyse-Optionen vorab auswählen?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some document analysis options.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "Wenn aktiviert, können Sie einige Dokumentanalyse-Optionen vorab auswählen."
|
|
||||||
|
|
||||||
-- No document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "Keine Dokumentenanalyse-Optionen sind vorausgewählt."
|
|
||||||
|
|
||||||
-- Close
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Schließen"
|
|
||||||
|
|
||||||
-- Document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Dokumentenanalyse-Optionen sind vorausgewählt."
|
|
||||||
|
|
||||||
-- Preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Eines Ihrer Profile vorauswählen?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some ERI server options.
|
-- When enabled, you can preselect some ERI server options.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "Wenn aktiviert, können Sie einige ERI-Serveroptionen vorauswählen."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "Wenn aktiviert, können Sie einige ERI-Serveroptionen vorauswählen."
|
||||||
|
|
||||||
@ -4905,6 +4980,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T878695986"] = "Lerne jeden Tag ei
|
|||||||
-- Localization
|
-- Localization
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Lokalisierung"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Lokalisierung"
|
||||||
|
|
||||||
|
-- Reload your workspaces
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T194629703"] = "Arbeitsbereiche neu laden"
|
||||||
|
|
||||||
-- Hide your workspaces
|
-- Hide your workspaces
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Arbeitsbereiche ausblenden"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Arbeitsbereiche ausblenden"
|
||||||
|
|
||||||
@ -4950,6 +5028,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T149711988"] = "Sie zahlen nur für das,
|
|||||||
-- Assistants
|
-- Assistants
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistenten"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistenten"
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1628689293"] = "Wir möchten zur Demokratisierung von KI beitragen. MindWork AI Studio läuft sogar auf kostengünstiger Hardware, einschließlich Computern für etwa 100 € wie dem Raspberry Pi. Dadurch werden die App und ihr vollständiger Funktionsumfang auch für Menschen und Familien mit begrenztem Budget zugänglich. Sie können mit lokalen LLMs starten oder günstige Cloud-Modelle nutzen."
|
||||||
|
|
||||||
-- Unrestricted usage
|
-- Unrestricted usage
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unbeschränkte Nutzung"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unbeschränkte Nutzung"
|
||||||
|
|
||||||
@ -4959,6 +5040,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1702902297"] = "Einführung"
|
|||||||
-- Vision
|
-- Vision
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1986314327"] = "Demokratisierung von KI"
|
||||||
|
|
||||||
-- Let's get started
|
-- Let's get started
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Los geht's"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Los geht's"
|
||||||
|
|
||||||
@ -5013,18 +5097,33 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1019424746"] = "Startprotokollda
|
|||||||
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Sehen Sie sich den Quellcode von AI Studio auf GitHub an – wir freuen uns über ihre Beiträge."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Sehen Sie sich den Quellcode von AI Studio auf GitHub an – wir freuen uns über ihre Beiträge."
|
||||||
|
|
||||||
|
-- ID mismatch: the plugin ID differs from the enterprise configuration ID.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1137744461"] = "ID-Konflikt: Die Plugin-ID stimmt nicht mit der ID der Unternehmenskonfiguration überein."
|
||||||
|
|
||||||
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "Dies ist eine private AI Studio-Installation. Sie läuft ohne Unternehmenskonfiguration."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "Dies ist eine private AI Studio-Installation. Sie läuft ohne Unternehmenskonfiguration."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1282228996"] = "AI Studio läuft mit einer Unternehmenskonfiguration und einem Konfigurationsserver. Das Konfigurations-Plugin ist noch nicht verfügbar."
|
|
||||||
|
|
||||||
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "Diese Bibliothek wird verwendet, um PDF-Dateien zu lesen. Das ist zum Beispiel notwendig, um PDFs als Datenquelle für einen Chat zu nutzen."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "Diese Bibliothek wird verwendet, um PDF-Dateien zu lesen. Das ist zum Beispiel notwendig, um PDFs als Datenquelle für einen Chat zu nutzen."
|
||||||
|
|
||||||
|
-- Database version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1420062548"] = "Datenbankversion"
|
||||||
|
|
||||||
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "Diese Bibliothek wird verwendet, um die MudBlazor-Bibliothek zu erweitern. Sie stellt zusätzliche Komponenten bereit, die nicht Teil der MudBlazor-Bibliothek sind."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "Diese Bibliothek wird verwendet, um die MudBlazor-Bibliothek zu erweitern. Sie stellt zusätzliche Komponenten bereit, die nicht Teil der MudBlazor-Bibliothek sind."
|
||||||
|
|
||||||
|
-- Waiting for the configuration plugin...
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1533382393"] = "Warten auf das Konfigurations-Plugin …"
|
||||||
|
|
||||||
|
-- Encryption secret: is not configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1560776885"] = "Geheimnis für die Verschlüsselung: ist nicht konfiguriert"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1596483935"] = "AI Studio wird mit Unternehmenskonfigurationen und Konfigurationsservern betrieben. Die Konfigurations-Plugins sind aktiv."
|
||||||
|
|
||||||
|
-- Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG -— retrieval-augmented generation -— within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1619832053"] = "Qdrant ist eine Vektordatenbank und Suchmaschine für Vektoren. Wir nutzen Qdrant, um lokales RAG (Retrieval-Augmented Generation) innerhalb von AI Studio zu realisieren. Vielen Dank für den Einsatz und die großartige Arbeit, die in Qdrant gesteckt wurde und weiterhin gesteckt wird."
|
||||||
|
|
||||||
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "Wir verwenden Lua als Sprache für Plugins. Lua-CSharp ermöglicht die Kommunikation zwischen Lua-Skripten und AI Studio in beide Richtungen. Vielen Dank an Yusuke Nakada für diese großartige Bibliothek."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "Wir verwenden Lua als Sprache für Plugins. Lua-CSharp ermöglicht die Kommunikation zwischen Lua-Skripten und AI Studio in beide Richtungen. Vielen Dank an Yusuke Nakada für diese großartige Bibliothek."
|
||||||
|
|
||||||
@ -5058,9 +5157,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1915240766"] = "Um ein beliebige
|
|||||||
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "Diese Bibliothek wird verwendet, um HTML in Markdown umzuwandeln. Das ist zum Beispiel notwendig, wenn Sie eine URL als Eingabe für einen Assistenten angeben."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "Diese Bibliothek wird verwendet, um HTML in Markdown umzuwandeln. Das ist zum Beispiel notwendig, wenn Sie eine URL als Eingabe für einen Assistenten angeben."
|
||||||
|
|
||||||
|
-- Encryption secret: is configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1931141322"] = "Geheimnis für die Verschlüsselung: ist konfiguriert"
|
||||||
|
|
||||||
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "Wir verwenden Rocket zur Implementierung der Runtime-API. Dies ist notwendig, da die Runtime mit der Benutzeroberfläche (IPC) kommunizieren muss. Rocket ist ein ausgezeichnetes Framework zur Umsetzung von Web-APIs in Rust."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "Wir verwenden Rocket zur Implementierung der Runtime-API. Dies ist notwendig, da die Runtime mit der Benutzeroberfläche (IPC) kommunizieren muss. Rocket ist ein ausgezeichnetes Framework zur Umsetzung von Web-APIs in Rust."
|
||||||
|
|
||||||
|
-- Copies the following to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2029659664"] = "Kopiert Folgendes in die Zwischenablage"
|
||||||
|
|
||||||
-- Copies the server URL to the clipboard
|
-- Copies the server URL to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Kopiert die Server-URL in die Zwischenablage"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Kopiert die Server-URL in die Zwischenablage"
|
||||||
|
|
||||||
@ -5079,9 +5184,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2272122662"] = "Konfigurationsse
|
|||||||
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "Wir müssen Zufallszahlen erzeugen, z. B. um die Kommunikation zwischen der Benutzeroberfläche und der Laufzeitumgebung abzusichern. Die rand-Bibliothek eignet sich dafür hervorragend."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "Wir müssen Zufallszahlen erzeugen, z. B. um die Kommunikation zwischen der Benutzeroberfläche und der Laufzeitumgebung abzusichern. Die rand-Bibliothek eignet sich dafür hervorragend."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2280402765"] = "AI Studio läuft mit einer Unternehmenskonfiguration über ein Konfigurations-Plugin, ohne zentrale Konfigurationsverwaltung."
|
|
||||||
|
|
||||||
-- Configuration plugin ID:
|
-- Configuration plugin ID:
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Konfigurations-Plugin-ID:"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Konfigurations-Plugin-ID:"
|
||||||
|
|
||||||
@ -5106,6 +5208,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2557066213"] = "Verwendete Open-
|
|||||||
-- Build time
|
-- Build time
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build-Zeit"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build-Zeit"
|
||||||
|
|
||||||
|
-- This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2619858133"] = "Diese Bibliothek wird verwendet, um temporäre Ordner zu erstellen, in denen das Zertifikat und der private Schlüssel für die Kommunikation mit Qdrant gespeichert werden."
|
||||||
|
|
||||||
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "Dieses Crate stellt Derive-Makros für Rust-Enums bereit, die wir verwenden, um Boilerplate zu reduzieren, wenn wir String-Konvertierungen und Metadaten für Laufzeittypen implementieren. Das ist hilfreich für die Kommunikation zwischen unseren Rust- und .NET-Systemen."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "Dieses Crate stellt Derive-Makros für Rust-Enums bereit, die wir verwenden, um Boilerplate zu reduzieren, wenn wir String-Konvertierungen und Metadaten für Laufzeittypen implementieren. Das ist hilfreich für die Kommunikation zwischen unseren Rust- und .NET-Systemen."
|
||||||
|
|
||||||
@ -5142,6 +5247,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2840582448"] = "Erklärung"
|
|||||||
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "Das .NET-Backend kann nicht als Desktop-App gestartet werden. Deshalb verwende ich ein zweites Backend in Rust, das ich „Runtime“ nenne. Mit Rust als Runtime kann Tauri genutzt werden, um eine typische Desktop-App zu realisieren. Dank Rust kann diese App für Windows-, macOS- und Linux-Desktops angeboten werden. Rust ist eine großartige Sprache für die Entwicklung sicherer und leistungsstarker Software."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "Das .NET-Backend kann nicht als Desktop-App gestartet werden. Deshalb verwende ich ein zweites Backend in Rust, das ich „Runtime“ nenne. Mit Rust als Runtime kann Tauri genutzt werden, um eine typische Desktop-App zu realisieren. Dank Rust kann diese App für Windows-, macOS- und Linux-Desktops angeboten werden. Rust ist eine großartige Sprache für die Entwicklung sicherer und leistungsstarker Software."
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2924964415"] = "AI Studio wird mit Unternehmenskonfigurationen und Konfigurationsservern betrieben. Die Konfigurations-Plugins sind noch nicht verfügbar."
|
||||||
|
|
||||||
-- Changelog
|
-- Changelog
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Änderungsprotokoll"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Änderungsprotokoll"
|
||||||
|
|
||||||
@ -5175,6 +5283,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3433065373"] = "Informationen ü
|
|||||||
-- Used Rust compiler
|
-- Used Rust compiler
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Verwendeter Rust-Compiler"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Verwendeter Rust-Compiler"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3449345633"] = "AI Studio wird mit Unternehmenskonfigurationen unter Verwendung von Konfigurations-Plugins betrieben. Eine zentrale Konfigurationsverwaltung wird nicht eingesetzt."
|
||||||
|
|
||||||
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri wird verwendet, um die Blazor-Benutzeroberfläche bereitzustellen. Es ist ein großartiges Projekt, das die Erstellung von Desktop-Anwendungen mit Webtechnologien ermöglicht. Ich liebe Tauri!"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri wird verwendet, um die Blazor-Benutzeroberfläche bereitzustellen. Es ist ein großartiges Projekt, das die Erstellung von Desktop-Anwendungen mit Webtechnologien ermöglicht. Ich liebe Tauri!"
|
||||||
|
|
||||||
@ -5184,9 +5295,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3563271893"] = "Motivation"
|
|||||||
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "Diese Bibliothek wird verwendet, um Excel- und OpenDocument-Tabellendateien zu lesen. Dies ist zum Beispiel notwendig, wenn Tabellen als Datenquelle für einen Chat verwendet werden sollen."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "Diese Bibliothek wird verwendet, um Excel- und OpenDocument-Tabellendateien zu lesen. Dies ist zum Beispiel notwendig, wenn Tabellen als Datenquelle für einen Chat verwendet werden sollen."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3741877842"] = "AI Studio läuft mit einer Unternehmenskonfiguration und einem Konfigurationsserver. Das Konfigurations-Plugin ist aktiv."
|
|
||||||
|
|
||||||
-- this version does not met the requirements
|
-- this version does not met the requirements
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "diese Version erfüllt die Anforderungen nicht"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "diese Version erfüllt die Anforderungen nicht"
|
||||||
|
|
||||||
@ -5223,6 +5331,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T566998575"] = "Dies ist eine Bib
|
|||||||
-- Used .NET SDK
|
-- Used .NET SDK
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Verwendetes .NET SDK"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Verwendetes .NET SDK"
|
||||||
|
|
||||||
|
-- This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T633932150"] = "Diese Bibliothek wird verwendet, um Sidecar-Prozesse zu verwalten und sicherzustellen, dass veraltete oder Zombie-Sidecars erkannt und beendet werden."
|
||||||
|
|
||||||
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Haben Sie einen Fehler gefunden oder Probleme festgestellt? Melden Sie Ihr Anliegen hier."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Haben Sie einen Fehler gefunden oder Probleme festgestellt? Melden Sie Ihr Anliegen hier."
|
||||||
|
|
||||||
@ -5253,6 +5364,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Interne Plugins"
|
|||||||
-- Disabled Plugins
|
-- Disabled Plugins
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Deaktivierte Plugins"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Deaktivierte Plugins"
|
||||||
|
|
||||||
|
-- Send a mail
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1999487139"] = "E-Mail senden"
|
||||||
|
|
||||||
-- Enable plugin
|
-- Enable plugin
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Plugin aktivieren"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Plugin aktivieren"
|
||||||
|
|
||||||
@ -5265,6 +5379,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Aktivierte Plugins"
|
|||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Aktionen"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Aktionen"
|
||||||
|
|
||||||
|
-- Open website
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4239378936"] = "Website öffnen"
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Einstellungen"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Einstellungen"
|
||||||
|
|
||||||
@ -5781,6 +5898,21 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T3893997203"] = "
|
|||||||
-- Trust all LLM providers
|
-- Trust all LLM providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Allen LLM-Anbietern vertrauen"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Allen LLM-Anbietern vertrauen"
|
||||||
|
|
||||||
|
-- Storage size
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1230141403"] = "Speichergröße"
|
||||||
|
|
||||||
|
-- HTTP port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1717573768"] = "HTTP-Port"
|
||||||
|
|
||||||
|
-- Reported version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T3556099842"] = "Gemeldete Version"
|
||||||
|
|
||||||
|
-- gRPC port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T757840040"] = "gRPC-Port"
|
||||||
|
|
||||||
|
-- Number of collections
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T842647336"] = "Anzahl der Collections"
|
||||||
|
|
||||||
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "Die zugehörigen Daten dürfen an keinen LLM-Anbieter gesendet werden. Das bedeutet, dass diese Datenquelle momentan nicht verwendet werden kann."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "Die zugehörigen Daten dürfen an keinen LLM-Anbieter gesendet werden. Das bedeutet, dass diese Datenquelle momentan nicht verwendet werden kann."
|
||||||
|
|
||||||
@ -5970,15 +6102,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2262604281"] = "Das
|
|||||||
-- The field DESCRIPTION does not exist or is not a valid string.
|
-- The field DESCRIPTION does not exist or is not a valid string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "Das Feld DESCRIPTION existiert nicht oder ist keine gültige Zeichenkette."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "Das Feld DESCRIPTION existiert nicht oder ist keine gültige Zeichenkette."
|
||||||
|
|
||||||
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://' or 'https://'.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2320984047"] = "Das Feld SOURCE_URL ist keine gültige URL. Die URL muss mit 'http://' oder 'https://' beginnen."
|
|
||||||
|
|
||||||
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "Das Feld VERSION ist keine gültige Versionsnummer. Die Versionsnummer muss als Zeichenkette im Format major.minor.patch (X.X.X) angegeben werden."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "Das Feld VERSION ist keine gültige Versionsnummer. Die Versionsnummer muss als Zeichenkette im Format major.minor.patch (X.X.X) angegeben werden."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://', 'https://', or 'mailto:'.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2892057533"] = "Das Feld SOURCE_URL ist keine gültige URL. Die URL muss mit „http://“, „https://“ oder „mailto:“ beginnen."
|
||||||
|
|
||||||
-- The table AUTHORS is empty. At least one author must be specified.
|
-- The table AUTHORS is empty. At least one author must be specified.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "Die Tabelle AUTHORS ist leer. Es muss mindestens ein Autor angegeben werden."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "Die Tabelle AUTHORS ist leer. Es muss mindestens ein Autor angegeben werden."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. When the URL starts with 'mailto:', it must contain a valid email address as recipient.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3165663073"] = "Das Feld SOURCE_URL ist keine gültige URL. Wenn die URL mit „mailto:“ beginnt, muss sie eine gültige E-Mail-Adresse als Empfänger enthalten."
|
||||||
|
|
||||||
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "Das Feld SUPPORT_CONTACT ist leer. Der Support-Kontakt muss eine nicht-leere Zeichenkette sein."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "Das Feld SUPPORT_CONTACT ist leer. Der Support-Kontakt muss eine nicht-leere Zeichenkette sein."
|
||||||
|
|
||||||
@ -6386,3 +6521,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unbenannt
|
|||||||
|
|
||||||
-- Delete Chat
|
-- Delete Chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Chat löschen"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Chat löschen"
|
||||||
|
|
||||||
|
-- Unnamed chat
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3310482275"] = "Unbenannter Chat"
|
||||||
|
|||||||
@ -399,9 +399,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."
|
||||||
|
|
||||||
-- Not implemented yet.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet."
|
|
||||||
|
|
||||||
-- Yes, protect this policy
|
-- Yes, protect this policy
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
||||||
|
|
||||||
@ -411,9 +408,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
||||||
|
|
||||||
|
-- Hide the policy definition when distributed via configuration plugin?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1875622568"] = "Hide the policy definition when distributed via configuration plugin?"
|
||||||
|
|
||||||
-- Common settings
|
-- Common settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
||||||
|
|
||||||
|
-- Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1984494439"] = "Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create."
|
||||||
|
|
||||||
|
-- This policy is managed by your organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2035084381"] = "This policy is managed by your organization."
|
||||||
|
|
||||||
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted."
|
||||||
|
|
||||||
@ -453,6 +459,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy name
|
-- Policy name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
||||||
|
|
||||||
|
-- No policy is selected. Please select a policy to export.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2929693091"] = "No policy is selected. Please select a policy to export."
|
||||||
|
|
||||||
-- Policy Description
|
-- Policy Description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Policy Description"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3023558273"] = "Policy Description"
|
||||||
|
|
||||||
@ -468,6 +477,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Policy {0}
|
-- Policy {0}
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
||||||
|
|
||||||
|
-- No, show the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3166091879"] = "No, show the policy definition"
|
||||||
|
|
||||||
-- The description of your policy must be between 32 and 512 characters long.
|
-- The description of your policy must be between 32 and 512 characters long.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
||||||
|
|
||||||
@ -510,6 +522,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
-- After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T726434276"] = "After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points."
|
||||||
|
|
||||||
|
-- The selected policy contains invalid data. Please fix the issues before exporting the policy.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T736334861"] = "The selected policy contains invalid data. Please fix the issues before exporting the policy."
|
||||||
|
|
||||||
-- Policy description
|
-- Policy description
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
||||||
|
|
||||||
@ -519,6 +534,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
|||||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
||||||
|
|
||||||
|
-- Yes, hide the policy definition
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T940701960"] = "Yes, hide the policy definition"
|
||||||
|
|
||||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
||||||
|
|
||||||
@ -1788,21 +1806,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Limitations
|
|||||||
-- Personal Needs and Limitations of Web Services
|
-- Personal Needs and Limitations of Web Services
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Personal Needs and Limitations of Web Services"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1839655973"] = "Personal Needs and Limitations of Web Services"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
-- While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3552777197"] = "While exploring available solutions, I found a desktop application called Anything LLM. Unfortunately, it fell short of meeting my specific requirements and lacked the user interface design I envisioned. For macOS, there were several apps similar to what I had in mind, but they were all commercial solutions shrouded in uncertainty. The developers' identities and the origins of these apps were unclear, raising significant security concerns. Reports from users about stolen API keys and unwanted charges only amplified my reservations."
|
||||||
|
|
||||||
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time.
|
-- We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3569462457"] = "Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. The motivation behind developing this app stems from several crucial needs and observations I made over time."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3672974243"] = "We also want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs for your first steps or use affordable cloud models. MindWork AI Studio itself is available free of charge."
|
||||||
|
|
||||||
-- Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T3622193740"] = "Through MindWork AI Studio, I aim to provide a secure, flexible, and user-friendly tool that caters to a wider audience without compromising on functionality or design. This app is the culmination of my desire to meet personal requirements, address existing gaps in the market, and showcase innovative development practices."
|
|
||||||
|
|
||||||
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
-- Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Relying on web services like ChatGPT was not a sustainable solution for me. I needed an AI that could also access files directly on my device, a functionality web services inherently lack due to security and privacy constraints. Although I could have scripted something in Python to meet my needs, this approach was too cumbersome for daily use. More importantly, I wanted to develop a solution that anyone could use without needing any programming knowledge."
|
||||||
|
|
||||||
|
-- Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T483341611"] = "Hello, my name is Thorsten Sommer, and I am the initial creator of MindWork AI Studio. I started this project based on several crucial needs and observations I made over time. Today, we have a core team of developers and support from the open-source community."
|
||||||
|
|
||||||
-- Cross-Platform and Modern Development
|
-- Cross-Platform and Modern Development
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platform and Modern Development"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platform and Modern Development"
|
||||||
|
|
||||||
|
-- Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T904941692"] = "Today, our team aims to provide a secure, flexible, and user-friendly tool that serves a broad audience without compromising on functionality or design."
|
||||||
|
|
||||||
-- Copies the content to the clipboard
|
-- Copies the content to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"
|
||||||
|
|
||||||
@ -2064,12 +2088,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1898060643"]
|
|||||||
-- Select the language for the app.
|
-- Select the language for the app.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Select the language for the app."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1907446663"] = "Select the language for the app."
|
||||||
|
|
||||||
|
-- When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2013281167"] = "When enabled, additional administration options become visible. These options are intended for IT staff to manage organization-wide configuration, e.g. configuring and exporting providers for an entire organization."
|
||||||
|
|
||||||
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
-- The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2143741496"] = "The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused."
|
||||||
|
|
||||||
-- Disable dictation and transcription
|
-- Disable dictation and transcription
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Disable dictation and transcription"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"] = "Disable dictation and transcription"
|
||||||
|
|
||||||
|
-- Enterprise Administration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2277116008"] = "Enterprise Administration"
|
||||||
|
|
||||||
-- Language behavior
|
-- Language behavior
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Language behavior"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Language behavior"
|
||||||
|
|
||||||
@ -2079,6 +2109,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T237706157"]
|
|||||||
-- Language
|
-- Language
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Language"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Language"
|
||||||
|
|
||||||
|
-- Administration settings are visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591866808"] = "Administration settings are visible"
|
||||||
|
|
||||||
-- Save energy?
|
-- Save energy?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Save energy?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Save energy?"
|
||||||
|
|
||||||
@ -2088,9 +2121,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3165555978"]
|
|||||||
-- App Options
|
-- App Options
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App Options"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3577148634"] = "App Options"
|
||||||
|
|
||||||
|
-- Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T362833"] = "Generate a 256-bit encryption secret for encrypting API keys in configuration plugins. Deploy this secret to client machines via Group Policy (Windows Registry) or environment variables. Providers can then be exported with encrypted API keys using the export buttons in the provider settings."
|
||||||
|
|
||||||
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
-- When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3652888444"] = "When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."
|
||||||
|
|
||||||
|
-- Show administration settings?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3694781396"] = "Show administration settings?"
|
||||||
|
|
||||||
|
-- Read the Enterprise IT documentation for details.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3705451321"] = "Read the Enterprise IT documentation for details."
|
||||||
|
|
||||||
-- Enable spellchecking?
|
-- Enable spellchecking?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Enable spellchecking?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"] = "Enable spellchecking?"
|
||||||
|
|
||||||
@ -2124,9 +2166,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T817101267"]
|
|||||||
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
-- Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T844514734"] = "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence."
|
||||||
|
|
||||||
|
-- Generate an encryption secret and copy it to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T922066419"] = "Generate an encryption secret and copy it to the clipboard"
|
||||||
|
|
||||||
|
-- Administration settings are not visible
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T929143445"] = "Administration settings are not visible"
|
||||||
|
|
||||||
|
-- Embedding Result
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1387042335"] = "Embedding Result"
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Delete"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1469573738"] = "Delete"
|
||||||
|
|
||||||
|
-- Embed text
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1644934561"] = "Embed text"
|
||||||
|
|
||||||
|
-- Test Embedding Provider
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1655784761"] = "Test Embedding Provider"
|
||||||
|
|
||||||
-- Add Embedding
|
-- Add Embedding
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Add Embedding"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1738753945"] = "Add Embedding"
|
||||||
|
|
||||||
@ -2139,6 +2196,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T18253
|
|||||||
-- Add Embedding Provider
|
-- Add Embedding Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Add Embedding Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T190634634"] = "Add Embedding Provider"
|
||||||
|
|
||||||
|
-- Add text that should be embedded:
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T1992646324"] = "Add text that should be embedded:"
|
||||||
|
|
||||||
|
-- Embedding Vector (one dimension per line)
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2174876961"] = "Embedding Vector (one dimension per line)"
|
||||||
|
|
||||||
-- Model
|
-- Model
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Model"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T2189814010"] = "Model"
|
||||||
|
|
||||||
@ -2148,6 +2211,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199
|
|||||||
-- Name
|
-- Name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name"
|
||||||
|
|
||||||
|
-- No embedding was returned.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T291969"] = "No embedding was returned."
|
||||||
|
|
||||||
-- Configured Embedding Providers
|
-- Configured Embedding Providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers"
|
||||||
|
|
||||||
@ -2157,6 +2223,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T32512
|
|||||||
-- Edit
|
-- Edit
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3448155331"] = "Close"
|
||||||
|
|
||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions"
|
||||||
|
|
||||||
@ -2178,9 +2247,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T51130
|
|||||||
-- Open Dashboard
|
-- Open Dashboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Open Dashboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223861"] = "Open Dashboard"
|
||||||
|
|
||||||
|
-- Test
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T805092869"] = "Test"
|
||||||
|
|
||||||
|
-- Example text to embed
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Example text to embed"
|
||||||
|
|
||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
|
-- Cannot export the encrypted API key: No enterprise encryption secret is configured.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Cannot export the encrypted API key: No enterprise encryption secret is configured."
|
||||||
|
|
||||||
|
-- This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T3368145670"] = "This provider has an API key configured. Do you want to include the encrypted API key in the export? Note: The recipient will need the same encryption secret to use the API key."
|
||||||
|
|
||||||
|
-- Export API Key?
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T4010580285"] = "Export API Key?"
|
||||||
|
|
||||||
-- Show provider's confidence level?
|
-- Show provider's confidence level?
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?"
|
||||||
|
|
||||||
@ -2286,6 +2373,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
-- No transcription provider configured yet.
|
-- No transcription provider configured yet.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet."
|
||||||
|
|
||||||
@ -2340,6 +2430,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78
|
|||||||
-- Provider
|
-- Provider
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider"
|
||||||
|
|
||||||
|
-- Export configuration
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Export configuration"
|
||||||
|
|
||||||
-- Copy {0} to the clipboard
|
-- Copy {0} to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard"
|
||||||
|
|
||||||
@ -2376,9 +2469,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1648606751"] = "You'll be able t
|
|||||||
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
-- It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1926587044"] = "It will soon be possible to integrate data from the corporate network using a specified interface (External Retrieval Interface, ERI for short). This will likely require development work by the organization in question."
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
-- Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2144737937"] = "Whatever your job or task is, MindWork AI Studio aims to meet your needs: whether you're a project manager, scientist, artist, author, software developer, or game developer."
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2201645589"] = "We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models. MindWork AI Studio itself is available free of charge."
|
||||||
|
|
||||||
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
-- You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T2289234741"] = "You can connect your email inboxes with AI Studio. The AI will read your emails and notify you of important events. You'll also be able to access knowledge from your emails in your chats."
|
||||||
|
|
||||||
@ -2460,8 +2559,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Are you sure
|
|||||||
-- Move chat
|
-- Move chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat"
|
||||||
|
|
||||||
-- Unnamed workspace
|
-- Loading chats...
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1307384014"] = "Unnamed workspace"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1364857726"] = "Loading chats..."
|
||||||
|
|
||||||
-- Delete
|
-- Delete
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Delete"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1469573738"] = "Delete"
|
||||||
@ -2517,9 +2616,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T323280982"] = "Please enter
|
|||||||
-- Please enter a workspace name.
|
-- Please enter a workspace name.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Please enter a workspace name."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3288132732"] = "Please enter a workspace name."
|
||||||
|
|
||||||
-- Unnamed chat
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3310482275"] = "Unnamed chat"
|
|
||||||
|
|
||||||
-- Rename
|
-- Rename
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Rename"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3355849203"] = "Rename"
|
||||||
|
|
||||||
@ -3258,6 +3354,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Pro
|
|||||||
-- Cancel
|
-- Cancel
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel"
|
||||||
|
|
||||||
|
-- Embedding Vector
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T1173984541"] = "Embedding Vector"
|
||||||
|
|
||||||
|
-- Close
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGRESULTDIALOG::T3448155331"] = "Close"
|
||||||
|
|
||||||
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system."
|
||||||
|
|
||||||
@ -4029,33 +4131,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
|||||||
-- Local Directory
|
-- Local Directory
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
||||||
|
|
||||||
-- Assistant: Document Analysis
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis"
|
|
||||||
|
|
||||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function."
|
|
||||||
|
|
||||||
-- Would you like to preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?"
|
|
||||||
|
|
||||||
-- Preselect document analysis options?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some document analysis options.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options."
|
|
||||||
|
|
||||||
-- No document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected"
|
|
||||||
|
|
||||||
-- Close
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close"
|
|
||||||
|
|
||||||
-- Document analysis options are preselected
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected"
|
|
||||||
|
|
||||||
-- Preselect one of your profiles?
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?"
|
|
||||||
|
|
||||||
-- When enabled, you can preselect some ERI server options.
|
-- When enabled, you can preselect some ERI server options.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
||||||
|
|
||||||
@ -4905,6 +4980,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T878695986"] = "Learn about one co
|
|||||||
-- Localization
|
-- Localization
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Localization"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Localization"
|
||||||
|
|
||||||
|
-- Reload your workspaces
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T194629703"] = "Reload your workspaces"
|
||||||
|
|
||||||
-- Hide your workspaces
|
-- Hide your workspaces
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Hide your workspaces"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T2351468526"] = "Hide your workspaces"
|
||||||
|
|
||||||
@ -4950,6 +5028,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T149711988"] = "You only pay for what yo
|
|||||||
-- Assistants
|
-- Assistants
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistants"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1614176092"] = "Assistants"
|
||||||
|
|
||||||
|
-- We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1628689293"] = "We want to contribute to the democratization of AI. MindWork AI Studio runs even on low-cost hardware, including computers around 100 € such as Raspberry Pi. This makes the app and its full feature set accessible to people and families with limited budgets. You can start with local LLMs or use affordable cloud models."
|
||||||
|
|
||||||
-- Unrestricted usage
|
-- Unrestricted usage
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unrestricted usage"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1686815996"] = "Unrestricted usage"
|
||||||
|
|
||||||
@ -4959,6 +5040,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1702902297"] = "Introduction"
|
|||||||
-- Vision
|
-- Vision
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1892426825"] = "Vision"
|
||||||
|
|
||||||
|
-- Democratization of AI
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1986314327"] = "Democratization of AI"
|
||||||
|
|
||||||
-- Let's get started
|
-- Let's get started
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Let's get started"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T2331588413"] = "Let's get started"
|
||||||
|
|
||||||
@ -5013,18 +5097,33 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1019424746"] = "Startup log file
|
|||||||
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Browse AI Studio's source code on GitHub — we welcome your contributions."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1107156991"] = "Browse AI Studio's source code on GitHub — we welcome your contributions."
|
||||||
|
|
||||||
|
-- ID mismatch: the plugin ID differs from the enterprise configuration ID.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1137744461"] = "ID mismatch: the plugin ID differs from the enterprise configuration ID."
|
||||||
|
|
||||||
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
-- This is a private AI Studio installation. It runs without an enterprise configuration.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1282228996"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available."
|
|
||||||
|
|
||||||
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."
|
||||||
|
|
||||||
|
-- Database version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1420062548"] = "Database version"
|
||||||
|
|
||||||
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."
|
||||||
|
|
||||||
|
-- Waiting for the configuration plugin...
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1533382393"] = "Waiting for the configuration plugin..."
|
||||||
|
|
||||||
|
-- Encryption secret: is not configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1560776885"] = "Encryption secret: is not configured"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1596483935"] = "AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active."
|
||||||
|
|
||||||
|
-- Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG -— retrieval-augmented generation -— within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1619832053"] = "Qdrant is a vector database and vector similarity search engine. We use it to realize local RAG -— retrieval-augmented generation -— within AI Studio. Thanks for the effort and great work that has been and is being put into Qdrant."
|
||||||
|
|
||||||
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T162898512"] = "We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library."
|
||||||
|
|
||||||
@ -5058,9 +5157,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1915240766"] = "In order to use
|
|||||||
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
-- This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1924365263"] = "This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."
|
||||||
|
|
||||||
|
-- Encryption secret: is configured
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1931141322"] = "Encryption secret: is configured"
|
||||||
|
|
||||||
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust."
|
||||||
|
|
||||||
|
-- Copies the following to the clipboard
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2029659664"] = "Copies the following to the clipboard"
|
||||||
|
|
||||||
-- Copies the server URL to the clipboard
|
-- Copies the server URL to the clipboard
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Copies the server URL to the clipboard"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Copies the server URL to the clipboard"
|
||||||
|
|
||||||
@ -5079,9 +5184,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2272122662"] = "Configuration se
|
|||||||
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2280402765"] = "AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management."
|
|
||||||
|
|
||||||
-- Configuration plugin ID:
|
-- Configuration plugin ID:
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Configuration plugin ID:"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2301484629"] = "Configuration plugin ID:"
|
||||||
|
|
||||||
@ -5106,6 +5208,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2557066213"] = "Used Open Source
|
|||||||
-- Build time
|
-- Build time
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build time"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T260228112"] = "Build time"
|
||||||
|
|
||||||
|
-- This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2619858133"] = "This library is used to create temporary folders for saving the certificate and private key for communication with Qdrant."
|
||||||
|
|
||||||
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
-- This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2635482790"] = "This crate provides derive macros for Rust enums, which we use to reduce boilerplate when implementing string conversions and metadata for runtime types. This is helpful for the communication between our Rust and .NET systems."
|
||||||
|
|
||||||
@ -5142,6 +5247,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2840582448"] = "Explanation"
|
|||||||
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
-- The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2868174483"] = "The .NET backend cannot be started as a desktop app. Therefore, I use a second backend in Rust, which I call runtime. With Rust as the runtime, Tauri can be used to realize a typical desktop app. Thanks to Rust, this app can be offered for Windows, macOS, and Linux desktops. Rust is a great language for developing safe and high-performance software."
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2924964415"] = "AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are not yet available."
|
||||||
|
|
||||||
-- Changelog
|
-- Changelog
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Changelog"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3017574265"] = "Changelog"
|
||||||
|
|
||||||
@ -5175,6 +5283,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3433065373"] = "Information abou
|
|||||||
-- Used Rust compiler
|
-- Used Rust compiler
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Used Rust compiler"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3440211747"] = "Used Rust compiler"
|
||||||
|
|
||||||
|
-- AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3449345633"] = "AI Studio runs with an enterprise configuration using configuration plugins, without central configuration management."
|
||||||
|
|
||||||
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
-- Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3494984593"] = "Tauri is used to host the Blazor user interface. It is a great project that allows the creation of desktop applications using web technologies. I love Tauri!"
|
||||||
|
|
||||||
@ -5184,9 +5295,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3563271893"] = "Motivation"
|
|||||||
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat."
|
||||||
|
|
||||||
-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3741877842"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active."
|
|
||||||
|
|
||||||
-- this version does not met the requirements
|
-- this version does not met the requirements
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "this version does not met the requirements"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3813932670"] = "this version does not met the requirements"
|
||||||
|
|
||||||
@ -5223,6 +5331,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T566998575"] = "This is a library
|
|||||||
-- Used .NET SDK
|
-- Used .NET SDK
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Used .NET SDK"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T585329785"] = "Used .NET SDK"
|
||||||
|
|
||||||
|
-- This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T633932150"] = "This library is used to manage sidecar processes and to ensure that stale or zombie sidecars are detected and terminated."
|
||||||
|
|
||||||
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
-- Did you find a bug or are you experiencing issues? Report your concern here.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Did you find a bug or are you experiencing issues? Report your concern here."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T639371534"] = "Did you find a bug or are you experiencing issues? Report your concern here."
|
||||||
|
|
||||||
@ -5253,6 +5364,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Internal Plugins"
|
|||||||
-- Disabled Plugins
|
-- Disabled Plugins
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
|
||||||
|
|
||||||
|
-- Send a mail
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1999487139"] = "Send a mail"
|
||||||
|
|
||||||
-- Enable plugin
|
-- Enable plugin
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
||||||
|
|
||||||
@ -5265,6 +5379,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Enabled Plugins"
|
|||||||
-- Actions
|
-- Actions
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
|
||||||
|
|
||||||
|
-- Open website
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4239378936"] = "Open website"
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Settings"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::SETTINGS::T1258653480"] = "Settings"
|
||||||
|
|
||||||
@ -5781,6 +5898,21 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T3893997203"] = "
|
|||||||
-- Trust all LLM providers
|
-- Trust all LLM providers
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Trust all LLM providers"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::CONFIDENCESCHEMESEXTENSIONS::T4107860491"] = "Trust all LLM providers"
|
||||||
|
|
||||||
|
-- Storage size
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
|
||||||
|
|
||||||
|
-- HTTP port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T1717573768"] = "HTTP port"
|
||||||
|
|
||||||
|
-- Reported version
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T3556099842"] = "Reported version"
|
||||||
|
|
||||||
|
-- gRPC port
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T757840040"] = "gRPC port"
|
||||||
|
|
||||||
|
-- Number of collections
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::QDRANT::QDRANTCLIENTIMPLEMENTATION::T842647336"] = "Number of collections"
|
||||||
|
|
||||||
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
-- The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::DATAMODEL::PROVIDERTYPEEXTENSIONS::T1555790630"] = "The related data is not allowed to be sent to any LLM provider. This means that this data source cannot be used at the moment."
|
||||||
|
|
||||||
@ -5970,15 +6102,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2262604281"] = "The
|
|||||||
-- The field DESCRIPTION does not exist or is not a valid string.
|
-- The field DESCRIPTION does not exist or is not a valid string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "The field DESCRIPTION does not exist or is not a valid string."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T229488255"] = "The field DESCRIPTION does not exist or is not a valid string."
|
||||||
|
|
||||||
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://' or 'https://'.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2320984047"] = "The field SOURCE_URL is not a valid URL. The URL must start with 'http://' or 'https://'."
|
|
||||||
|
|
||||||
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
-- The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X).
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X)."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2538827536"] = "The field VERSION is not a valid version number. The version number must be formatted as string in the major.minor.patch format (X.X.X)."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. The URL must start with 'http://', 'https://', or 'mailto:'.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2892057533"] = "The field SOURCE_URL is not a valid URL. The URL must start with 'http://', 'https://', or 'mailto:'."
|
||||||
|
|
||||||
-- The table AUTHORS is empty. At least one author must be specified.
|
-- The table AUTHORS is empty. At least one author must be specified.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "The table AUTHORS is empty. At least one author must be specified."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T2981832540"] = "The table AUTHORS is empty. At least one author must be specified."
|
||||||
|
|
||||||
|
-- The field SOURCE_URL is not a valid URL. When the URL starts with 'mailto:', it must contain a valid email address as recipient.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3165663073"] = "The field SOURCE_URL is not a valid URL. When the URL starts with 'mailto:', it must contain a valid email address as recipient."
|
||||||
|
|
||||||
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
-- The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string."
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T3524814526"] = "The field SUPPORT_CONTACT is empty. The support contact must be a non-empty string."
|
||||||
|
|
||||||
@ -6386,3 +6521,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unnamed w
|
|||||||
|
|
||||||
-- Delete Chat
|
-- Delete Chat
|
||||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Delete Chat"
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Delete Chat"
|
||||||
|
|
||||||
|
-- Unnamed chat
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3310482275"] = "Unnamed chat"
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using AIStudio.Agents;
|
using AIStudio.Agents;
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Tools.Databases;
|
||||||
|
using AIStudio.Tools.Databases.Qdrant;
|
||||||
using AIStudio.Tools.PluginSystem;
|
using AIStudio.Tools.PluginSystem;
|
||||||
using AIStudio.Tools.Services;
|
using AIStudio.Tools.Services;
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ internal sealed class Program
|
|||||||
public static string API_TOKEN = null!;
|
public static string API_TOKEN = null!;
|
||||||
public static IServiceProvider SERVICE_PROVIDER = null!;
|
public static IServiceProvider SERVICE_PROVIDER = null!;
|
||||||
public static ILoggerFactory LOGGER_FACTORY = null!;
|
public static ILoggerFactory LOGGER_FACTORY = null!;
|
||||||
|
public static DatabaseClient DATABASE_CLIENT = null!;
|
||||||
|
|
||||||
public static async Task Main()
|
public static async Task Main()
|
||||||
{
|
{
|
||||||
@ -82,6 +85,39 @@ internal sealed class Program
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var qdrantInfo = await rust.GetQdrantInfo();
|
||||||
|
if (qdrantInfo.Path == string.Empty)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Failed to get the Qdrant path from Rust.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qdrantInfo.PortHttp == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Failed to get the Qdrant HTTP port from Rust.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qdrantInfo.PortGrpc == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Failed to get the Qdrant gRPC port from Rust.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qdrantInfo.Fingerprint == string.Empty)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Failed to get the Qdrant fingerprint from Rust.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qdrantInfo.ApiToken == string.Empty)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Failed to get the Qdrant API token from Rust.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseClient = new QdrantClientImplementation("Qdrant", qdrantInfo.Path, qdrantInfo.PortHttp, qdrantInfo.PortGrpc, qdrantInfo.Fingerprint, qdrantInfo.ApiToken);
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder();
|
var builder = WebApplication.CreateBuilder();
|
||||||
builder.WebHost.ConfigureKestrel(kestrelServerOptions =>
|
builder.WebHost.ConfigureKestrel(kestrelServerOptions =>
|
||||||
{
|
{
|
||||||
@ -133,6 +169,7 @@ internal sealed class Program
|
|||||||
builder.Services.AddHostedService<UpdateService>();
|
builder.Services.AddHostedService<UpdateService>();
|
||||||
builder.Services.AddHostedService<TemporaryChatService>();
|
builder.Services.AddHostedService<TemporaryChatService>();
|
||||||
builder.Services.AddHostedService<EnterpriseEnvironmentService>();
|
builder.Services.AddHostedService<EnterpriseEnvironmentService>();
|
||||||
|
builder.Services.AddSingleton<DatabaseClient>(databaseClient);
|
||||||
builder.Services.AddHostedService<GlobalShortcutService>();
|
builder.Services.AddHostedService<GlobalShortcutService>();
|
||||||
builder.Services.AddHostedService<RustAvailabilityMonitorService>();
|
builder.Services.AddHostedService<RustAvailabilityMonitorService>();
|
||||||
|
|
||||||
@ -192,6 +229,10 @@ internal sealed class Program
|
|||||||
RUST_SERVICE = rust;
|
RUST_SERVICE = rust;
|
||||||
ENCRYPTION = encryption;
|
ENCRYPTION = encryption;
|
||||||
|
|
||||||
|
var databaseLogger = app.Services.GetRequiredService<ILogger<DatabaseClient>>();
|
||||||
|
databaseClient.SetLogger(databaseLogger);
|
||||||
|
DATABASE_CLIENT = databaseClient;
|
||||||
|
|
||||||
programLogger.LogInformation("Initialize internal file system.");
|
programLogger.LogInformation("Initialize internal file system.");
|
||||||
app.Use(Redirect.HandlerContentAsync);
|
app.Use(Redirect.HandlerContentAsync);
|
||||||
app.Use(FileHandler.HandlerAsync);
|
app.Use(FileHandler.HandlerAsync);
|
||||||
@ -228,6 +269,7 @@ internal sealed class Program
|
|||||||
await serverTask;
|
await serverTask;
|
||||||
|
|
||||||
RUST_SERVICE.Dispose();
|
RUST_SERVICE.Dispose();
|
||||||
|
DATABASE_CLIENT.Dispose();
|
||||||
PluginFactory.Dispose();
|
PluginFactory.Dispose();
|
||||||
programLogger.LogInformation("The AI Studio server was stopped.");
|
programLogger.LogInformation("The AI Studio server was stopped.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,13 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C
|
|||||||
return Task.FromResult(string.Empty);
|
return Task.FromResult(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inhertidoc />
|
||||||
|
public override async Task<IReadOnlyList<IReadOnlyList<float>>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List<string> texts)
|
||||||
|
{
|
||||||
|
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.EMBEDDING_PROVIDER);
|
||||||
|
return await this.PerformStandardTextEmbeddingRequest(requestedSecret, embeddingModel, token: token, texts: texts);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -114,6 +114,12 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, "
|
|||||||
return Task.FromResult(string.Empty);
|
return Task.FromResult(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inhertidoc />
|
||||||
|
public override Task<IReadOnlyList<IReadOnlyList<float>>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List<string> texts)
|
||||||
|
{
|
||||||
|
return Task.FromResult<IReadOnlyList<IReadOnlyList<float>>>([]);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
@ -98,6 +99,9 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract Task<string> TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default);
|
public abstract Task<string> TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract Task<IReadOnlyList<IReadOnlyList<float>>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List<string> texts);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default);
|
public abstract Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default);
|
||||||
|
|
||||||
@ -112,9 +116,14 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this provider was imported from an enterprise configuration plugin.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEnterpriseConfiguration { get; init; }
|
||||||
|
|
||||||
#region Implementation of ISecretId
|
#region Implementation of ISecretId
|
||||||
|
|
||||||
public string SecretId => this.Id;
|
public string SecretId => this.IsEnterpriseConfiguration ? $"{ISecretId.ENTERPRISE_KEY_PREFIX}::{this.Id}" : this.Id;
|
||||||
|
|
||||||
public string SecretName => this.InstanceName;
|
public string SecretName => this.InstanceName;
|
||||||
|
|
||||||
@ -640,6 +649,81 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task<IReadOnlyList<IReadOnlyList<float>>> PerformStandardTextEmbeddingRequest(RequestedSecret requestedSecret, Model embeddingModel, Host host = Host.NONE, CancellationToken token = default, params List<string> texts)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Add the model name to the form data. Ensure that a model name is always provided.
|
||||||
|
// Otherwise, the StringContent constructor will throw an exception.
|
||||||
|
//
|
||||||
|
var modelName = embeddingModel.Id;
|
||||||
|
if (string.IsNullOrWhiteSpace(modelName))
|
||||||
|
modelName = "placeholder";
|
||||||
|
|
||||||
|
// Prepare the HTTP embedding request:
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
model = modelName,
|
||||||
|
input = texts,
|
||||||
|
encoding_format = "float"
|
||||||
|
};
|
||||||
|
|
||||||
|
var embeddingRequest = JsonSerializer.Serialize(payload, JSON_SERIALIZER_OPTIONS);
|
||||||
|
using var request = new HttpRequestMessage(HttpMethod.Post, host.EmbeddingURL());
|
||||||
|
|
||||||
|
// Handle the authorization header based on the provider:
|
||||||
|
switch (this.Provider)
|
||||||
|
{
|
||||||
|
case LLMProviders.SELF_HOSTED:
|
||||||
|
if(requestedSecret.Success)
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(!requestedSecret.Success)
|
||||||
|
{
|
||||||
|
this.logger.LogError("No valid API key available for embedding request.");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the content:
|
||||||
|
request.Content = new StringContent(embeddingRequest, Encoding.UTF8, "application/json");
|
||||||
|
using var response = await this.httpClient.SendAsync(request, token);
|
||||||
|
var responseBody = response.Content.ReadAsStringAsync(token).Result;
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger.LogError("Embedding request failed with status code {ResponseStatusCode} and body: '{ResponseBody}'.", response.StatusCode, responseBody);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var embeddingResponse = JsonSerializer.Deserialize<EmbeddingResponse>(responseBody, JSON_SERIALIZER_OPTIONS);
|
||||||
|
if (embeddingResponse is { Data: not null })
|
||||||
|
{
|
||||||
|
return embeddingResponse.Data
|
||||||
|
.Select(d => d.Embedding?.ToArray() ?? [])
|
||||||
|
.Cast<IReadOnlyList<float>>()
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.logger.LogError("Was not able to deserialize the embedding response.");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.logger.LogError("Failed to perform embedding request: '{Message}'.", e.Message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parse and convert API parameters from a provided JSON string into a dictionary,
|
/// Parse and convert API parameters from a provided JSON string into a dictionary,
|
||||||
/// optionally merging additional parameters and removing specific keys.
|
/// optionally merging additional parameters and removing specific keys.
|
||||||
|
|||||||
@ -87,6 +87,12 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h
|
|||||||
return Task.FromResult(string.Empty);
|
return Task.FromResult(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inhertidoc />
|
||||||
|
public override Task<IReadOnlyList<IReadOnlyList<float>>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List<string> texts)
|
||||||
|
{
|
||||||
|
return Task.FromResult<IReadOnlyList<IReadOnlyList<float>>>([]);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
public override Task<IEnumerable<Model>> GetTextModels(string? apiKeyProvisional = null, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user