mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-05-03 09:39:47 +00:00
Add component to read PDF files into assistants (#439)
Some checks failed
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Some checks failed
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
This commit is contained in:
parent
9996b810e2
commit
c4d9af18cd
127
.github/workflows/build-and-release.yml
vendored
127
.github/workflows/build-and-release.yml
vendored
@ -167,6 +167,12 @@ jobs:
|
||||
sed -i '' "10s/.*/${{ matrix.dotnet_runtime }}/" metadata.txt
|
||||
fi
|
||||
|
||||
# Next line is the necessary PDFium version.
|
||||
# The format is '137.0.7123.0'. What we need
|
||||
# is the '7123' part:
|
||||
pdfium_version=$(sed -n '11p' metadata.txt)
|
||||
pdfium_version=$(echo $pdfium_version | cut -d'.' -f3)
|
||||
|
||||
# Write the metadata to the environment:
|
||||
echo "APP_VERSION=${app_version}" >> $GITHUB_ENV
|
||||
echo "FORMATTED_APP_VERSION=${formatted_app_version}" >> $GITHUB_ENV
|
||||
@ -178,6 +184,7 @@ jobs:
|
||||
echo "MUD_BLAZOR_VERSION=${mud_blazor_version}" >> $GITHUB_ENV
|
||||
echo "TAURI_VERSION=${tauri_version}" >> $GITHUB_ENV
|
||||
echo "ARCHITECTURE=${{ matrix.dotnet_runtime }}" >> $GITHUB_ENV
|
||||
echo "PDFIUM_VERSION=${pdfium_version}" >> $GITHUB_ENV
|
||||
|
||||
# Log the metadata:
|
||||
echo "App version: '${formatted_app_version}'"
|
||||
@ -189,6 +196,7 @@ jobs:
|
||||
echo "MudBlazor version: '${mud_blazor_version}'"
|
||||
echo "Tauri version: '${tauri_version}'"
|
||||
echo "Architecture: '${{ matrix.dotnet_runtime }}'"
|
||||
echo "PDFium version: '${pdfium_version}'"
|
||||
|
||||
- name: Read and format metadata (Windows)
|
||||
if: matrix.platform == 'windows-latest'
|
||||
@ -227,6 +235,12 @@ jobs:
|
||||
# Write the changed metadata back to the file:
|
||||
Set-Content -Path metadata.txt -Value $metadata
|
||||
|
||||
# Next line is the necessary PDFium version.
|
||||
# The format is '137.0.7123.0'. What we need
|
||||
# is the '7123' part:
|
||||
$pdfium_version = $metadata[10]
|
||||
$pdfium_version = $pdfium_version.Split('.')[2]
|
||||
|
||||
# Write the metadata to the environment:
|
||||
Write-Output "APP_VERSION=${app_version}" >> $env:GITHUB_ENV
|
||||
Write-Output "FORMATTED_APP_VERSION=${formatted_app_version}" >> $env:GITHUB_ENV
|
||||
@ -237,6 +251,7 @@ jobs:
|
||||
Write-Output "RUST_VERSION=${rust_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 "PDFIUM_VERSION=${pdfium_version}" >> $env:GITHUB_ENV
|
||||
|
||||
# Log the metadata:
|
||||
Write-Output "App version: '${formatted_app_version}'"
|
||||
@ -248,6 +263,7 @@ jobs:
|
||||
Write-Output "MudBlazor version: '${mud_blazor_version}'"
|
||||
Write-Output "Tauri version: '${tauri_version}'"
|
||||
Write-Output "Architecture: '${{ matrix.dotnet_runtime }}'"
|
||||
Write-Output "PDFium version: '${pdfium_version}'"
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
@ -255,6 +271,117 @@ jobs:
|
||||
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
|
||||
cache: true
|
||||
cache-dependency-path: 'app/MindWork AI Studio/packages.lock.json'
|
||||
|
||||
- name: Deploy PDFium (Unix)
|
||||
if: matrix.platform != 'windows-latest'
|
||||
env:
|
||||
PDFIUM_VERSION: ${{ env.PDFIUM_VERSION }}
|
||||
DOTNET_RUNTIME: ${{ matrix.dotnet_runtime }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
# Target directory:
|
||||
TLIB_DIR="runtime/resources/libraries"
|
||||
mkdir -p "$TLIB_DIR"
|
||||
|
||||
case "${DOTNET_RUNTIME}" in
|
||||
linux-x64)
|
||||
PDFIUM_FILE="linux-x64.tgz"
|
||||
LIB_SOURCE="lib/libpdfium.so"
|
||||
LIB_TARGET="libpdfium.so"
|
||||
;;
|
||||
linux-arm64)
|
||||
PDFIUM_FILE="linux-arm64.tgz"
|
||||
LIB_SOURCE="lib/libpdfium.so"
|
||||
LIB_TARGET="libpdfium.so"
|
||||
;;
|
||||
osx-x64)
|
||||
PDFIUM_FILE="mac-x64.tgz"
|
||||
LIB_SOURCE="lib/libpdfium.dylib"
|
||||
LIB_TARGET="libpdfium.dylib"
|
||||
;;
|
||||
osx-arm64)
|
||||
PDFIUM_FILE="mac-arm64.tgz"
|
||||
LIB_SOURCE="lib/libpdfium.dylib"
|
||||
LIB_TARGET="libpdfium.dylib"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown platform: ${DOTNET_RUNTIME}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
PDFIUM_URL="https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F${PDFIUM_VERSION}/pdfium-${PDFIUM_FILE}"
|
||||
|
||||
echo "Download PDFium $PDFIUM_URL ..."
|
||||
TMP=$(mktemp -d)
|
||||
ARCHIVE="${TMP}/pdfium.tgz"
|
||||
|
||||
curl -fsSL -o "$ARCHIVE" "$PDFIUM_URL"
|
||||
|
||||
echo "Extracting PDFium ..."
|
||||
tar xzf "$ARCHIVE" -C "$TMP"
|
||||
SRC="${TMP}/${LIB_SOURCE}"
|
||||
|
||||
if [ ! -f "$SRC" ]; then
|
||||
echo "Was not able to find PDFium source: $SRC"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copy PDFium from ${LIB_TARGET} to ${TLIB_DIR}/"
|
||||
cp -f "$SRC" "$TLIB_DIR/$LIB_TARGET"
|
||||
|
||||
echo "Cleaning up ..."
|
||||
rm -fr "$TMP"
|
||||
|
||||
- name: Install PDFium (Windows)
|
||||
if: matrix.platform == 'windows-latest'
|
||||
env:
|
||||
PDFIUM_VERSION: ${{ env.PDFIUM_VERSION }}
|
||||
DOTNET_RUNTIME: ${{ matrix.dotnet_runtime }}
|
||||
run: |
|
||||
$TLIB_DIR = "runtime\resources\libraries"
|
||||
New-Item -ItemType Directory -Force -Path $TLIB_DIR | Out-Null
|
||||
|
||||
switch ($env:DOTNET_RUNTIME) {
|
||||
"win-x64" {
|
||||
$PDFIUM_FILE = "win-x64.tgz"
|
||||
$LIB_SOURCE = "bin\pdfium.dll"
|
||||
$LIB_TARGET = "pdfium.dll"
|
||||
}
|
||||
"win-arm64" {
|
||||
$PDFIUM_FILE = "win-arm64.tgz"
|
||||
$LIB_SOURCE = "bin\pdfium.dll"
|
||||
$LIB_TARGET = "pdfium.dll"
|
||||
}
|
||||
default {
|
||||
Write-Error "Unknown platform: $($env:DOTNET_RUNTIME)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
$PDFIUM_URL = "https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F$($env:PDFIUM_VERSION)/pdfium-$PDFIUM_FILE"
|
||||
Write-Host "Download $PDFIUM_URL ..."
|
||||
$TMP = New-TemporaryFile | Split-Path
|
||||
$ARCHIVE = Join-Path $TMP "pdfium.tgz"
|
||||
|
||||
Invoke-WebRequest -Uri $PDFIUM_URL -OutFile $ARCHIVE
|
||||
|
||||
Write-Host "Extracting PDFium ..."
|
||||
tar -xzf $ARCHIVE -C $TMP
|
||||
|
||||
$SRC = Join-Path $TMP $LIB_SOURCE
|
||||
if (!(Test-Path $SRC)) {
|
||||
Write-Error "Cannot find PDFium source: $SRC"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$DEST = Join-Path $TLIB_DIR $LIB_TARGET
|
||||
Copy-Item -Path $SRC -Destination $DEST -Force
|
||||
|
||||
Write-Host "Cleaning up ..."
|
||||
Remove-Item $ARCHIVE -Force
|
||||
Remove-Item $TMP -Recurse -Force
|
||||
|
||||
- name: Build .NET project
|
||||
run: |
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
||||
# Ignore pdfium library:
|
||||
libpdfium.dylib
|
||||
libpdfium.so
|
||||
libpdfium.dll
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
@ -17,5 +17,10 @@ public sealed class CheckRidsCommand
|
||||
{
|
||||
Console.WriteLine($"- {rid}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("The RID for the current OS and CPU is:");
|
||||
var currentRid = Environment.GetCurrentRid();
|
||||
Console.WriteLine($"- {currentRid}");
|
||||
}
|
||||
}
|
3
app/Build/Commands/Library.cs
Normal file
3
app/Build/Commands/Library.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace Build.Commands;
|
||||
|
||||
public record Library(string Path, string Filename);
|
107
app/Build/Commands/Pdfium.cs
Normal file
107
app/Build/Commands/Pdfium.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using System.Formats.Tar;
|
||||
using System.IO.Compression;
|
||||
|
||||
using SharedTools;
|
||||
|
||||
namespace Build.Commands;
|
||||
|
||||
public static class Pdfium
|
||||
{
|
||||
public static async Task InstallAsync(RID rid, string version)
|
||||
{
|
||||
Console.Write($"- Installing Pdfium {version} for {rid.ToUserFriendlyName()} ...");
|
||||
|
||||
var cwd = Environment.GetRustRuntimeDirectory();
|
||||
var pdfiumTmpDownloadPath = Path.GetTempFileName();
|
||||
var pdfiumTmpExtractPath = Directory.CreateTempSubdirectory();
|
||||
var pdfiumUrl = GetPdfiumDownloadUrl(rid, version);
|
||||
|
||||
//
|
||||
// Download the file:
|
||||
//
|
||||
Console.Write(" downloading ...");
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var response = await client.GetAsync(pdfiumUrl);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Console.WriteLine($" failed to download Pdfium {version} for {rid.ToUserFriendlyName()}");
|
||||
return;
|
||||
}
|
||||
|
||||
await using var fileStream = File.Create(pdfiumTmpDownloadPath);
|
||||
await response.Content.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
//
|
||||
// Extract the downloaded file:
|
||||
//
|
||||
Console.Write(" extracting ...");
|
||||
await using(var tgzStream = File.Open(pdfiumTmpDownloadPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
await using var uncompressedStream = new GZipStream(tgzStream, CompressionMode.Decompress);
|
||||
await TarFile.ExtractToDirectoryAsync(uncompressedStream, pdfiumTmpExtractPath.FullName, true);
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the library to the target directory:
|
||||
//
|
||||
Console.Write(" deploying ...");
|
||||
var library = GetLibraryPath(rid);
|
||||
if (string.IsNullOrEmpty(library.Path))
|
||||
{
|
||||
Console.WriteLine($" failed to find the library path for {rid.ToUserFriendlyName()}");
|
||||
return;
|
||||
}
|
||||
|
||||
var pdfiumLibSourcePath = Path.Join(pdfiumTmpExtractPath.FullName, library.Path);
|
||||
var pdfiumLibTargetPath = Path.Join(cwd, "resources", "libraries", library.Filename);
|
||||
if (!File.Exists(pdfiumLibSourcePath))
|
||||
{
|
||||
Console.WriteLine($" failed to find the library file '{pdfiumLibSourcePath}'");
|
||||
return;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.Join(cwd, "resources", "libraries"));
|
||||
if (File.Exists(pdfiumLibTargetPath))
|
||||
File.Delete(pdfiumLibTargetPath);
|
||||
|
||||
File.Copy(pdfiumLibSourcePath, pdfiumLibTargetPath);
|
||||
|
||||
//
|
||||
// Cleanup:
|
||||
//
|
||||
Console.Write(" cleaning up ...");
|
||||
File.Delete(pdfiumTmpDownloadPath);
|
||||
Directory.Delete(pdfiumTmpExtractPath.FullName, true);
|
||||
|
||||
Console.WriteLine(" done.");
|
||||
}
|
||||
|
||||
private static Library GetLibraryPath(RID rid) => rid switch
|
||||
{
|
||||
RID.LINUX_ARM64 or RID.LINUX_X64 => new(Path.Join("lib", "libpdfium.so"), "libpdfium.so"),
|
||||
RID.OSX_ARM64 or RID.OSX_X64 => new(Path.Join("lib", "libpdfium.dylib"), "libpdfium.dylib"),
|
||||
RID.WIN_ARM64 or RID.WIN_X64 => new(Path.Join("bin", "pdfium.dll"), "pdfium.dll"),
|
||||
|
||||
_ => new(string.Empty, string.Empty),
|
||||
};
|
||||
|
||||
private static string GetPdfiumDownloadUrl(RID rid, string version)
|
||||
{
|
||||
var baseUrl = $"https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F{version}/pdfium-";
|
||||
return rid switch
|
||||
{
|
||||
RID.LINUX_ARM64 => $"{baseUrl}linux-arm64.tgz",
|
||||
RID.LINUX_X64 => $"{baseUrl}linux-x64.tgz",
|
||||
|
||||
RID.OSX_ARM64 => $"{baseUrl}mac-arm64.tgz",
|
||||
RID.OSX_X64 => $"{baseUrl}mac-x64.tgz",
|
||||
|
||||
RID.WIN_ARM64 => $"{baseUrl}win-arm64.zip",
|
||||
RID.WIN_X64 => $"{baseUrl}win-x64.zip",
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
}
|
@ -105,105 +105,102 @@ public sealed partial class UpdateMetadataCommands
|
||||
// Build the .NET project:
|
||||
//
|
||||
var pathApp = Environment.GetAIStudioDirectory();
|
||||
var rids = Environment.GetRidsForCurrentOS();
|
||||
foreach (var rid in rids)
|
||||
{
|
||||
Console.WriteLine("==============================");
|
||||
await this.UpdateArchitecture(rid);
|
||||
|
||||
Console.Write($"- Start .NET build for '{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 dotnetBuildOutputLines = dotnetBuildOutput.Split([global::System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries);
|
||||
var foundIssue = false;
|
||||
foreach (var buildOutputLine in dotnetBuildOutputLines)
|
||||
{
|
||||
if(buildOutputLine.Contains(" error ") || buildOutputLine.Contains("#warning"))
|
||||
{
|
||||
if(!foundIssue)
|
||||
{
|
||||
foundIssue = true;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("- Build has issues:");
|
||||
}
|
||||
|
||||
Console.Write(" - ");
|
||||
Console.WriteLine(buildOutputLine);
|
||||
}
|
||||
}
|
||||
|
||||
if(foundIssue)
|
||||
Console.WriteLine();
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" completed successfully.");
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare the .NET artifact to be used by Tauri as sidecar:
|
||||
//
|
||||
var os = Environment.GetOS();
|
||||
var tauriSidecarArtifactName = rid switch
|
||||
{
|
||||
RID.WIN_X64 => "mindworkAIStudioServer-x86_64-pc-windows-msvc.exe",
|
||||
RID.WIN_ARM64 => "mindworkAIStudioServer-aarch64-pc-windows-msvc.exe",
|
||||
|
||||
RID.LINUX_X64 => "mindworkAIStudioServer-x86_64-unknown-linux-gnu",
|
||||
RID.LINUX_ARM64 => "mindworkAIStudioServer-aarch64-unknown-linux-gnu",
|
||||
|
||||
RID.OSX_ARM64 => "mindworkAIStudioServer-aarch64-apple-darwin",
|
||||
RID.OSX_X64 => "mindworkAIStudioServer-x86_64-apple-darwin",
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tauriSidecarArtifactName))
|
||||
{
|
||||
Console.WriteLine($"- Error: Unsupported rid '{rid.AsMicrosoftRid()}'.");
|
||||
return;
|
||||
}
|
||||
var rid = Environment.GetCurrentRid();
|
||||
|
||||
var dotnetArtifactPath = Path.Combine(pathApp, "bin", "dist");
|
||||
if(!Directory.Exists(dotnetArtifactPath))
|
||||
Directory.CreateDirectory(dotnetArtifactPath);
|
||||
|
||||
var dotnetArtifactFilename = os switch
|
||||
Console.WriteLine("==============================");
|
||||
await this.UpdateArchitecture(rid);
|
||||
|
||||
var pdfiumVersion = await this.ReadPdfiumVersion();
|
||||
await Pdfium.InstallAsync(rid, pdfiumVersion);
|
||||
|
||||
Console.Write($"- Start .NET build for {rid.ToUserFriendlyName()} ...");
|
||||
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 dotnetBuildOutputLines = dotnetBuildOutput.Split([global::System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries);
|
||||
var foundIssue = false;
|
||||
foreach (var buildOutputLine in dotnetBuildOutputLines)
|
||||
{
|
||||
if(buildOutputLine.Contains(" error ") || buildOutputLine.Contains("#warning"))
|
||||
{
|
||||
"windows" => "mindworkAIStudio.exe",
|
||||
_ => "mindworkAIStudio",
|
||||
};
|
||||
|
||||
var dotnetPublishedPath = Path.Combine(pathApp, "bin", "release", Environment.DOTNET_VERSION, rid.AsMicrosoftRid(), "publish", dotnetArtifactFilename);
|
||||
var finalDestination = Path.Combine(dotnetArtifactPath, tauriSidecarArtifactName);
|
||||
|
||||
if(File.Exists(dotnetPublishedPath))
|
||||
Console.WriteLine("- Published .NET artifact found.");
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"- Error: Published .NET artifact not found: '{dotnetPublishedPath}'.");
|
||||
return;
|
||||
}
|
||||
if(!foundIssue)
|
||||
{
|
||||
foundIssue = true;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("- Build has issues:");
|
||||
}
|
||||
|
||||
Console.Write($"- Move the .NET artifact to the Tauri sidecar destination ...");
|
||||
try
|
||||
{
|
||||
File.Move(dotnetPublishedPath, finalDestination, true);
|
||||
Console.WriteLine(" done.");
|
||||
Console.Write(" - ");
|
||||
Console.WriteLine(buildOutputLine);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(" failed.");
|
||||
Console.WriteLine($" - Error: {e.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(foundIssue)
|
||||
Console.WriteLine();
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" completed successfully.");
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare the .NET artifact to be used by Tauri as sidecar:
|
||||
//
|
||||
var os = Environment.GetOS();
|
||||
var tauriSidecarArtifactName = rid switch
|
||||
{
|
||||
RID.WIN_X64 => "mindworkAIStudioServer-x86_64-pc-windows-msvc.exe",
|
||||
RID.WIN_ARM64 => "mindworkAIStudioServer-aarch64-pc-windows-msvc.exe",
|
||||
|
||||
RID.LINUX_X64 => "mindworkAIStudioServer-x86_64-unknown-linux-gnu",
|
||||
RID.LINUX_ARM64 => "mindworkAIStudioServer-aarch64-unknown-linux-gnu",
|
||||
|
||||
RID.OSX_ARM64 => "mindworkAIStudioServer-aarch64-apple-darwin",
|
||||
RID.OSX_X64 => "mindworkAIStudioServer-x86_64-apple-darwin",
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tauriSidecarArtifactName))
|
||||
{
|
||||
Console.WriteLine($"- Error: Unsupported rid '{rid.AsMicrosoftRid()}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
var dotnetArtifactPath = Path.Combine(pathApp, "bin", "dist");
|
||||
if(!Directory.Exists(dotnetArtifactPath))
|
||||
Directory.CreateDirectory(dotnetArtifactPath);
|
||||
|
||||
var dotnetArtifactFilename = os switch
|
||||
{
|
||||
"windows" => "mindworkAIStudio.exe",
|
||||
_ => "mindworkAIStudio",
|
||||
};
|
||||
|
||||
var dotnetPublishedPath = Path.Combine(pathApp, "bin", "release", Environment.DOTNET_VERSION, rid.AsMicrosoftRid(), "publish", dotnetArtifactFilename);
|
||||
var finalDestination = Path.Combine(dotnetArtifactPath, tauriSidecarArtifactName);
|
||||
|
||||
if(File.Exists(dotnetPublishedPath))
|
||||
Console.WriteLine("- Published .NET artifact found.");
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"- Error: Published .NET artifact not found: '{dotnetPublishedPath}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write($"- Move the .NET artifact to the Tauri sidecar destination ...");
|
||||
try
|
||||
{
|
||||
File.Move(dotnetPublishedPath, finalDestination, true);
|
||||
Console.WriteLine(" done.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(" failed.");
|
||||
Console.WriteLine($" - Error: {e.Message}");
|
||||
}
|
||||
|
||||
//
|
||||
// Build the Rust project / runtime:
|
||||
//
|
||||
|
||||
Console.WriteLine("==============================");
|
||||
Console.WriteLine("- Start building the Rust runtime ...");
|
||||
|
||||
var pathRuntime = Environment.GetRustRuntimeDirectory();
|
||||
@ -314,6 +311,18 @@ public sealed partial class UpdateMetadataCommands
|
||||
await File.WriteAllTextAsync(changelogCodePath, changelogCode, Environment.UTF8_NO_BOM);
|
||||
Console.WriteLine(" done.");
|
||||
}
|
||||
|
||||
private async Task<string> ReadPdfiumVersion()
|
||||
{
|
||||
const int PDFIUM_VERSION_INDEX = 10;
|
||||
|
||||
var pathMetadata = Environment.GetMetadataPath();
|
||||
var lines = await File.ReadAllLinesAsync(pathMetadata, Encoding.UTF8);
|
||||
var currentPdfiumVersion = lines[PDFIUM_VERSION_INDEX].Trim();
|
||||
var shortVersion = currentPdfiumVersion.Split('.')[2];
|
||||
|
||||
return shortVersion;
|
||||
}
|
||||
|
||||
private async Task UpdateArchitecture(RID rid)
|
||||
{
|
||||
@ -321,7 +330,7 @@ public sealed partial class UpdateMetadataCommands
|
||||
|
||||
var pathMetadata = Environment.GetMetadataPath();
|
||||
var lines = await File.ReadAllLinesAsync(pathMetadata, Encoding.UTF8);
|
||||
Console.Write("- Updating architecture ...");
|
||||
Console.Write($"- Updating architecture to {rid.ToUserFriendlyName()} ...");
|
||||
lines[ARCHITECTURE_INDEX] = rid.AsMicrosoftRid();
|
||||
|
||||
await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
|
||||
|
@ -17,7 +17,7 @@ public sealed class UpdateWebAssetsCommand
|
||||
Console.WriteLine("=========================");
|
||||
Console.Write("- Updating web assets ...");
|
||||
|
||||
var rid = Environment.GetRidsForCurrentOS().First();
|
||||
var rid = Environment.GetCurrentRid();
|
||||
var cwd = Environment.GetAIStudioDirectory();
|
||||
var contentPath = Path.Join(cwd, "bin", "release", Environment.DOTNET_VERSION, rid.AsMicrosoftRid(), "publish", "wwwroot", "_content");
|
||||
var isMudBlazorDirectoryPresent = Directory.Exists(Path.Join(contentPath, "MudBlazor"));
|
||||
|
@ -76,4 +76,38 @@ public static class Environment
|
||||
Console.WriteLine($"Error: Unsupported OS '{RuntimeInformation.OSDescription}'");
|
||||
return [];
|
||||
}
|
||||
|
||||
public static RID GetCurrentRid()
|
||||
{
|
||||
var arch = RuntimeInformation.ProcessArchitecture;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return arch switch
|
||||
{
|
||||
Architecture.X64 => RID.WIN_X64,
|
||||
Architecture.Arm64 => RID.WIN_ARM64,
|
||||
|
||||
_ => RID.NONE,
|
||||
};
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
return arch switch
|
||||
{
|
||||
Architecture.X64 => RID.OSX_X64,
|
||||
Architecture.Arm64 => RID.OSX_ARM64,
|
||||
|
||||
_ => RID.NONE,
|
||||
};
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return arch switch
|
||||
{
|
||||
Architecture.X64 => RID.LINUX_X64,
|
||||
Architecture.Arm64 => RID.LINUX_ARM64,
|
||||
|
||||
_ => RID.NONE,
|
||||
};
|
||||
|
||||
Console.WriteLine($"Error: Unsupported OS '{RuntimeInformation.OSDescription}'");
|
||||
return RID.NONE;
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LM/@EntryIndexedValue">LM</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MSG/@EntryIndexedValue">MSG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PDF/@EntryIndexedValue">PDF</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RAG/@EntryIndexedValue">RAG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RID/@EntryIndexedValue">RID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TB/@EntryIndexedValue">TB</s:String>
|
||||
|
@ -631,6 +631,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can
|
||||
-- Provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider"
|
||||
|
||||
-- Use PDF content as input
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T2849276709"] = "Use PDF content as input"
|
||||
|
||||
-- Select PDF file
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T63272795"] = "Select PDF file"
|
||||
|
||||
-- The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1164201762"] = "The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used."
|
||||
|
||||
@ -2116,6 +2122,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T228561878"] = "In order to use any LLM
|
||||
-- The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK."
|
||||
|
||||
-- Used PDFium version
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Used PDFium version"
|
||||
|
||||
-- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "This library is used to determine the language of the operating system. This is necessary to set the language of the user interface."
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
@attribute [Route(Routes.ASSISTANT_LEGAL_CHECK)]
|
||||
@using AIStudio.Settings.DataModel
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogLegalCheck>
|
||||
|
||||
@if (!this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)
|
||||
@ -6,6 +7,11 @@
|
||||
<ReadWebContent @bind-Content="@this.inputLegalDocument" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" Preselect="@(this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions && this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader)" PreselectContentCleanerAgent="@(this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions && this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent)"/>
|
||||
}
|
||||
|
||||
@if (PreviewFeatures.PRE_READ_PDF_2025.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
<ReadPDFContent @bind-PDFContent="@this.inputLegalDocument"/>
|
||||
}
|
||||
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputLegalDocument" Validation="@this.ValidatingLegalDocument" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Legal document")" Variant="Variant.Outlined" Lines="12" AutoGrow="@true" MaxLines="24" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputQuestions" Validation="@this.ValidatingQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionAnswer" Adornment="Adornment.Start" Label="@T("Your questions")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
@ -1,4 +1,5 @@
|
||||
@attribute [Route(Routes.ASSISTANT_SUMMARIZER)]
|
||||
@using AIStudio.Settings.DataModel
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogTextSummarizer>
|
||||
|
||||
@if (!this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)
|
||||
@ -6,6 +7,11 @@
|
||||
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" Preselect="@(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions && this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader)" PreselectContentCleanerAgent="@(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions && this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent)"/>
|
||||
}
|
||||
|
||||
@if (PreviewFeatures.PRE_READ_PDF_2025.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
<ReadPDFContent @bind-PDFContent="@this.inputText"/>
|
||||
}
|
||||
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" />
|
||||
<EnumSelection T="Complexity" NameFunc="@(complexity => complexity.Name())" @bind-Value="@this.selectedComplexity" Icon="@Icons.Material.Filled.Layers" Label="@T("Target complexity")" AllowOther="@true" @bind-OtherInput="@this.expertInField" OtherValue="Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS" LabelOther="@T("Your expertise")" ValidateOther="@this.ValidateExpertInField" />
|
||||
|
@ -1,4 +1,5 @@
|
||||
@attribute [Route(Routes.ASSISTANT_TRANSLATION)]
|
||||
@using AIStudio.Settings.DataModel
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogTranslation>
|
||||
|
||||
@if (!this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)
|
||||
@ -6,6 +7,11 @@
|
||||
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" Preselect="@(this.SettingsManager.ConfigurationData.Translation.PreselectOptions && this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader)" PreselectContentCleanerAgent="@(this.SettingsManager.ConfigurationData.Translation.PreselectOptions && this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent)"/>
|
||||
}
|
||||
|
||||
@if (PreviewFeatures.PRE_READ_PDF_2025.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
<ReadPDFContent @bind-PDFContent="@this.inputText"/>
|
||||
}
|
||||
|
||||
<MudTextSwitch Label="@T("Live translation")" @bind-Value="@this.liveTranslation" LabelOn="@T("Live translation")" LabelOff="@T("No live translation")"/>
|
||||
@if (this.liveTranslation)
|
||||
{
|
||||
|
4
app/MindWork AI Studio/Components/ReadPDFContent.razor
Normal file
4
app/MindWork AI Studio/Components/ReadPDFContent.razor
Normal file
@ -0,0 +1,4 @@
|
||||
@inherits MSGComponentBase
|
||||
<MudButton StartIcon="@Icons.Material.Filled.Description" OnClick="async () => await this.SelectFile()" Variant="Variant.Filled" Class="mb-3">
|
||||
@T("Use PDF content as input")
|
||||
</MudButton>
|
33
app/MindWork AI Studio/Components/ReadPDFContent.razor.cs
Normal file
33
app/MindWork AI Studio/Components/ReadPDFContent.razor.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public partial class ReadPDFContent : MSGComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string PDFContent { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> PDFContentChanged { get; set; }
|
||||
|
||||
[Inject]
|
||||
private RustService RustService { get; init; } = null!;
|
||||
|
||||
private async Task SelectFile()
|
||||
{
|
||||
var pdfFile = await this.RustService.SelectFile(T("Select PDF file"));
|
||||
if (pdfFile.UserCancelled)
|
||||
return;
|
||||
|
||||
if (!pdfFile.SelectedFilePath.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
if(!File.Exists(pdfFile.SelectedFilePath))
|
||||
return;
|
||||
|
||||
var pdfText = await this.RustService.GetPDFText(pdfFile.SelectedFilePath);
|
||||
await this.PDFContentChanged.InvokeAsync(pdfText);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
@inherits MSGComponentBase
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<MudPaper Class="pa-3 mb-3 border-dashed border rounded-lg">
|
||||
<MudTextSwitch Label="@T("Read content from web?")" Disabled="@this.AgentIsRunning" @bind-Value="@this.showWebContentReader" LabelOn="@T("Show web content options")" LabelOff="@T("Hide web content options")" />
|
||||
@if (this.showWebContentReader)
|
||||
{
|
||||
|
@ -80,6 +80,7 @@
|
||||
<MetaTauriVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 7 ])</MetaTauriVersion>
|
||||
<MetaAppCommitHash>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 8 ])</MetaAppCommitHash>
|
||||
<MetaArchitecture>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 9 ])</MetaArchitecture>
|
||||
<MetaPdfiumVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 10 ])</MetaPdfiumVersion>
|
||||
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
|
||||
@ -104,6 +105,9 @@
|
||||
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataArchitecture">
|
||||
<_Parameter1>$(MetaArchitecture)</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataLibraries">
|
||||
<_Parameter1>$(MetaPdfiumVersion)</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
@ -18,6 +18,7 @@
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@VersionDotnetSdk"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Memory" Text="@VersionDotnetRuntime"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@VersionRust"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.DocumentScanner" Text="@VersionPdfium"/>
|
||||
<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.Translate" Text="@this.OSLanguage"/>
|
||||
@ -111,6 +112,7 @@
|
||||
<ThirdPartyComponent Name="rcgen" Developer="RustTLS developers, est31 & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/rustls/rcgen/blob/main/LICENSE" RepositoryUrl="https://github.com/rustls/rcgen" UseCase="@T("For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose.")"/>
|
||||
<ThirdPartyComponent Name="file-format" Developer="Mickaël Malécot & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/mmalecot/file-format/blob/main/LICENSE-MIT" RepositoryUrl="https://github.com/mmalecot/file-format" UseCase="@T("This library is used to determine the file type of a file. This is necessary, e.g., when we want to stream a file.")"/>
|
||||
<ThirdPartyComponent Name="calamine" Developer="Johann Tuffe, Joel Natividad, Eric Jolibois, Dmitriy & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/tafia/calamine/blob/master/LICENSE-MIT.md" RepositoryUrl="https://github.com/tafia/calamine" UseCase="@T("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.")"/>
|
||||
<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="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="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.")" />
|
||||
|
@ -21,7 +21,8 @@ public partial class About : MSGComponentBase
|
||||
|
||||
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
|
||||
private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute<MetaDataAttribute>()!;
|
||||
private static readonly MetaDataArchitecture META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitecture>()!;
|
||||
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
|
||||
private static readonly MetaDataLibrariesAttribute META_DATA_LIBRARIES = ASSEMBLY.GetCustomAttribute<MetaDataLibrariesAttribute>()!;
|
||||
|
||||
private string osLanguage = string.Empty;
|
||||
|
||||
@ -40,6 +41,8 @@ public partial class About : MSGComponentBase
|
||||
private string VersionDotnetSdk => $"{T("Used .NET SDK")}: v{META_DATA.DotnetSdkVersion}";
|
||||
|
||||
private string BuildTime => $"{T("Build time")}: {META_DATA.BuildTime}";
|
||||
|
||||
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
|
||||
|
||||
private GetLogPathsResponse logPaths;
|
||||
|
||||
|
@ -633,6 +633,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "Hier ka
|
||||
-- Provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Anbieter"
|
||||
|
||||
-- Use PDF content as input
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T2849276709"] = "PDF-Inhalt als Eingabe verwenden"
|
||||
|
||||
-- Select PDF file
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T63272795"] = "PDF-Datei auswählen"
|
||||
|
||||
-- The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1164201762"] = "Der Inhalt wird mithilfe eines LLM-Agents bereinigt: Der Hauptinhalt wird extrahiert, Werbung und andere irrelevante Elemente werden nach Möglichkeit entfernt. Relative Links werden nach Möglichkeit in absolute Links umgewandelt, damit sie verwendet werden können."
|
||||
|
||||
@ -2118,6 +2124,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T228561878"] = "Um ein beliebiges LLM n
|
||||
-- The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "Die Programmiersprache C# wird für die Umsetzung der Benutzeroberfläche und des Backends verwendet. Für die Entwicklung der Benutzeroberfläche mit C# kommt die Blazor-Technologie aus ASP.NET Core zum Einsatz. Alle diese Technologien sind im .NET SDK integriert."
|
||||
|
||||
-- Used PDFium version
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Verwendete PDFium-Version"
|
||||
|
||||
-- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "Diese Bibliothek wird verwendet, um die Sprache des Betriebssystems zu erkennen. Dies ist notwendig, um die Sprache der Benutzeroberfläche einzustellen."
|
||||
|
||||
|
@ -633,6 +633,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can
|
||||
-- Provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider"
|
||||
|
||||
-- Use PDF content as input
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T2849276709"] = "Use PDF content as input"
|
||||
|
||||
-- Select PDF file
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READPDFCONTENT::T63272795"] = "Select PDF file"
|
||||
|
||||
-- The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1164201762"] = "The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used."
|
||||
|
||||
@ -2118,6 +2124,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T228561878"] = "In order to use any LLM
|
||||
-- The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK."
|
||||
|
||||
-- Used PDFium version
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Used PDFium version"
|
||||
|
||||
-- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "This library is used to determine the language of the operating system. This is necessary to set the language of the user interface."
|
||||
|
||||
@ -2519,3 +2528,4 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T3948127789"] = "Suggestion"
|
||||
|
||||
-- Your stage directions
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::WRITER::T779923726"] = "Your stage directions"
|
||||
|
||||
|
@ -10,4 +10,5 @@ public enum PreviewFeatures
|
||||
PRE_RAG_2024,
|
||||
|
||||
PRE_PLUGINS_2025,
|
||||
PRE_READ_PDF_2025,
|
||||
}
|
@ -6,7 +6,9 @@ public static class PreviewFeaturesExtensions
|
||||
{
|
||||
PreviewFeatures.PRE_WRITER_MODE_2024 => "Writer Mode: Experiments about how to write long texts using AI",
|
||||
PreviewFeatures.PRE_RAG_2024 => "RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company",
|
||||
|
||||
PreviewFeatures.PRE_PLUGINS_2025 => "Plugins: Preview of our plugin system where you can extend the functionality of the app",
|
||||
PreviewFeatures.PRE_READ_PDF_2025 => "Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files",
|
||||
|
||||
_ => "Unknown preview feature"
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ public static class PreviewVisibilityExtensions
|
||||
|
||||
if (visibility >= PreviewVisibility.PROTOTYPE)
|
||||
{
|
||||
features.Add(PreviewFeatures.PRE_READ_PDF_2025);
|
||||
features.Add(PreviewFeatures.PRE_RAG_2024);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
namespace AIStudio.Tools.Metadata;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly)]
|
||||
public class MetaDataArchitecture(string architecture) : Attribute
|
||||
public class MetaDataArchitectureAttribute(string architecture) : Attribute
|
||||
{
|
||||
public string Architecture => architecture;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace AIStudio.Tools.Metadata;
|
||||
|
||||
public class MetaDataLibrariesAttribute(string pdfiumVersion) : Attribute
|
||||
{
|
||||
public string PdfiumVersion => pdfiumVersion;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
namespace AIStudio.Tools.Services;
|
||||
|
||||
public sealed partial class RustService
|
||||
{
|
||||
public async Task<string> GetPDFText(string filePath)
|
||||
{
|
||||
var response = await this.http.GetAsync($"/retrieval/fs/read/pdf?file_path={filePath}");
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
this.logger!.LogError($"Failed to read the PDF file due to an network error: '{response.StatusCode}'");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
# v0.9.42, build 217 (2025-05-xx xx:xx UTC)
|
||||
- Added the writing style "Changelog" to the rewrite & improve text assistant. This helps to create changelogs for your projects.
|
||||
- Added an option to load PDF files directly into the translation, text summarization, and legal check assistants as a preview prototype for testing before release.
|
||||
- Improved the model selection for OpenAI by removing all `o1-pro` models. These models cannot be used right now, since OpenAI introduced a new API, which is not yet supported by MindWork AI Studio.
|
||||
- Improved the internal plugin maintenance so that removed resources are now removed from the file system.
|
||||
- Improved the app settings to apply the chosen language immediately.
|
||||
- Fixed an issue where empty lines in source code were being ignored by the Markdown renderer. Thanks My Nihongo for fixing this bug in the `MudBlazor.Markdown` repository.
|
||||
- Fixed the localization assistant not being able to load the localization file when used in the release app.
|
||||
- Upgraded .NET dependencies.
|
||||
- Upgraded Rust & .NET dependencies.
|
@ -7,4 +7,5 @@
|
||||
8.5.1
|
||||
1.8.1
|
||||
47b6a896851, release
|
||||
osx-arm64
|
||||
osx-arm64
|
||||
137.0.7123.0
|
34
runtime/Cargo.lock
generated
34
runtime/Cargo.lock
generated
@ -188,6 +188,12 @@ dependencies = [
|
||||
"system-deps 6.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi_simd"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4790f9e8961209112beb783d85449b508673cf4a6a419c8449b210743ac4dbe9"
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.5.3"
|
||||
@ -430,15 +436,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "calamine"
|
||||
version = "0.26.1"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138646b9af2c5d7f1804ea4bf93afc597737d2bd4f7341d67c48b03316976eb1"
|
||||
checksum = "6d80f81ba5c68206b9027e62346d49dc26fb32ffc4fe6ef7022a8ae21d348ccb"
|
||||
dependencies = [
|
||||
"atoi_simd",
|
||||
"byteorder",
|
||||
"codepage",
|
||||
"encoding_rs",
|
||||
"fast-float2",
|
||||
"log",
|
||||
"quick-xml 0.31.0",
|
||||
"quick-xml 0.37.5",
|
||||
"serde",
|
||||
"zip 2.5.0",
|
||||
]
|
||||
@ -1064,6 +1072,12 @@ dependencies = [
|
||||
"zune-inflate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fast-float2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.1.0"
|
||||
@ -3200,9 +3214,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfium-render"
|
||||
version = "0.8.30"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2773a939ec2c736640f5f2e62a325c2e1a997d694961c50f17cadfb4c8682e84"
|
||||
checksum = "a473e1f4c2630f7240b127eb9efebd1d9e55053015b624bfe9dbeae0299947e1"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bytemuck",
|
||||
@ -3563,20 +3577,20 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
|
||||
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.32.0"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
|
@ -34,8 +34,8 @@ hmac = "0.12.1"
|
||||
sha2 = "0.10.8"
|
||||
rcgen = { version = "0.13.2", features = ["pem"] }
|
||||
file-format = "0.26.0"
|
||||
calamine = "0.26.1"
|
||||
pdfium-render = "0.8.30"
|
||||
calamine = "0.27.0"
|
||||
pdfium-render = "0.8.31"
|
||||
sys-locale = "0.3.2"
|
||||
|
||||
# Fixes security vulnerability downstream, where the upstream is not fixed yet:
|
||||
|
@ -7,13 +7,14 @@ use rocket::serde::json::Json;
|
||||
use rocket::serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use tauri::updater::UpdateResponse;
|
||||
use tauri::{Manager, Window};
|
||||
use tauri::{Manager, PathResolver, Window};
|
||||
use tauri::api::dialog::blocking::FileDialogBuilder;
|
||||
use tokio::time;
|
||||
use crate::api_token::APIToken;
|
||||
use crate::dotnet::stop_dotnet_server;
|
||||
use crate::environment::{is_prod, CONFIG_DIRECTORY, DATA_DIRECTORY};
|
||||
use crate::log::switch_to_file_logging;
|
||||
use crate::metadata::META_DATA;
|
||||
|
||||
/// The Tauri main window.
|
||||
static MAIN_WINDOW: Lazy<Mutex<Option<Window>>> = Lazy::new(|| Mutex::new(None));
|
||||
@ -39,6 +40,7 @@ pub fn start_tauri() {
|
||||
info!(Source = "Bootloader Tauri"; "Reconfigure the file logger to use the app data directory {data_path:?}");
|
||||
switch_to_file_logging(data_path).map_err(|e| error!("Failed to switch logging to file: {e}")).unwrap();
|
||||
|
||||
deploy_pdfium(app.path_resolver());
|
||||
Ok(())
|
||||
})
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
@ -319,4 +321,50 @@ pub struct PreviousFile {
|
||||
pub struct FileSelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_file_path: String,
|
||||
}
|
||||
|
||||
fn deploy_pdfium(path_resolver: PathResolver) {
|
||||
info!(Source = "Bootloader Tauri"; "Deploy PDFium from the resources...");
|
||||
let working_directory = std::env::current_dir().unwrap();
|
||||
let pdfium_target_path = working_directory;
|
||||
let metadata = &META_DATA;
|
||||
let metadata = metadata.lock().unwrap();
|
||||
let arch = metadata.clone().unwrap().architecture;
|
||||
let pdfium_filename = match arch.as_str() {
|
||||
"linux-x64" => Some("libpdfium.so"),
|
||||
"linux-arm64" => Some("libpdfium.so"),
|
||||
|
||||
"win-x64" => Some("pdfium.dll"),
|
||||
"win-arm64" => Some("pdfium.dll"),
|
||||
|
||||
"osx-x64" => Some("libpdfium.dylib"),
|
||||
"osx-arm64" => Some("libpdfium.dylib"),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if pdfium_filename.is_none() {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to find the PDFium library for the current platform.");
|
||||
return;
|
||||
}
|
||||
|
||||
let pdfium_filename = pdfium_filename.unwrap();
|
||||
let pdfium_relative_source_path = String::from("resources/libraries/") + pdfium_filename;
|
||||
let pdfium_source_path = path_resolver.resolve_resource(pdfium_relative_source_path);
|
||||
if pdfium_source_path.is_none() {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to find the PDFium library for the current platform.");
|
||||
return;
|
||||
}
|
||||
|
||||
let pdfium_source_path = pdfium_source_path.unwrap();
|
||||
let pdfium_target_path = pdfium_target_path.join(pdfium_filename);
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Detected platform: {arch:?}, expected PDFium filename: {pdfium_filename:?}, source path: {pdfium_source_path:?}, target path: {pdfium_target_path:?}");
|
||||
|
||||
if let Err(e) = std::fs::copy(pdfium_source_path, pdfium_target_path) {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to copy the PDFium library for the current platform: {e}");
|
||||
return;
|
||||
}
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Successfully deployed PDFium.");
|
||||
}
|
@ -15,6 +15,7 @@ use rocket::response::stream::{EventStream, Event};
|
||||
use rocket::tokio::select;
|
||||
use rocket::serde::Serialize;
|
||||
use rocket::get;
|
||||
use crate::api_token::APIToken;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Chunk {
|
||||
@ -39,7 +40,7 @@ type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>
|
||||
type ChunkStream = Pin<Box<dyn Stream<Item = Result<Chunk>> + Send>>;
|
||||
|
||||
#[get("/retrieval/fs/extract?<path>")]
|
||||
pub async fn extract_data(path: String, mut end: Shutdown) -> EventStream![] {
|
||||
pub async fn extract_data(_token: APIToken, path: String, mut end: Shutdown) -> EventStream![] {
|
||||
EventStream! {
|
||||
let stream_result = stream_data(&path).await;
|
||||
match stream_result {
|
||||
@ -78,7 +79,7 @@ async fn stream_data(file_path: &str) -> Result<ChunkStream> {
|
||||
FileFormat::from_file(&file_path_clone)
|
||||
}).await??;
|
||||
|
||||
let ext = file_path.split('.').last().unwrap_or("");
|
||||
let ext = file_path.split('.').next_back().unwrap_or("");
|
||||
let stream = match ext {
|
||||
DOCX | ODT => {
|
||||
let from = if ext == DOCX { "docx" } else { "odt" };
|
||||
@ -91,7 +92,7 @@ async fn stream_data(file_path: &str) -> Result<ChunkStream> {
|
||||
|
||||
_ => match fmt.kind() {
|
||||
Kind::Document => match fmt {
|
||||
FileFormat::PortableDocumentFormat => read_pdf(file_path).await?,
|
||||
FileFormat::PortableDocumentFormat => stream_pdf(file_path).await?,
|
||||
FileFormat::MicrosoftWordDocument => {
|
||||
convert_with_pandoc(file_path, "docx", TO_MARKDOWN).await?
|
||||
}
|
||||
@ -133,7 +134,7 @@ async fn stream_text_file(file_path: &str) -> Result<ChunkStream> {
|
||||
let mut line_number = 0;
|
||||
|
||||
let stream = stream! {
|
||||
while let Ok(Some(line)) = lines.next_line().await { // Korrektur hier
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
line_number += 1;
|
||||
yield Ok(Chunk {
|
||||
content: line,
|
||||
@ -145,23 +146,47 @@ async fn stream_text_file(file_path: &str) -> Result<ChunkStream> {
|
||||
Ok(Box::pin(stream))
|
||||
}
|
||||
|
||||
async fn read_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
#[get("/retrieval/fs/read/pdf?<file_path>")]
|
||||
pub fn read_pdf(_token: APIToken, file_path: String) -> String {
|
||||
let pdfium = Pdfium::default();
|
||||
let doc = match pdfium.load_pdf_from_file(&file_path, None) {
|
||||
Ok(document) => document,
|
||||
Err(e) => return e.to_string(),
|
||||
};
|
||||
|
||||
let mut pdf_content = String::new();
|
||||
for page in doc.pages().iter() {
|
||||
let content = match page.text().map(|text_content| text_content.all()) {
|
||||
Ok(content) => content,
|
||||
Err(_) => {
|
||||
continue
|
||||
}
|
||||
};
|
||||
|
||||
pdf_content.push_str(&content);
|
||||
pdf_content.push_str("\n\n");
|
||||
}
|
||||
|
||||
pdf_content
|
||||
}
|
||||
|
||||
async fn stream_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
let path = file_path.to_owned();
|
||||
let (tx, rx) = mpsc::channel(10);
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let pdfium = Pdfium::default();
|
||||
let doc = match pdfium.load_pdf_from_file(&path, None) {
|
||||
Ok(d) => d,
|
||||
Ok(document) => document,
|
||||
Err(e) => {
|
||||
let _ = tx.blocking_send(Err(e.into()));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for (i, page) in doc.pages().iter().enumerate() {
|
||||
for (num_page, page) in doc.pages().iter().enumerate() {
|
||||
let content = match page.text().map(|t| t.all()) {
|
||||
Ok(c) => c,
|
||||
Ok(text_content) => text_content,
|
||||
Err(e) => {
|
||||
let _ = tx.blocking_send(Err(e.into()));
|
||||
continue;
|
||||
@ -170,7 +195,7 @@ async fn read_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
|
||||
if tx.blocking_send(Ok(Chunk {
|
||||
content,
|
||||
metadata: Metadata::Pdf { page_number: i + 1 },
|
||||
metadata: Metadata::Pdf { page_number: num_page + 1 },
|
||||
})).is_err() {
|
||||
break;
|
||||
}
|
||||
|
@ -9,4 +9,5 @@ pub mod secret;
|
||||
pub mod clipboard;
|
||||
pub mod runtime_api;
|
||||
pub mod certificate;
|
||||
pub mod file_data;
|
||||
pub mod file_data;
|
||||
pub mod metadata;
|
@ -10,6 +10,7 @@ use mindwork_ai_studio::certificate::{generate_certificate};
|
||||
use mindwork_ai_studio::dotnet::start_dotnet_server;
|
||||
use mindwork_ai_studio::environment::is_dev;
|
||||
use mindwork_ai_studio::log::init_logging;
|
||||
use mindwork_ai_studio::metadata::{MetaData, META_DATA};
|
||||
use mindwork_ai_studio::runtime_api::start_runtime_api;
|
||||
|
||||
#[tokio::main]
|
||||
@ -26,6 +27,22 @@ async fn main() {
|
||||
let tauri_version = metadata_lines.next().unwrap();
|
||||
let app_commit_hash = metadata_lines.next().unwrap();
|
||||
let architecture = metadata_lines.next().unwrap();
|
||||
let pdfium_version = metadata_lines.next().unwrap();
|
||||
|
||||
let metadata = MetaData {
|
||||
architecture: architecture.to_string(),
|
||||
app_commit_hash: app_commit_hash.to_string(),
|
||||
app_version: app_version.to_string(),
|
||||
build_number: build_number.to_string(),
|
||||
build_time: build_time.to_string(),
|
||||
dotnet_sdk_version: dotnet_sdk_version.to_string(),
|
||||
dotnet_version: dotnet_version.to_string(),
|
||||
mud_blazor_version: mud_blazor_version.to_string(),
|
||||
rust_version: rust_version.to_string(),
|
||||
tauri_version: tauri_version.to_string(),
|
||||
};
|
||||
|
||||
*META_DATA.lock().unwrap() = Some(metadata);
|
||||
|
||||
init_logging();
|
||||
info!("Starting MindWork AI Studio:");
|
||||
@ -40,6 +57,7 @@ async fn main() {
|
||||
info!(".. Rust: v{rust_version}");
|
||||
info!(".. MudBlazor: v{mud_blazor_version}");
|
||||
info!(".. Tauri: v{tauri_version}");
|
||||
info!(".. PDFium: v{pdfium_version}");
|
||||
|
||||
if is_dev() {
|
||||
warn!("Running in development mode.");
|
||||
|
18
runtime/src/metadata.rs
Normal file
18
runtime/src/metadata.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use std::sync::Mutex;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static META_DATA: Lazy<Mutex<Option<MetaData>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MetaData {
|
||||
pub app_version: String,
|
||||
pub build_time: String,
|
||||
pub build_number: String,
|
||||
pub dotnet_sdk_version: String,
|
||||
pub dotnet_version: String,
|
||||
pub rust_version: String,
|
||||
pub mud_blazor_version: String,
|
||||
pub tauri_version: String,
|
||||
pub app_commit_hash: String,
|
||||
pub architecture: String,
|
||||
}
|
@ -79,6 +79,7 @@ pub fn start_runtime_api() {
|
||||
crate::environment::get_config_directory,
|
||||
crate::environment::read_user_language,
|
||||
crate::file_data::extract_data,
|
||||
crate::file_data::read_pdf,
|
||||
crate::log::get_log_paths,
|
||||
])
|
||||
.ignite().await.unwrap()
|
||||
|
@ -29,6 +29,9 @@
|
||||
"scope": [
|
||||
"http://localhost"
|
||||
]
|
||||
},
|
||||
"fs": {
|
||||
"scope": ["$RESOURCE/resources/*"]
|
||||
}
|
||||
},
|
||||
"windows": [
|
||||
@ -57,6 +60,9 @@
|
||||
"externalBin": [
|
||||
"../app/MindWork AI Studio/bin/dist/mindworkAIStudioServer"
|
||||
],
|
||||
"resources": [
|
||||
"resources/*"
|
||||
],
|
||||
"macOS": {
|
||||
"exceptionDomain": "localhost"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user