Compare commits

..
135 Commits
Author SHA1 Message Date
Thorsten Sommer 8b0ee49ba9 Prepared release v0.9.53 (#576)
Build and Release / Read metadata (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 }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Prepare & create release (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 }}) (-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-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Publish release (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
2025-11-17 13:34:22 +01:00
Thorsten Sommer 45ac3eee2b Added command to update project commit hash (#575) 2025-11-17 13:28:00 +01:00
Thorsten Sommer 0b6c2f1041 Fixed mandatory parsing of API parameters (#574)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-11-17 13:13:19 +01:00
Thorsten Sommer 70fbc74a1d Prepared release v0.9.53 (#573)
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Publish 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 / Prepare & create release (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
2025-11-14 14:34:31 +01:00
Thorsten Sommer bac0b49dce Upgraded dependencies (#572)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-11-14 14:04:54 +01:00
Paul Koudelka cfb7fe403d Added support for GPT-5.1. (#570)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
2025-11-14 13:46:46 +01:00
Thorsten Sommer 164b07c629 Improved Pandoc installation checking (#571)
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
2025-11-14 13:34:30 +01:00
Paul Koudelkaandtsommer 473bfd068d Added functionality to add profiles via plugins (#569)
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
2025-11-14 12:04:01 +01:00
Sabrina-devops 120d5c808a Added the ability to use documents as input for profile fields (#568)
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
2025-11-13 18:20:41 +01:00
Peer SchüttandThorsten Sommer 9ef1a047f0 Added expert mode to providers (#562)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
2025-11-13 18:13:16 +01:00
Peer SchüttandThorsten Sommer d6f5dc143d Removed the character limit for profiles (#565)
Build and Release / Read metadata (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-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 / Prepare & create release (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 }}) (-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 / Publish release (push) Has been cancelled
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
2025-11-12 10:11:01 +01:00
Sabrina-devops d90a82de64 Updated the changelog (#567) 2025-11-12 10:07:21 +01:00
Sabrina-devops 9418b99275 Added export to word function for the chat (#566)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
2025-11-11 15:30:17 +01:00
Thorsten Sommer 37bd42e41f Prepared release v0.9.52 (#563)
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 }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (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 / Read metadata (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-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 / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
2025-10-24 08:38:40 +02:00
Thorsten Sommer 38103121c9 Extended managed configuration (#560)
Build and Release / Read metadata (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 / 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 / Publish release (push) Has been cancelled
2025-10-19 11:51:28 +02:00
Thorsten Sommer 9587a07556 Showing sources coming from data providers (#559)
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish 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 }}) (-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 }}) (-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 }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
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 / 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
2025-09-25 19:47:18 +02:00
Thorsten Sommer c3bbcacaed Updated README (#558)
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-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-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (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 / Publish release (push) Has been cancelled
Build and Release / Read metadata (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 }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
2025-09-05 11:17:51 +02:00
Thorsten Sommer f00722e0a6 Prepared release v0.9.51 (#557)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
2025-09-04 20:17:55 +02:00
Thorsten Sommer ce243913ed Fixed resetting profiles and chat templates on assistant reset (#556)
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-09-04 11:26:06 +02:00
Thorsten Sommer fc37882773 Fixed bottom margin for code blocks in chat (#555)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
2025-09-04 11:11:49 +02:00
Thorsten Sommer 864bda1213 Fixed #546: made Lua tables for config objects optional (#554)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-09-03 22:41:28 +02:00
Thorsten Sommer 73b2f1fa6a Upgraded MudBlazor (#553) 2025-09-03 22:28:51 +02:00
Thorsten Sommer d966929dca Improved the I18N & the German translation (#552)
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
2025-09-03 22:14:31 +02:00
Thorsten Sommer 6a37ce6d25 Improved provider logging (#551)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-09-03 21:25:17 +02:00
Thorsten Sommer 70e64f2d14 Fixed Dependabot security alert regarding tracing-subscriber crate (#550)
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-09-03 20:52:54 +02:00
Thorsten Sommer 38ec098430 Improved the OpenAI provider (#548)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
2025-09-03 10:08:04 +02:00
Peer Schüttandtsommer 4e167d58ea Fixed bugs in & related to the web content reader (#549)
Build and Release / Read metadata (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 / Prepare & create release (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-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (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 / Publish release (push) Has been cancelled
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
2025-09-01 19:13:02 +02:00
Thorsten Sommer f61fe87181 Fixed calling the workspace selection dialog (#547)
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-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-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Read metadata (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 }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
2025-08-31 14:45:03 +02:00
Peer Schüttandtsommer 2a01d3bb6e Added support for Perplexity (#545)
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Publish release (push) Blocked by required conditions
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
2025-08-31 14:27:35 +02:00
Peer SchüttandThorsten Sommer adf61a1384 Improving the text summarizer assistant (#544)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
2025-08-30 10:35:40 +02:00
Thorsten Sommer f1c2a65450 Made dialog parameter usage explicit with generic types (#543)
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 }}) (-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-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Build and Release / Read metadata (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-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
2025-08-28 18:51:44 +02:00
Thorsten Sommer e03289b680 Fixed input field header for single input dialog (#542)
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
2025-08-28 18:31:50 +02:00
Thorsten Sommer 99dc2606aa Improved input validation for the single input dialog (#541) 2025-08-28 18:16:30 +02:00
Thorsten Sommer e931e28ab1 Improved workspace handling (#540)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-08-28 16:44:32 +02:00
Thorsten Sommer 5d17dcc29b Added option for update installation behavior (#539)
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 }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Publish release (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 / Read metadata (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 }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (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
2025-08-26 20:06:13 +02:00
Thorsten Sommer c1826426d9 Refactored configuration objects (#538)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-08-26 10:59:56 +02:00
Thorsten Sommer be11efed67 Allow chat templates in config plugins (#537)
Build and Release / Read metadata (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-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-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (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 / Publish release (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 / Prepare & create release (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
2025-08-18 20:40:52 +02:00
Thorsten Sommer 7d10bb00f7 Applied several small fixes (#536)
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 / Publish release (push) Has been cancelled
Build and Release / Read metadata (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-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg 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-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (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
2025-08-15 21:16:51 +02:00
Thorsten Sommer 9ca2860079 Fixed resetting bug in assistants (#535)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-08-15 20:07:05 +02:00
Thorsten Sommer 28b470f40b Prepared release v0.9.50 (#534)
Build and Release / Read metadata (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-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis 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-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 / Publish release (push) Has been cancelled
2025-08-10 18:47:06 +02:00
Thorsten Sommer 6b61f34fff Upgraded dependencies (#533)
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
2025-08-10 18:32:38 +02:00
Thorsten Sommer 4197d5a0ee Fixed a profile selection visual bug in assistants (#532)
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
2025-08-10 17:59:49 +02:00
Thorsten Sommer 22aacff717 Improved the German translation (#531)
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-08-10 16:39:07 +02:00
Peer SchüttandThorsten Sommer b75d90b13f Added vLLM support (#524)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
2025-08-10 16:26:25 +02:00
Peer SchüttandThorsten Sommer fe2baa8c00 Hide the enterprise configuration details by default (#523)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
2025-08-10 15:59:44 +02:00
Thorsten Sommer 7d22b77d47 Updated Git ignore (#530)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
2025-08-09 20:28:40 +02:00
Thorsten Sommer 96c1c0653d Fixed Windows pipeline (#529)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-08-09 20:04:50 +02:00
Peer Schüttandtsommer 035412f7ff Adding providers can now be disabled using config plugins (#522)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
2025-08-09 19:29:43 +02:00
6116c03f7c Extension of the chat template (#521)
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 / Read metadata (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
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 / 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 / Prepare & create release (push) Has been cancelled
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
Co-authored-by: Thorsten Sommer <thorsten.sommer@dlr.de>
2025-07-11 09:57:46 +02:00
Thorsten Sommer 9c52812c09 Prepared release v0.9.49 (#520)
Build and Release / Read metadata (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 / 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 / Publish release (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 / 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
2025-07-02 14:15:35 +02:00
Thorsten Sommer be27fd84b8 Fixed chat bug causing the input box to occupy too much space (#519)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
2025-07-02 14:01:10 +02:00
Thorsten Sommer 61ffddf1ec Improved the loading of the about page (#518)
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-07-02 13:34:21 +02:00
Thorsten Sommer 6d1ecb7678 Improved PowerPoint implementation for reading slide data (#517)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-07-01 18:34:14 +02:00
Thorsten Sommer 68f5bb1512 Finished the function for importing arbitrary documents (#516) 2025-06-30 21:51:02 +02:00
aaedf667fe Allow loading any document in some assistants (#508)
Co-authored-by: krut_ni <nils.kruthoff@dlr.de>
Co-authored-by: Thorsten Sommer <mail@tsommer.org>
2025-06-30 18:56:48 +02:00
Thorsten Sommer 7df0b3e6e0 Refactored plugin settings handling for maintainability (#515) 2025-06-27 22:52:34 +02:00
Thorsten Sommer 1b8ed286e7 Fixed a bug with ERI data source retrieval process loading (#514) 2025-06-27 22:03:51 +02:00
Thorsten Sommer 87bb04e3c0 Improved text content phrasing in German and English (#513) 2025-06-27 21:40:39 +02:00
Thorsten Sommer 181ba07d2d Improved the loading of some components that require data fetching (#512) 2025-06-27 20:52:33 +02:00
Thorsten Sommer 3587f547b5 Refactored theme provider to replace obsolete calls (#511) 2025-06-27 20:03:28 +02:00
Thorsten Sommer cf17c643a0 Upgraded dependencies (#510) 2025-06-27 10:31:36 +02:00
Thorsten Sommer 7843426057 Fixed the web asset update logic in the build script (#509) 2025-06-27 10:02:32 +02:00
Thorsten Sommer 4db31fd9cf Added acknowledgment, docs, & final things for PowerPoint lib (#507) 2025-06-23 15:19:21 +02:00
nilskruthoffandkrut_ni 18b2e22725 Added support for reading PowerPoint files (#506)
Co-authored-by: krut_ni <nils.kruthoff@dlr.de>
2025-06-23 14:49:36 +02:00
Peer Schütt b6169e5bfb Changed chat time to local time format (#502) 2025-06-11 19:04:04 +02:00
Thorsten Sommer 4aeb51c9f1 Prepared release v0.9.48 (#501) 2025-06-11 10:20:49 +02:00
Peer Schütt 7c4ddf1164 Prepared release v0.9.48 (#500) 2025-06-10 15:40:25 +02:00
Peer Schütt 793a9cae0a Dont display <think> tags (#496) 2025-06-10 14:32:24 +02:00
Thorsten Sommer 368fc9ce39 Improved the German translation within the "send to" menu (#499) 2025-06-09 14:21:58 +02:00
Thorsten Sommer 2ef563e9ab Improved the confirmation dialog for longer texts (#498) 2025-06-09 14:13:31 +02:00
Thorsten Sommer 32e1ab977d Improved enterprise IT (#497) 2025-06-09 14:06:54 +02:00
Thorsten Sommer 7a498d524e Prepared release v0.9.47 (#495) 2025-06-02 20:29:09 +02:00
Thorsten Sommer ce915292dc Improved enterprise IT checks when run without such an environment (#494) 2025-06-02 20:22:15 +02:00
Thorsten Sommer 6979a73e5c Improved enterprise service (#493) 2025-06-02 20:08:25 +02:00
Thorsten Sommer fcf511cea8 Prepared release v0.9.46 (#492) 2025-06-01 21:27:13 +02:00
Thorsten Sommer e8cfce05fe Add enterprise config support via env vars & Windows registry (#491) 2025-06-01 21:14:21 +02:00
Thorsten Sommer b88b78a08e Improved plugin page (#490) 2025-05-31 17:28:25 +02:00
Thorsten Sommer 9a1b7853aa Updated README (#489) 2025-05-31 12:09:28 +02:00
Thorsten Sommer 69610ea908 Released plugin system, I18N support, and default language plugins (#488) 2025-05-31 12:04:58 +02:00
Thorsten Sommer 437da0fd9b Finished the Pandoc integration (#487) 2025-05-30 22:39:16 +02:00
nilskruthoffandThorsten Sommer 5b685193ef UI for Pandoc integration (#393)
Co-authored-by: Thorsten Sommer
2025-05-29 14:01:56 +02:00
Thorsten Sommer 1d31fd9a22 Add more text content to the I18N system (#486) 2025-05-28 23:14:05 +02:00
Thorsten Sommer e3c272b0c4 Added more text content to the I18N system (#485) 2025-05-26 20:50:24 +02:00
Thorsten Sommer 1e19c05c57 Add configuration for maximum matches per query across data sources (#484) 2025-05-26 19:53:31 +02:00
Thorsten Sommer c08881784d Prepared release v0.9.45 (#483) 2025-05-25 15:59:02 +02:00
Thorsten Sommer 05544eca15 Added support for Claude 4 models to Anthropic provider (#482) 2025-05-25 15:53:47 +02:00
Thorsten Sommer baa80beb92 Moved the workspace settings directly to the workspaces (#481) 2025-05-25 15:41:55 +02:00
Thorsten Sommer 801179e835 Refactored profile settings (#480) 2025-05-25 13:27:22 +02:00
Thorsten Sommer e3110820d2 Improved secret input fields by adding a toggle visibility feature (#479) 2025-05-25 12:21:23 +02:00
Thorsten Sommer e11c15dbab Updated the data source settings design (#478) 2025-05-25 10:47:08 +02:00
Thorsten Sommer fc7a4391cb Added Russian as a language option for assistants (#477) 2025-05-25 10:42:42 +02:00
Thorsten Sommer d2f85f31ea Moved chat template options to a setting dialog (#476) 2025-05-25 10:33:13 +02:00
Thorsten Sommer 9e207974e9 Finalized chat templates (#475) 2025-05-24 19:11:28 +02:00
Peer Schütt df062ae6e6 Added chat templates (#474) 2025-05-24 12:27:00 +02:00
Thorsten Sommer 35eebc08a5 Improved chat options by moving it to the chat interface (#473) 2025-05-21 20:23:44 +02:00
Thorsten Sommer 206706f77a Updated readme, build, and setup documentation for clarity and accuracy (#472) 2025-05-19 20:01:48 +02:00
Thorsten Sommer d87df5b044 Removed unused imports (#471) 2025-05-18 21:46:04 +02:00
Thorsten Sommer b9b850b2c1 Prepared release v0.9.44 (#470) 2025-05-18 21:37:54 +02:00
Thorsten Sommer 9aa0a91465 Added more text content to the localization (#469) 2025-05-18 21:31:15 +02:00
Thorsten Sommer 217d31bc44 Released PDF import feature (#468) 2025-05-18 13:50:53 +02:00
Thorsten Sommer 038ddec46b Upgraded dependencies to .NET 9.0.5 and Rust 1.87.0 (#467) 2025-05-17 21:07:29 +02:00
Thorsten Sommer d02efce689 Improved table views for providers, embeddings, and profiles (#466) 2025-05-17 20:54:51 +02:00
Thorsten Sommer 2e58ecb97d Fixed a rare bug regarding renaming chats (#465) 2025-05-17 20:35:51 +02:00
Thorsten Sommer a548cabe24 Improved compatibility with some Ubuntu linux versions (#464) 2025-05-17 19:53:08 +02:00
Thorsten Sommer 4b2da61a90 Fixed an issue that caused live translation to stop working (#463) 2025-05-17 19:17:29 +02:00
Thorsten Sommer 2ae292009d Improved I18N (#462) 2025-05-17 14:22:10 +02:00
Thorsten Sommer 03e196b66f Improved dev experience & allow native .NET debugging (#461) 2025-05-17 13:49:43 +02:00
Thorsten Sommer 4ca1fd54d9 Improved dev experience & allow native .NET debugging (#460) 2025-05-17 13:36:28 +02:00
Thorsten Sommer c0cf620fe3 Refactored some text fields to use the DebouncedTextField component (#459) 2025-05-16 15:36:08 +02:00
Thorsten Sommer 47a0598e8f Improved German translations and localization code (#458) 2025-05-12 20:57:03 +02:00
Thorsten Sommer 85a867459e Prepared release v0.9.43 (#457) 2025-05-11 19:30:25 +02:00
Thorsten Sommer ba236c4012 Add the DLR as the first titan supporter (#456) 2025-05-11 17:40:24 +02:00
Thorsten Sommer 9fa0f95611 Localized the embedding configuration (#455) 2025-05-11 16:57:52 +02:00
Thorsten Sommer f10d9a5d88 Improved the embedding configuration dialog (#454) 2025-05-11 15:35:19 +02:00
Thorsten Sommer 1a4e4781cd Enhanced Google model selection and updated the changelog (#453) 2025-05-11 15:01:04 +02:00
Thorsten Sommer 99b4d616c7 Updated changelog (#452) 2025-05-11 14:40:39 +02:00
Peer Schütt ace125d7cb Proofreading the automatic German translation (#451) 2025-05-11 13:58:43 +02:00
Thorsten Sommer d6af5a3afd Add model capabilities (#450) 2025-05-11 12:51:35 +02:00
Thorsten Sommer 07b858fd72 Updated README to reflect recent I18N enhancements (#449) 2025-05-05 18:49:06 +02:00
Thorsten Sommer 5d7949211f Fixed build script for Windows by fixing Windows PDFium download (#448) 2025-05-05 08:42:54 +02:00
Thorsten Sommer c23f0f49f9 Prepared release v0.9.42 (#447) 2025-05-04 15:06:45 +02:00
Thorsten Sommer 7a08baf99b Added more text content to the I18N system (#446) 2025-05-04 14:59:30 +02:00
Thorsten Sommer cfc2103b43 Improved I18N system (#445) 2025-05-03 21:47:43 +02:00
Thorsten Sommer f8dbc186fb Improved chat name generation to remove line breaks, tabs, etc. (#444) 2025-05-03 16:25:51 +02:00
Thorsten Sommer 6041b42510 Refactored I18N key handling in build script (#443) 2025-05-03 16:17:23 +02:00
Thorsten Sommer 10dc03f33b Added file type filtering to file selection dialogs (#442) 2025-05-03 15:43:12 +02:00
Thorsten Sommer 437ea2c243 Refactored metadata initialization (#441) 2025-05-03 14:26:13 +02:00
Thorsten Sommer b0d4615506 Refactored PDFium initialization (#440) 2025-05-03 12:20:22 +02:00
Thorsten Sommer c4d9af18cd Add component to read PDF files into assistants (#439)
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 / 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 / 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 / Publish release (push) Has been cancelled
2025-05-02 23:09:50 +02:00
Thorsten Sommer 9996b810e2 Added "Changelog" writing style to assist in creating release notes (#438)
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
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) Blocked by required conditions
2025-05-02 12:11:23 +02:00
Thorsten Sommer 53ec4c2162 Improved app settings to apply language changes immediately (#437)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
2025-05-02 11:50:14 +02:00
Thorsten Sommer 38facf3e04 Improved internal plugin maintenance (#436)
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
2025-05-02 11:27:21 +02:00
Thorsten Sommer 68404199ba Improved model selection for OpenAI by excluding unsupported models (#435)
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
2025-05-01 13:35:27 +02:00
Thorsten Sommer 08b8f42c25 Fixed localization assistant file loading issue in the release app (#434) 2025-05-01 13:23:57 +02:00
Thorsten Sommer 3c41fe2771 Fixed Markdown rendering issue and upgrade dependencies (#433)
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) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
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) Blocked by required conditions
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) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
2025-05-01 12:54:04 +02:00
457 changed files with 24795 additions and 3884 deletions

No files matched your search

+139 -2
View File
@@ -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,127 @@ 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 ..."
# 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 "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 -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: Build .NET project
run: |
@@ -298,13 +435,13 @@ jobs:
if: matrix.platform == 'ubuntu-22.04' && contains(matrix.rust_target, 'x86_64')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
sudo apt-get install -y libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libfuse2
- name: Setup dependencies (Ubuntu-specific, ARM)
if: matrix.platform == 'ubuntu-22.04-arm' && contains(matrix.rust_target, 'aarch64')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
sudo apt-get install -y libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libfuse2
- name: Setup Tauri (Unix)
if: matrix.platform != 'windows-latest'
+11
View File
@@ -1,3 +1,11 @@
# Ignore any startup.env file:
startup.env
# Ignore pdfium library:
libpdfium.dylib
libpdfium.so
libpdfium.dll
# User-specific files
*.rsuser
*.suo
@@ -148,3 +156,6 @@ orleans.codegen.cs
**/.idea/**/uiDesigner.xml
**/.idea/**/dbnavigator.xml
**/.vs
# Ignore AI plugin config files:
/app/.idea/.idea.MindWork AI Studio/.idea/AugmentWebviewStateStore.xml
+17
View File
@@ -0,0 +1,17 @@
# Project Guidelines
## Repository Structure
- The repository and the app consist of a Rust project in the `runtime` folder and a .NET solution in the `app` folder.
- The .NET solution then contains 4 .NET projects:
- `Build Script` is not required for running the app; instead, it contains the build script for creating new releases, for example.
- `MindWork AI Studio` contains the actual app code.
- `SharedTools` contains types that are needed in the build script and in the app, for example.
- `SourceCodeRules` is a Roslyn analyzer project. It contains analyzers and code fixes that we use to enforce code style rules within the team.
## Changelogs
- There is a changelog in Markdown format for each version.
- All changelogs are located in the folder `app/MindWork AI Studio/wwwroot/changelog`.
- These changelogs are intended for end users, not for developers.
- Therefore, we don't mention all changes in the changelog: changes that end users wouldn't understand remain unmentioned. For complex refactorings, for example, we mention a generic point that the code quality has been improved to enhance future maintenance.
- The changelog is always written in US English.
- The changelog doesn't mention bug fixes if the bug was never shipped and users don't know about it.
+126 -43
View File
@@ -1,52 +1,89 @@
# MindWork AI Studio
<img src="app/MindWork%20AI%20Studio/wwwroot/svg/banner.svg" alt="MindWork AI Studio Banner"/>
Are you new here? [Read here](#what-is-ai-studio) what AI Studio is.
## News
Things we are currently working on:
<details>
<summary>
<h3 style="display:inline-block">
Things we are currently working on
</h3>
</summary>
- Since November 2024: Work on RAG (integration of your data and files) has begun. We will support the integration of local and external data sources. We need to implement the following runtime (Rust) and app (.NET) steps:
<details>
<summary>
<h4 style="display:inline-block">
RAG (Retrieval-Augmented Generation)
</h4>
</summary>
- [x] ~~Runtime: Restructuring the code into meaningful modules (PR [#192](https://github.com/MindWorkAI/AI-Studio/pull/192))~~
- [x] ~~Define the [External Retrieval Interface (ERI)](https://github.com/MindWorkAI/ERI) as a contract for integrating arbitrary external data (PR [#1](https://github.com/MindWorkAI/ERI/pull/1))~~
- [x] ~~App: Metadata for providers (which provider offers embeddings?) (PR [#205](https://github.com/MindWorkAI/AI-Studio/pull/205))~~
- [x] ~~App: Add an option to show preview features (PR [#222](https://github.com/MindWorkAI/AI-Studio/pull/222))~~
- [x] ~~App: Configure embedding providers (PR [#224](https://github.com/MindWorkAI/AI-Studio/pull/224))~~
- [x] ~~App: Implement an [ERI](https://github.com/MindWorkAI/ERI) server coding assistant (PR [#231](https://github.com/MindWorkAI/AI-Studio/pull/231))~~
- [x] ~~App: Management of data sources (local & external data via [ERI](https://github.com/MindWorkAI/ERI)) (PR [#259](https://github.com/MindWorkAI/AI-Studio/pull/259), [#273](https://github.com/MindWorkAI/AI-Studio/pull/273))~~
- [x] ~~Runtime: Extract data from txt / md / pdf / docx / xlsx files (PR [#374](https://github.com/MindWorkAI/AI-Studio/pull/374))~~
- [ ] (*Optional*) Runtime: Implement internal embedding provider through [fastembed-rs](https://github.com/Anush008/fastembed-rs)
- [ ] App: Implement dialog for checking & handling [pandoc](https://pandoc.org/) installation ([PR #393](https://github.com/MindWorkAI/AI-Studio/pull/393))
- [ ] App: Implement external embedding providers
- [ ] App: Implement the process to vectorize one local file using embeddings
- [ ] Runtime: Integration of the vector database [LanceDB](https://github.com/lancedb/lancedb)
- [ ] 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 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: Integrate data sources in chats (PR [#282](https://github.com/MindWorkAI/AI-Studio/pull/282))~~
Since November 2024: Work on RAG (integration of your data and files) has begun. We will support the integration of local and external data sources. We need to implement the following runtime (Rust) and app (.NET) steps:
- [x] ~~Runtime: Restructuring the code into meaningful modules (PR [#192](https://github.com/MindWorkAI/AI-Studio/pull/192))~~
- [x] ~~Define the [External Retrieval Interface (ERI)](https://github.com/MindWorkAI/ERI) as a contract for integrating arbitrary external data (PR [#1](https://github.com/MindWorkAI/ERI/pull/1))~~
- [x] ~~App: Metadata for providers (which provider offers embeddings?) (PR [#205](https://github.com/MindWorkAI/AI-Studio/pull/205))~~
- [x] ~~App: Add an option to show preview features (PR [#222](https://github.com/MindWorkAI/AI-Studio/pull/222))~~
- [x] ~~App: Configure embedding providers (PR [#224](https://github.com/MindWorkAI/AI-Studio/pull/224))~~
- [x] ~~App: Implement an [ERI](https://github.com/MindWorkAI/ERI) server coding assistant (PR [#231](https://github.com/MindWorkAI/AI-Studio/pull/231))~~
- [x] ~~App: Management of data sources (local & external data via [ERI](https://github.com/MindWorkAI/ERI)) (PR [#259](https://github.com/MindWorkAI/AI-Studio/pull/259), [#273](https://github.com/MindWorkAI/AI-Studio/pull/273))~~
- [x] ~~Runtime: Extract data from txt / md / pdf / docx / xlsx files (PR [#374](https://github.com/MindWorkAI/AI-Studio/pull/374))~~
- [ ] (*Optional*) Runtime: Implement internal embedding provider through [fastembed-rs](https://github.com/Anush008/fastembed-rs)
- [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 the process to vectorize one local file using embeddings
- [ ] Runtime: Integration of the vector database [LanceDB](https://github.com/lancedb/lancedb)
- [ ] 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 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: Integrate data sources in chats (PR [#282](https://github.com/MindWorkAI/AI-Studio/pull/282))~~
- Since September 2024: Experiments have been started on how we can work on long texts with AI Studio. Let's say you want to write a fantasy novel or create a complex project proposal and use LLM for support. The initial experiments were promising, but not yet satisfactory. We are testing further approaches until a satisfactory solution is found. The current state of our experiment is available as an experimental preview feature through your app configuration. Related PR: ~~[PR #167](https://github.com/MindWorkAI/AI-Studio/pull/167), [PR #226](https://github.com/MindWorkAI/AI-Studio/pull/226)~~, [PR #376](https://github.com/MindWorkAI/AI-Studio/pull/376).
</details>
- Since March 2025: We have started developing the plugin system. There will be language plugins to offer AI Studio in other languages, configuration plugins to centrally manage certain providers and rules within an organization, and assistant plugins that allow anyone to develop their own assistants. We are using Lua as the plugin language:
- [x] ~~Plan & implement the base plugin system ([PR #322](https://github.com/MindWorkAI/AI-Studio/pull/322))~~
- [x] ~~Start the plugin system ([PR #372](https://github.com/MindWorkAI/AI-Studio/pull/372))~~
- [x] ~~Added hot-reload support for plugins ([PR #377](https://github.com/MindWorkAI/AI-Studio/pull/377), [PR #391](https://github.com/MindWorkAI/AI-Studio/pull/391))~~
- [ ] Add support for other languages (I18N) to AI Studio (~~[PR #381](https://github.com/MindWorkAI/AI-Studio/pull/381), [PR #400](https://github.com/MindWorkAI/AI-Studio/pull/400), [PR #404](https://github.com/MindWorkAI/AI-Studio/pull/404), [PR #429](https://github.com/MindWorkAI/AI-Studio/pull/429))~~
- [x] ~~Add an I18N assistant to translate all AI Studio texts to a certain language & culture ([PR #422](https://github.com/MindWorkAI/AI-Studio/pull/422))~~
- [ ] Provide MindWork AI Studio in German ([PR #430](https://github.com/MindWorkAI/AI-Studio/pull/430))
- [ ] Add configuration plugins, which allow pre-defining some LLM providers in organizations
- [ ] Add an app store for plugins, showcasing community-contributed plugins from public GitHub and GitLab repositories. This will enable AI Studio users to discover, install, and update plugins directly within the platform.
- [ ] Add assistant plugins
<details>
<summary>
<h4 style="display:inline-block">
Writer Mode
</h4>
</summary>
Other News:
Since September 2024: Experiments have been started on how we can work on long texts with AI Studio. Let's say you want to write a fantasy novel or create a complex project proposal and use LLM for support. The initial experiments were promising, but not yet satisfactory. We are testing further approaches until a satisfactory solution is found. The current state of our experiment is available as an experimental preview feature through your app configuration. Related PR: ~~[PR #167](https://github.com/MindWorkAI/AI-Studio/pull/167), [PR #226](https://github.com/MindWorkAI/AI-Studio/pull/226)~~, [PR #376](https://github.com/MindWorkAI/AI-Studio/pull/376).
- April 2025: We have two active financial supporters: Peer `peerschuett` and Dominic `donework`. Thank you very much for your support. MindWork AI reinvests these donations by passing them on to our AI Studio dependencies ([see here](https://github.com/orgs/MindWorkAI/sponsoring)). In the event that we receive large donations, we will first sign the app ([#56](https://github.com/MindWorkAI/Planning/issues/56)). In case we receive more donations, we will look for and pay staff to develop features for AI Studio.
</details>
- April 2025: The [German Aerospace Center (DLR)](https://en.wikipedia.org/wiki/German_Aerospace_Center) ([Website](https://www.dlr.de/en)) will use AI Studio at least within the scope of three projects and will also contribute to its further development. This is great news.
<details>
<summary>
<h4 style="display:inline-block">
Plugin System
</h4>
</summary>
Since March 2025: We have started developing the plugin system. There will be language plugins to offer AI Studio in other languages, configuration plugins to centrally manage certain providers and rules within an organization, and assistant plugins that allow anyone to develop their own assistants. We are using Lua as the plugin language:
- [x] ~~Plan & implement the base plugin system ([PR #322](https://github.com/MindWorkAI/AI-Studio/pull/322))~~
- [x] ~~Start the plugin system ([PR #372](https://github.com/MindWorkAI/AI-Studio/pull/372))~~
- [x] ~~Added hot-reload support for plugins ([PR #377](https://github.com/MindWorkAI/AI-Studio/pull/377), [PR #391](https://github.com/MindWorkAI/AI-Studio/pull/391))~~
- [x] ~~Add support for other languages (I18N) to AI Studio ([PR #381](https://github.com/MindWorkAI/AI-Studio/pull/381), [PR #400](https://github.com/MindWorkAI/AI-Studio/pull/400), [PR #404](https://github.com/MindWorkAI/AI-Studio/pull/404), [PR #429](https://github.com/MindWorkAI/AI-Studio/pull/429), [PR #446](https://github.com/MindWorkAI/AI-Studio/pull/446), [PR #451](https://github.com/MindWorkAI/AI-Studio/pull/451), [PR #455](https://github.com/MindWorkAI/AI-Studio/pull/455), [PR #458](https://github.com/MindWorkAI/AI-Studio/pull/458), [PR #462](https://github.com/MindWorkAI/AI-Studio/pull/462), [PR #469](https://github.com/MindWorkAI/AI-Studio/pull/469), [PR #486](https://github.com/MindWorkAI/AI-Studio/pull/486))~~
- [x] ~~Add an I18N assistant to translate all AI Studio texts to a certain language & culture ([PR #422](https://github.com/MindWorkAI/AI-Studio/pull/422))~~
- [x] ~~Provide MindWork AI Studio in German ([PR #430](https://github.com/MindWorkAI/AI-Studio/pull/430), [PR #446](https://github.com/MindWorkAI/AI-Studio/pull/446), [PR #451](https://github.com/MindWorkAI/AI-Studio/pull/451), [PR #455](https://github.com/MindWorkAI/AI-Studio/pull/455), [PR #458](https://github.com/MindWorkAI/AI-Studio/pull/458), [PR #462](https://github.com/MindWorkAI/AI-Studio/pull/462), [PR #469](https://github.com/MindWorkAI/AI-Studio/pull/469), [PR #486](https://github.com/MindWorkAI/AI-Studio/pull/486))~~
- [x] ~~Add configuration plugins, which allow pre-defining some LLM providers in organizations ([PR #491](https://github.com/MindWorkAI/AI-Studio/pull/491), [PR #493](https://github.com/MindWorkAI/AI-Studio/pull/493), [PR #494](https://github.com/MindWorkAI/AI-Studio/pull/494), [PR #497](https://github.com/MindWorkAI/AI-Studio/pull/497))~~
- [ ] Add an app store for plugins, showcasing community-contributed plugins from public GitHub and GitLab repositories. This will enable AI Studio users to discover, install, and update plugins directly within the platform.
- [ ] Add assistant plugins
Features we have recently released:
</details>
</details>
<details open>
<summary>
<h3 style="display:inline-block">
Features we have recently released
</h3>
</summary>
- v0.9.51: Added support for [Perplexity](https://www.perplexity.ai/); citations added so that LLMs can provide source references (e.g., some OpenAI models, Perplexity); added support for OpenAI's Responses API so that all text LLMs from OpenAI now work in MindWork AI Studio, including Deep Research models; web searches are now possible (some OpenAI models, Perplexity).
- v0.9.50: Added support for self-hosted LLMs using [vLLM](https://blog.vllm.ai/2023/06/20/vllm.html).
- v0.9.46: Released our plugin system, a German language plugin, early support for enterprise environments, and configuration plugins. Additionally, we added the Pandoc integration for future data processing and file generation.
- v0.9.45: Added chat templates to AI Studio, allowing you to create and use a library of system prompts for your chats.
- v0.9.44: Added PDF import to the text summarizer, translation, and legal check assistants, allowing you to import PDF files and use them as input for the assistants.
- v0.9.40: Added support for the `o4` models from OpenAI. Also, we added Alibaba Cloud & Hugging Face as LLM providers.
- v0.9.39: Added the plugin system as a preview feature.
- v0.9.31: Added Helmholtz & GWDG as LLM providers. This is a huge improvement for many researchers out there who can use these providers for free. We added DeepSeek as a provider as well.
@@ -54,8 +91,8 @@ Features we have recently released:
- v0.9.26+: Added RAG for external data sources using our [ERI interface](https://mindworkai.org/#eri---external-retrieval-interface) as a preview feature.
- v0.9.25: Added [xAI](https://x.ai/) as a new provider. xAI provides their Grok models for generating content.
- v0.9.23: Added support for OpenAI `o` models (`o1`, `o1-mini`, `o3`, etc.); added also an [ERI](https://github.com/MindWorkAI/ERI) server coding assistant as a preview feature behind the RAG feature flag. Your own ERI server can be used to gain access to, e.g., your enterprise data from within AI Studio.
- v0.9.22: Added options for preview features; added embedding provider configuration for RAG (preview) and writer mode (experimental preview).
- v0.9.18: Added the new Anthropic Heiku model; added Groq and Google Gemini as provider options.
</details>
## What is AI Studio?
@@ -69,7 +106,8 @@ MindWork AI Studio is a free desktop app for macOS, Windows, and Linux. It provi
**Key advantages:**
- **Free of charge**: The app is free to use, both for personal and commercial purposes.
- **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/) (GPT4o, GPT4.1, o1, o3, o4, etc.)
- [OpenAI](https://openai.com/) (GPT5, GPT4.1, o1, o3, o4, etc.)
- [Perplexity](https://www.perplexity.ai/)
- [Mistral](https://mistral.ai/)
- [Anthropic](https://www.anthropic.com/) (Claude)
- [Google Gemini](https://gemini.google.com)
@@ -77,7 +115,7 @@ MindWork AI Studio is a free desktop app for macOS, Windows, and Linux. It provi
- [DeepSeek](https://www.deepseek.com/en)
- [Alibaba Cloud](https://www.alibabacloud.com) (Qwen)
- [Hugging Face](https://huggingface.co/) using their [inference providers](https://huggingface.co/docs/inference-providers/index) such as Cerebras, Nebius, Sambanova, Novita, Hyperbolic, Together AI, Fireworks, Hugging Face
- Self-hosted models using [llama.cpp](https://github.com/ggerganov/llama.cpp), [ollama](https://github.com/ollama/ollama), [LM Studio](https://lmstudio.ai/)
- Self-hosted models using [llama.cpp](https://github.com/ggerganov/llama.cpp), [ollama](https://github.com/ollama/ollama), [LM Studio](https://lmstudio.ai/), and [vLLM](https://github.com/vllm-project/vllm)
- [Groq](https://groq.com/)
- [Fireworks](https://fireworks.ai/)
- For scientists and employees of research institutions, we also support [Helmholtz](https://helmholtz.cloud/services/?serviceID=d7d5c597-a2f6-4bd1-b71e-4d6499d98570) and [GWDG](https://gwdg.de/services/application-services/ai-services/) 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.
@@ -90,7 +128,13 @@ MindWork AI Studio is a free desktop app for macOS, Windows, and Linux. It provi
## **Ready to get started 🤩?** [Download the appropriate setup for your operating system here](documentation/Setup.md).
## Support the Project
<details>
<summary>
<h2 style="display:inline-block">
Support the Project
</h2>
</summary>
Thank you for using MindWork AI Studio and considering supporting its development 😀. Your support helps keep the project alive and ensures continuous improvements and new features.
We offer various ways you can support the project:
@@ -104,7 +148,15 @@ For companies, sponsoring MindWork AI Studio is not only a way to support innova
To view all available tiers, please visit our [GitHub Sponsors page](https://github.com/sponsors/MindWorkAI).
Your support, whether big or small, keeps the wheels turning and is deeply appreciated ❤️.
## Planned Features
</details>
<details>
<summary>
<h2 style="display:inline-block">
Planned Features
</h2>
</summary>
Here's an exciting look at some of the features we're planning to add to AI Studio in future releases:
- **Integrating your data**: You'll be able to integrate your data into AI Studio, like your PDF or Office files, or your Markdown notes.
- **Integration of enterprise data:** It will soon be possible to integrate data from the corporate network using a specified interface ([External Retrieval Interface](https://github.com/MindWorkAI/ERI), ERI for short). This will likely require development work by the organization in question.
@@ -118,14 +170,45 @@ Here's an exciting look at some of the features we're planning to add to AI Stud
Stay tuned for more updates and enhancements to make MindWork AI Studio even more powerful and versatile 🤩.
## Building
If you're interested in learning more about future plans, check out our [roadmap](https://github.com/orgs/MindWorkAI/projects/2/views/3) and our [planning issues](https://github.com/MindWorkAI/Planning/issues).
</details>
<details>
<summary>
<h2 style="display:inline-block">
Building
</h2>
</summary>
You want to know how to build MindWork AI Studio from source? [Check out the instructions here](documentation/Build.md).
## License
</details>
<details>
<summary>
<h2 style="display:inline-block">
Enterprise IT
</h2>
</summary>
Do you want to manage AI Studio centrally from your IT department? Yes, that’s possible. [Here’s how it works.](documentation/Enterprise%20IT.md)
</details>
<details>
<summary>
<h2 style="display:inline-block">
License
</h2>
</summary>
MindWork AI Studio is licensed under the `FSL-1.1-MIT` license (functional source license). Here’s a simple rundown of what that means for you:
- **Permitted Use**: Feel free to use, copy, modify, and share the software for your own projects, educational purposes, research, or even in professional services. The key is to use it in a way that doesn't compete with our offerings.
- **Competing Use**: Our only request is that you don't create commercial products or services that replace or compete with MindWork AI Studio or any of our other offerings.
- **No Warranties**: The software is provided "as is", without any promises from us about it working perfectly for your needs. While we strive to make it great, we can't guarantee it will be free of bugs or issues.
- **Future License**: Good news! The license for each release of MindWork AI Studio will automatically convert to an MIT license two years from its release date. This makes it even easier for you to use the software in the future.
For more details, refer to the [LICENSE](LICENSE.md) file. This license structure ensures you have plenty of freedom to use and enjoy the software while protecting our work.
For more details, refer to the [LICENSE](LICENSE.md) file. This license structure ensures you have plenty of freedom to use and enjoy the software while protecting our work.
</details>
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Tauri Dev" type="ShConfigurationType">
<configuration default="false" name="[1] Start Tauri" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="cargo tauri dev --no-watch" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="" />
+27
View File
@@ -0,0 +1,27 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="[2] Start .NET Server" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/MindWork AI Studio/bin/Debug/net9.0/osx-arm64/mindworkAIStudio" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/MindWork AI Studio" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="ENV_FILE_PATHS" value="" />
<option name="REDIRECT_INPUT_PATH" value="" />
<option name="PTY_MODE" value="Auto" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="AUTO_ATTACH_CHILDREN" value="0" />
<option name="MIXED_MODE_DEBUG" value="0" />
<option name="RUNTIME_TYPE" value="coreclr" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/MindWork AI Studio/MindWork AI Studio.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="net9.0" />
<method v="2">
<option name="Build" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Collect I18N content" run_configuration_type="ShConfigurationType" />
</method>
</configuration>
</component>
+5
View File
@@ -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}");
}
}
+37 -28
View File
@@ -10,6 +10,29 @@ namespace Build.Commands;
public sealed partial class CollectI18NKeysCommand
{
private const string START_TAG1 = """
T("
""";
private const string START_TAG2 = """
TB("
""";
private const string START_TAG3 = """
T(@"
""";
private const string END_TAG = """
")
""";
private static readonly (string Tag, int Length)[] START_TAGS =
[
(START_TAG1, START_TAG1.Length),
(START_TAG2, START_TAG2.Length),
(START_TAG3, START_TAG3.Length)
];
[Command("collect-i18n", Description = "Collect I18N keys")]
public async Task CollectI18NKeys()
{
@@ -133,36 +156,22 @@ public sealed partial class CollectI18NKeysCommand
private List<string> FindAllTextTags(ReadOnlySpan<char> fileContent)
{
const string START_TAG1 = """
T("
""";
const string START_TAG2 = """
TB("
""";
const string END_TAG = """
")
""";
(int Index, int Len) FindNextStart(ReadOnlySpan<char> content)
{
var startIdx1 = content.IndexOf(START_TAG1);
var startIdx2 = content.IndexOf(START_TAG2);
if (startIdx1 == -1 && startIdx2 == -1)
return (-1, 0);
if (startIdx1 == -1)
return (startIdx2, START_TAG2.Length);
if (startIdx2 == -1)
return (startIdx1, START_TAG1.Length);
if (startIdx1 < startIdx2)
return (startIdx1, START_TAG1.Length);
return (startIdx2, START_TAG2.Length);
var bestIndex = -1;
var bestLength = 0;
foreach (var (tag, length) in START_TAGS)
{
var index = content.IndexOf(tag);
if (index != -1 && (bestIndex == -1 || index < bestIndex))
{
bestIndex = index;
bestLength = length;
}
}
return (bestIndex, bestLength);
}
var matches = new List<string>();
+3
View File
@@ -0,0 +1,3 @@
namespace Build.Commands;
public record Library(string Path, string Filename);
+107
View 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()} from {pdfiumUrl}");
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.IsNullOrWhiteSpace(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.tgz",
RID.WIN_X64 => $"{baseUrl}win-x64.tgz",
_ => string.Empty,
};
}
}
+102 -92
View File
@@ -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,14 +330,15 @@ 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);
Console.WriteLine(" done.");
}
private async Task UpdateProjectCommitHash()
[Command("update-project-hash", Description = "Update the project commit hash")]
public async Task UpdateProjectCommitHash()
{
const int COMMIT_HASH_INDEX = 8;
+12 -4
View File
@@ -17,9 +17,10 @@ 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"));
if (!isMudBlazorDirectoryPresent)
{
@@ -28,14 +29,21 @@ public sealed class UpdateWebAssetsCommand
return;
}
Directory.CreateDirectory(Path.Join(cwd, "wwwroot", "system"));
var destinationPath = Path.Join(cwd, "wwwroot", "system");
if(Directory.Exists(destinationPath))
Directory.Delete(destinationPath, true);
Directory.CreateDirectory(destinationPath);
var sourcePaths = Directory.EnumerateFiles(contentPath, "*", SearchOption.AllDirectories);
var counter = 0;
foreach(var sourcePath in sourcePaths)
{
counter++;
var relativePath = Path.GetRelativePath(cwd, sourcePath);
var targetPath = Path.Join(cwd, "wwwroot", relativePath);
var relativePath = sourcePath
.Replace(contentPath, "")
.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var targetPath = Path.Join(cwd, "wwwroot", "system", relativePath);
var targetDirectory = Path.GetDirectoryName(targetPath);
if (targetDirectory != null)
Directory.CreateDirectory(targetDirectory);
+34
View File
@@ -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;
}
}
+3
View File
@@ -5,10 +5,12 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FNV/@EntryIndexedValue">FNV</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GWDG/@EntryIndexedValue">GWDG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HF/@EntryIndexedValue">HF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IERI/@EntryIndexedValue">IERI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LLM/@EntryIndexedValue">LLM</s:String>
<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>
@@ -19,6 +21,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=groq/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gwdg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=huggingface/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ieri/@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/=tauri_0027s/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+3 -5
View File
@@ -54,7 +54,7 @@ public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager setti
#region Implementation of IAgent
public abstract AIStudio.Settings.Provider? ProviderSettings { get; set; }
public abstract AIStudio.Settings.Provider ProviderSettings { get; set; }
public abstract Task<ChatThread> ProcessContext(ChatThread chatThread, IDictionary<string, string> additionalData);
@@ -73,7 +73,6 @@ public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager setti
WorkspaceId = Guid.Empty,
ChatId = Guid.NewGuid(),
Name = string.Empty,
Seed = this.RNG.Next(),
SystemPrompt = systemPrompt,
Blocks = [],
};
@@ -103,10 +102,9 @@ public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager setti
protected async Task AddAIResponseAsync(ChatThread thread, IContent lastUserPrompt, DateTimeOffset time)
{
if(this.ProviderSettings is null)
if(this.ProviderSettings == Settings.Provider.NONE)
return;
var providerSettings = this.ProviderSettings.Value;
var aiText = new ContentText
{
// We have to wait for the remote
@@ -127,6 +125,6 @@ public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager setti
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
await aiText.CreateFromProviderAsync(providerSettings.CreateProvider(this.Logger), providerSettings.Model, lastUserPrompt, thread);
await aiText.CreateFromProviderAsync(this.ProviderSettings.CreateProvider(), this.ProviderSettings.Model, lastUserPrompt, thread);
}
}
@@ -86,7 +86,7 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
""";
/// <inheritdoc />
public override Settings.Provider? ProviderSettings { get; set; }
public override Settings.Provider ProviderSettings { get; set; } = Settings.Provider.NONE;
/// <summary>
/// The data source selection agent does not work with context. Use
@@ -131,7 +131,7 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
#endregion
public async Task<List<SelectedDataSource>> PerformSelectionAsync(IProvider provider, IContent lastPrompt, ChatThread chatThread, AllowedSelectedDataSources dataSources, CancellationToken token = default)
public async Task<List<SelectedDataSource>> PerformSelectionAsync(IProvider provider, IContent lastUserPrompt, ChatThread chatThread, AllowedSelectedDataSources dataSources, CancellationToken token = default)
{
logger.LogInformation("The AI should select the appropriate data sources.");
@@ -141,6 +141,11 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
// We start with the provider currently selected by the user:
var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_DATA_SOURCE_SELECTION, provider.Id, true);
if (agentProvider == Settings.Provider.NONE)
{
logger.LogWarning("No provider is selected for the agent. The agent cannot select data sources.");
return [];
}
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the data source selection uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
@@ -149,7 +154,7 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
//
// 2. Prepare the current system and user prompts as input for the agent:
//
var lastPromptContent = lastPrompt switch
var lastPromptContent = lastUserPrompt switch
{
ContentText text => text.Text,
@@ -71,7 +71,7 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
""";
/// <inheritdoc />
public override Settings.Provider? ProviderSettings { get; set; }
public override Settings.Provider ProviderSettings { get; set; } = Settings.Provider.NONE;
/// <summary>
/// The retrieval context validation agent does not work with context. Use
@@ -133,6 +133,11 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
{
// We start with the provider currently selected by the user:
var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, provider.Id, true);
if (agentProvider == Settings.Provider.NONE)
{
logger.LogWarning("No provider is selected for the agent.");
return;
}
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the retrieval context validation uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
@@ -142,12 +147,12 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
/// <summary>
/// Validate all retrieval contexts against the last user and the system prompt.
/// </summary>
/// <param name="lastPrompt">The last user prompt.</param>
/// <param name="lastUserPrompt">The last user prompt.</param>
/// <param name="chatThread">The chat thread.</param>
/// <param name="retrievalContexts">All retrieval contexts to validate.</param>
/// <param name="token">The cancellation token.</param>
/// <returns>The validation results.</returns>
public async Task<IReadOnlyList<RetrievalContextValidationResult>> ValidateRetrievalContextsAsync(IContent lastPrompt, ChatThread chatThread, IReadOnlyList<IRetrievalContext> retrievalContexts, CancellationToken token = default)
public async Task<IReadOnlyList<RetrievalContextValidationResult>> ValidateRetrievalContextsAsync(IContent lastUserPrompt, ChatThread chatThread, IReadOnlyList<IRetrievalContext> retrievalContexts, CancellationToken token = default)
{
// Check if the retrieval context validation is enabled:
if (!this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
@@ -173,7 +178,7 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
await semaphore.WaitAsync(token);
// Start the next validation task:
validationTasks.Add(this.ValidateRetrievalContextAsync(lastPrompt, chatThread, retrievalContext, token, semaphore));
validationTasks.Add(this.ValidateRetrievalContextAsync(lastUserPrompt, chatThread, retrievalContext, token, semaphore));
}
// Wait for all validation tasks to complete:
@@ -188,13 +193,13 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
/// can call this method in parallel for each retrieval context. You might use
/// the ValidateRetrievalContextsAsync method to validate all retrieval contexts.
/// </remarks>
/// <param name="lastPrompt">The last user prompt.</param>
/// <param name="lastUserPrompt">The last user prompt.</param>
/// <param name="chatThread">The chat thread.</param>
/// <param name="retrievalContext">The retrieval context to validate.</param>
/// <param name="token">The cancellation token.</param>
/// <param name="semaphore">The optional semaphore to limit the number of parallel validations.</param>
/// <returns>The validation result.</returns>
public async Task<RetrievalContextValidationResult> ValidateRetrievalContextAsync(IContent lastPrompt, ChatThread chatThread, IRetrievalContext retrievalContext, CancellationToken token = default, SemaphoreSlim? semaphore = null)
public async Task<RetrievalContextValidationResult> ValidateRetrievalContextAsync(IContent lastUserPrompt, ChatThread chatThread, IRetrievalContext retrievalContext, CancellationToken token = default, SemaphoreSlim? semaphore = null)
{
try
{
@@ -209,7 +214,7 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
//
// 1. Prepare the current system and user prompts as input for the agent:
//
var lastPromptContent = lastPrompt switch
var lastPromptContent = lastUserPrompt switch
{
ContentText text => text.Text,
@@ -11,7 +11,7 @@ public sealed class AgentTextContentCleaner(ILogger<AgentBase> logger, SettingsM
#region Overrides of AgentBase
public override AIStudio.Settings.Provider? ProviderSettings { get; set; }
public override AIStudio.Settings.Provider ProviderSettings { get; set; } = AIStudio.Settings.Provider.NONE;
protected override Type Type => Type.SYSTEM;
+1 -1
View File
@@ -12,7 +12,7 @@ public interface IAgent
/// <summary>
/// The provider to use for this agent.
/// </summary>
public AIStudio.Settings.Provider? ProviderSettings { get; set; }
public Settings.Provider ProviderSettings { get; set; }
/// <summary>
/// Processes a chat thread (i.e., context) and returns the updated thread.
@@ -1,51 +1,55 @@
@attribute [Route(Routes.ASSISTANT_AGENDA)]
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogAgenda>
<MudTextField T="string" @bind-Text="@this.inputName" Validation="@this.ValidateName" Label="Meeting Name" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Tag" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Name the meeting, seminar, etc." Placeholder="Weekly jour fixe" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputTopic" Validation="@this.ValidateTopic" Label="Topic" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.EventNote" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe the topic of the meeting, seminar, etc. Is it about quantum computing, software engineering, or is it a general business meeting?" Placeholder="Project meeting" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputContent" Validation="@this.ValidateContent" Label="Content list" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Bullet list the content of the meeting, seminar, etc. roughly. Use dashes (-) to separate the items." Placeholder="@PLACEHOLDER_CONTENT" Class="mb-3" Immediate="@false" DebounceInterval="1_000" OnDebounceIntervalElapsed="@this.OnContentChanged" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt"/>
<MudSelect T="string" Label="(Optional) What topics should be the focus?" MultiSelection="@true" @bind-SelectedValues="@this.selectedFoci" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
<MudTextField T="string" @bind-Text="@this.inputName" Validation="@this.ValidateName" Label="@T("Meeting Name")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Tag" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Name the meeting, seminar, etc.")" Placeholder="@T("Weekly jour fixe")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputTopic" Validation="@this.ValidateTopic" Label="@T("Topic")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.EventNote" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Describe the topic of the meeting, seminar, etc. Is it about quantum computing, software engineering, or is it a general business meeting?")" Placeholder="@T("Project meeting")" Class="mb-3"/>
<DebouncedTextField @bind-Text="@this.inputContent" ValidationFunc="@this.ValidateContent" DebounceTime="TimeSpan.FromSeconds(1)" Label="@T("Content list")" Lines="6" Attributes="@USER_INPUT_ATTRIBUTES" HelpText="@T("Bullet list the content of the meeting, seminar, etc. roughly. Use dashes (-) to separate the items.")" Placeholder="@PLACEHOLDER_CONTENT" WhenTextCanged="@this.OnContentChanged" Icon="@Icons.Material.Filled.ListAlt"/>
<MudSelect T="string" Label="@T("(Optional) What topics should be the focus?")" MultiSelection="@true" @bind-SelectedValues="@this.selectedFoci" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
@foreach (var contentLine in this.contentLines)
{
@if(!this.justBriefly.Contains(contentLine))
{
<MudSelectItem T="string" Value="@contentLine">@contentLine</MudSelectItem>
<MudSelectItem T="string" Value="@contentLine">
@contentLine
</MudSelectItem>
}
}
</MudSelect>
<MudSelect T="string" Label="(Optional) What topics should only be briefly addressed?" MultiSelection="@true" @bind-SelectedValues="@this.justBriefly" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
<MudSelect T="string" Label="@T("(Optional) What topics should only be briefly addressed?")" MultiSelection="@true" @bind-SelectedValues="@this.justBriefly" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
@foreach (var contentLine in this.contentLines)
{
@if(!this.selectedFoci.Contains(contentLine))
{
<MudSelectItem T="string" Value="@contentLine">@contentLine</MudSelectItem>
<MudSelectItem T="string" Value="@contentLine">
@contentLine
</MudSelectItem>
}
}
</MudSelect>
<MudTextField T="string" @bind-Text="@this.inputObjective" Validation="@this.ValidateObjective" Label="Objective" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Flag" Variant="Variant.Outlined" Lines="3" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe the objective(s) of the meeting, seminar, etc. What should be achieved?" Placeholder="Discuss the current project status and plan the next steps." Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputModerator" Validation="@this.ValidateModerator" Label="Moderator" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person3" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Who will moderate the meeting, seminar, etc.?" Placeholder="Jane Doe" Class="mb-3" />
<MudTextField T="string" @bind-Text="@this.inputDuration" Validation="@this.ValidateDuration" Label="Duration" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="How long will the meeting, seminar, etc. last? E.g., '2 hours', or '2 days (first day 8 hours, then 4 hours)', etc." Placeholder="2 hours" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputStartTime" Validation="@this.ValidateStartTime" Label="Start time" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="When will the meeting, seminar, etc. start? E.g., '9:00 AM', or '9:00 AM (CET)', etc. When the meeting is a multi-day event, specify the start time for each day." Placeholder="9:00 AM" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputWhoIsPresenting" Label="(Optional) Who is presenting?" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="(Optional) List the persons who will present at the meeting, seminar, etc. Use dashes (-) to separate the items." Placeholder="@PLACEHOLDER_WHO_IS_PRESENTING" Class="mb-3"/>
<MudTextSwitch Label="Do the participants need to get to know each other first?" @bind-Value="@this.introduceParticipants" LabelOn="Yes, introduce participants" LabelOff="No, participants know each other" />
<EnumSelection T="NumberParticipants" @bind-Value="@this.numberParticipants" NameFunc="@(participants => participants.Name())" Icon="@Icons.Material.Filled.Group" Label="Number of participants" ValidateSelection="@this.ValidateNumberParticipants"/>
<MudTextSwitch Label="Should the participants be involved passively or actively?" @bind-Value="@this.activeParticipation" LabelOn="Active participation, like world café, discussions, etc." LabelOff="Passive participation, like presentations, lectures, etc." />
<MudTextSwitch Label="Is this a virtual event, e.g., a call or webinar?" @bind-Value="@this.isMeetingVirtual" LabelOn="Yes, this is a virtual event" LabelOff="No, this is a physical event" />
<MudTextField T="string" @bind-Text="@this.inputObjective" Validation="@this.ValidateObjective" Label="@T("Objective")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Flag" Variant="Variant.Outlined" Lines="3" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Describe the objective(s) of the meeting, seminar, etc. What should be achieved?")" Placeholder="@T("Discuss the current project status and plan the next steps.")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputModerator" Validation="@this.ValidateModerator" Label="@T("Moderator")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person3" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Who will moderate the meeting, seminar, etc.?")" Placeholder="Jane Doe" Class="mb-3" />
<MudTextField T="string" @bind-Text="@this.inputDuration" Validation="@this.ValidateDuration" Label="@T("Duration")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("How long will the meeting, seminar, etc. last? E.g., '2 hours', or '2 days (first day 8 hours, then 4 hours)', etc.")" Placeholder="@T("2 hours")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputStartTime" Validation="@this.ValidateStartTime" Label="Start time" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("When will the meeting, seminar, etc. start? E.g., '9:00 AM', or '9:00 AM (CET)', etc. When the meeting is a multi-day event, specify the start time for each day.")" Placeholder="@T("9:00 AM")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputWhoIsPresenting" Label="@T("(Optional) Who is presenting?")" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("(Optional) List the persons who will present at the meeting, seminar, etc. Use dashes (-) to separate the items.")" Placeholder="@PLACEHOLDER_WHO_IS_PRESENTING" Class="mb-3"/>
<MudTextSwitch Label="@T("Do the participants need to get to know each other first?")" @bind-Value="@this.introduceParticipants" LabelOn="@T("Yes, introduce participants")" LabelOff="@T("No, participants know each other")" />
<EnumSelection T="NumberParticipants" @bind-Value="@this.numberParticipants" NameFunc="@(participants => participants.Name())" Icon="@Icons.Material.Filled.Group" Label="@T("Number of participants")" ValidateSelection="@this.ValidateNumberParticipants"/>
<MudTextSwitch Label="@T("Should the participants be involved passively or actively?")" @bind-Value="@this.activeParticipation" LabelOn="@T("Active participation, like world café, discussions, etc.")" LabelOff="@T("Passive participation, like presentations, lectures, etc.")" />
<MudTextSwitch Label="@T("Is this a virtual event, e.g., a call or webinar?")" @bind-Value="@this.isMeetingVirtual" LabelOn="@T("Yes, this is a virtual event")" LabelOff="@T("No, this is a physical event")" />
@if (!this.isMeetingVirtual)
{
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
<MudTextField T="string" @bind-Text="@this.inputLocation" Validation="@this.ValidateLocation" Label="Location" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.MyLocation" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Where will the meeting, seminar, etc. take place?" Placeholder="Hamburg, Germany" Class="mb-3"/>
<MudTextSwitch Label="Should there be a joint dinner?" @bind-Value="@this.goingToDinner" LabelOn="Yes, there should be a joint dinner" LabelOff="No, there should be no joint dinner" />
<MudTextSwitch Label="Should there be a social activity?" @bind-Value="@this.doingSocialActivity" LabelOn="Yes, there should be a social activity" LabelOff="No, there should be no social activity" />
<MudTextSwitch Label="Do participants need to arrive and depart?" @bind-Value="@this.needToArriveAndDepart" LabelOn="Yes, participants need to arrive and depart" LabelOff="No, participants do not need to arrive and depart" />
<MudTextField T="string" @bind-Text="@this.inputLocation" Validation="@this.ValidateLocation" Label="@T("Location")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.MyLocation" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Where will the meeting, seminar, etc. take place?")" Placeholder="@T("Hamburg, Germany")" Class="mb-3"/>
<MudTextSwitch Label="@T("Should there be a joint dinner?")" @bind-Value="@this.goingToDinner" LabelOn="@T("Yes, there should be a joint dinner")" LabelOff="@T("No, there should be no joint dinner")" />
<MudTextSwitch Label="@T("Should there be a social activity?")" @bind-Value="@this.doingSocialActivity" LabelOn="@T("Yes, there should be a social activity")" LabelOff="@T("No, there should be no social activity")" />
<MudTextSwitch Label="@T("Do participants need to arrive and depart?")" @bind-Value="@this.needToArriveAndDepart" LabelOn="@T("Yes, participants need to arrive and depart")" LabelOff="@T("No, participants do not need to arrive and depart")" />
<MudStack Row="@true" Wrap="Wrap.Wrap">
<MudTextSlider T="int" Label="Approx. duration of the lunch break" @bind-Value="@this.durationLunchBreak" Min="30" Max="120" Step="5" Unit="minutes"/>
<MudTextSlider T="int" Label="Approx. duration of the coffee or tea breaks" @bind-Value="@this.durationBreaks" Min="10" Max="60" Step="5" Unit="minutes"/>
<MudTextSlider T="int" Label="@T("Approx. duration of the lunch break")" @bind-Value="@this.durationLunchBreak" Min="30" Max="120" Step="5" Unit="@T("minutes")"/>
<MudTextSlider T="int" Label="@T("Approx. duration of the coffee or tea breaks")" @bind-Value="@this.durationBreaks" Min="10" Max="60" Step="5" Unit="@T("minutes")"/>
</MudStack>
</MudPaper>
}
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -9,14 +9,9 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
{
public override Tools.Components Component => Tools.Components.AGENDA_ASSISTANT;
protected override string Title => "Agenda Planner";
protected override string Title => T("Agenda Planner");
protected override string Description =>
"""
This agenda planner helps you create a structured agenda for your meeting or seminar. Just provide some basic
information about the event, and the assistant will generate an agenda for you. You can also specify the
duration, the start time, the location, the target language, and other details.
""";
protected override string Description => T("This agenda planner helps you create a structured agenda for your meeting or seminar. Just provide some basic information about the event, and the assistant will generate an agenda for you. You can also specify the duration, the start time, the location, the target language, and other details.");
protected override string SystemPrompt =>
$"""
@@ -98,7 +93,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Create Agenda";
protected override string SubmitText => T("Create Agenda");
protected override Func<Task> SubmitAction => this.CreateAgenda;
@@ -235,7 +230,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateLocation(string location)
{
if(!this.isMeetingVirtual && string.IsNullOrWhiteSpace(location))
return "Please provide a location for the meeting or the seminar.";
return T("Please provide a location for the meeting or the seminar.");
return null;
}
@@ -243,7 +238,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateNumberParticipants(NumberParticipants selectedSize)
{
if(selectedSize is NumberParticipants.NOT_SPECIFIED)
return "Please select the number of participants.";
return T("Please select the number of participants.");
return null;
}
@@ -251,7 +246,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateTargetLanguage(CommonLanguages language)
{
if(language is CommonLanguages.AS_IS)
return "Please select a target language for the agenda.";
return T("Please select a target language for the agenda.");
return null;
}
@@ -259,7 +254,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateDuration(string duration)
{
if(string.IsNullOrWhiteSpace(duration))
return "Please provide a duration for the meeting or the seminar, e.g. '2 hours', or '2 days (8 hours and 4 hours)', etc.";
return T("Please provide a duration for the meeting or the seminar, e.g. '2 hours', or '2 days (8 hours and 4 hours)', etc.");
return null;
}
@@ -267,7 +262,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateStartTime(string startTime)
{
if(string.IsNullOrWhiteSpace(startTime))
return "Please provide a start time for the meeting or the seminar. When the meeting is a multi-day event, specify the start time for each day, e.g. '9:00 AM, 10:00 AM', etc.";
return T("Please provide a start time for the meeting or the seminar. When the meeting is a multi-day event, specify the start time for each day, e.g. '9:00 AM, 10:00 AM', etc.");
return null;
}
@@ -275,7 +270,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return T("Please provide a custom language.");
return null;
}
@@ -283,7 +278,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateTopic(string topic)
{
if(string.IsNullOrWhiteSpace(topic))
return "Please provide a topic for the agenda. What is the meeting or the seminar about?";
return T("Please provide a topic for the agenda. What is the meeting or the seminar about?");
return null;
}
@@ -291,7 +286,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateName(string name)
{
if(string.IsNullOrWhiteSpace(name))
return "Please provide a name for the meeting or the seminar.";
return T("Please provide a name for the meeting or the seminar.");
return null;
}
@@ -299,12 +294,12 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateContent(string content)
{
if(string.IsNullOrWhiteSpace(content))
return "Please provide some content for the agenda. What are the main points of the meeting or the seminar?";
return T("Please provide some content for the agenda. What are the main points of the meeting or the seminar?");
var lines = content.Split('\n', StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
if(!line.TrimStart().StartsWith('-'))
return "Please start each line of your content list with a dash (-) to create a bullet point list.";
return T("Please start each line of your content list with a dash (-) to create a bullet point list.");
return null;
}
@@ -312,7 +307,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateObjective(string objective)
{
if(string.IsNullOrWhiteSpace(objective))
return "Please provide an objective for the meeting or the seminar. What do you want to achieve?";
return T("Please provide an objective for the meeting or the seminar. What do you want to achieve?");
return null;
}
@@ -320,7 +315,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
private string? ValidateModerator(string moderator)
{
if(string.IsNullOrWhiteSpace(moderator))
return "Please provide a moderator for the meeting or the seminar. Who will lead the discussion?";
return T("Please provide a moderator for the meeting or the seminar. Who will lead the discussion?");
return null;
}
@@ -2,22 +2,24 @@ namespace AIStudio.Assistants.Agenda;
public static class NumberParticipantsExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(NumberParticipantsExtensions).Namespace, nameof(NumberParticipantsExtensions));
public static string Name(this NumberParticipants numberParticipants) => numberParticipants switch
{
NumberParticipants.NOT_SPECIFIED => "Please select how many participants are expected",
NumberParticipants.NOT_SPECIFIED => TB("Please select how many participants are expected"),
NumberParticipants.PEER_TO_PEER => "2 (peer to peer)",
NumberParticipants.PEER_TO_PEER => TB("2 (peer to peer)"),
NumberParticipants.SMALL_GROUP => "3 - 5 (small group)",
NumberParticipants.LARGE_GROUP => "6 - 12 (large group)",
NumberParticipants.MULTIPLE_SMALL_GROUPS => "13 - 20 (multiple small groups)",
NumberParticipants.MULTIPLE_LARGE_GROUPS => "21 - 30 (multiple large groups)",
NumberParticipants.SMALL_GROUP => TB("3 - 5 (small group)"),
NumberParticipants.LARGE_GROUP => TB("6 - 12 (large group)"),
NumberParticipants.MULTIPLE_SMALL_GROUPS => TB("13 - 20 (multiple small groups)"),
NumberParticipants.MULTIPLE_LARGE_GROUPS => TB("21 - 30 (multiple large groups)"),
NumberParticipants.SYMPOSIUM => "31 - 100 (symposium)",
NumberParticipants.CONFERENCE => "101 - 200 (conference)",
NumberParticipants.CONGRESS => "201 - 1,000 (congress)",
NumberParticipants.SYMPOSIUM => TB("31 - 100 (symposium)"),
NumberParticipants.CONFERENCE => TB("101 - 200 (conference)"),
NumberParticipants.CONGRESS => TB("201 - 1,000 (congress)"),
NumberParticipants.LARGE_EVENT => "1,000+ (large event)",
NumberParticipants.LARGE_EVENT => TB("1,000+ (large event)"),
_ => "Unknown"
};
@@ -4,23 +4,20 @@
<div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
@(this.Title)
</MudText>
<MudStack Row="true" AlignItems="AlignItems.Center" Class="mb-2 mr-3" StretchItems="StretchItems.Start">
<MudText Typo="Typo.h3">
@this.Title
</MudText>
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" OnClick="@(async () => await this.OpenSettingsDialog())"/>
</MudStack>
<InnerScrolling>
<ChildContent>
<MudForm @ref="@(this.form)" @bind-IsValid="@(this.inputIsValid)" @bind-Errors="@(this.inputIssues)" FieldChanged="@this.TriggerFormChange" Class="pr-2">
<MudGrid Class="mb-2">
<MudItem xs="10">
<MudText Typo="Typo.body1" Align="Align.Justify">
@this.Description
</MudText>
</MudItem>
<MudItem xs="2" Class="d-flex justify-end align-start">
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Settings" OnClick="() => this.OpenSettingsDialog()"/>
</MudItem>
</MudGrid>
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-2">
@this.Description
</MudText>
@if (this.Body is not null)
{
@@ -29,13 +26,13 @@
</CascadingValue>
<MudStack Row="true" AlignItems="AlignItems.Center" StretchItems="StretchItems.Start" Class="mb-3">
<MudButton Disabled="@this.SubmitDisabled" Variant="Variant.Filled" OnClick="async () => await this.Start()" Style="@this.SubmitButtonStyle">
<MudButton Disabled="@this.SubmitDisabled" Variant="Variant.Filled" OnClick="@(async () => await this.Start())" Style="@this.SubmitButtonStyle">
@this.SubmitText
</MudButton>
@if (this.isProcessing && this.cancellationTokenSource is not null)
{
<MudTooltip Text="@TB("Stop generation")">
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Stop" Color="Color.Error" OnClick="() => this.CancelStreaming()"/>
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Stop" Color="Color.Error" OnClick="@(async () => await this.CancelStreaming())"/>
</MudTooltip>
}
</MudStack>
@@ -74,7 +71,7 @@
</div>
</ChildContent>
<FooterContent>
<MudStack Row="@true" Wrap="Wrap.Wrap" Class="ma-1">
<MudStack Row="@true" Wrap="Wrap.Wrap" AlignItems="AlignItems.Center" StretchItems="StretchItems.None" Class="ma-1">
@if (!this.FooterButtons.Any(x => x.Type is ButtonTypes.SEND_TO))
{
@@ -83,7 +80,7 @@
<MudMenu AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomLeft" StartIcon="@Icons.Material.Filled.Apps" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@TB("Send to ...")" Variant="Variant.Filled" Style="@this.GetSendToColor()" Class="rounded">
@foreach (var assistant in Enum.GetValues<Components>().Where(n => n.AllowSendTo()).OrderBy(n => n.Name().Length))
{
<MudMenuItem OnClick="() => this.SendToAssistant(assistant, new())">
<MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, new()))">
@assistant.Name()
</MudMenuItem>
}
@@ -97,14 +94,14 @@
{
case ButtonData buttonData when !string.IsNullOrWhiteSpace(buttonData.Tooltip):
<MudTooltip Text="@buttonData.Tooltip">
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" Disabled="@buttonData.DisabledAction()" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" Disabled="@buttonData.DisabledAction()" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="@(async () => await buttonData.AsyncAction())">
@buttonData.Text
</MudButton>
</MudTooltip>
break;
case ButtonData buttonData:
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" Disabled="@buttonData.DisabledAction()" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" Disabled="@buttonData.DisabledAction()" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="@(async () => await buttonData.AsyncAction())">
@buttonData.Text
</MudButton>
break;
@@ -113,7 +110,7 @@
<MudMenu AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomLeft" StartIcon="@Icons.Material.Filled.Apps" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@TB("Send to ...")" Variant="Variant.Filled" Style="@this.GetSendToColor()" Class="rounded">
@foreach (var assistant in Enum.GetValues<Components>().Where(n => n.AllowSendTo()).OrderBy(n => n.Name().Length))
{
<MudMenuItem OnClick="() => this.SendToAssistant(assistant, sendToButton)">
<MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, sendToButton))">
@assistant.Name()
</MudMenuItem>
}
@@ -124,14 +121,14 @@
@if (this.ShowCopyResult)
{
<MudButton Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.ContentCopy" OnClick="() => this.CopyToClipboard()">
<MudButton Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.ContentCopy" OnClick="@(async () => await this.CopyToClipboard())">
@TB("Copy result")
</MudButton>
}
@if (this.ShowReset)
{
<MudButton Variant="Variant.Filled" Style="@this.GetResetColor()" StartIcon="@Icons.Material.Filled.Refresh" OnClick="() => this.InnerResetForm()">
<MudButton Variant="Variant.Filled" Style="@this.GetResetColor()" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@(async () => await this.InnerResetForm())">
@TB("Reset")
</MudButton>
}
@@ -20,9 +20,6 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
[Inject]
protected IJSRuntime JsRuntime { get; init; } = null!;
[Inject]
protected ThreadSafeRandom RNG { get; init; } = null!;
[Inject]
protected ISnackbar Snackbar { get; init; } = null!;
@@ -85,10 +82,11 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
protected AIStudio.Settings.Provider providerSettings;
protected AIStudio.Settings.Provider providerSettings = Settings.Provider.NONE;
protected MudForm? form;
protected bool inputIsValid;
protected Profile currentProfile = Profile.NO_PROFILE;
protected ChatTemplate currentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE;
protected ChatThread? chatThread;
protected IContent? lastUserPrompt;
protected CancellationTokenSource? cancellationTokenSource;
@@ -115,6 +113,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
this.MightPreselectValues();
this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
}
protected override async Task OnParametersSetAsync()
@@ -144,7 +143,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected string? ValidatingProvider(AIStudio.Settings.Provider provider)
{
if(provider.UsedLLMProvider == LLMProviders.NONE)
return "Please select a provider.";
return this.TB("Please select a provider.");
return null;
}
@@ -196,8 +195,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
SystemPrompt = this.SystemPrompt,
WorkspaceId = Guid.Empty,
ChatId = Guid.NewGuid(),
Name = string.Format(T("Assistant - {0}"), this.Title),
Seed = this.RNG.Next(),
Name = string.Format(this.TB("Assistant - {0}"), this.Title),
Blocks = [],
};
}
@@ -213,7 +211,6 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
WorkspaceId = workspaceId,
ChatId = chatId,
Name = name,
Seed = this.RNG.Next(),
Blocks = [],
};
@@ -242,6 +239,9 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected async Task<string> AddAIResponseAsync(DateTimeOffset time, bool hideContentFromUser = false)
{
var manageCancellationLocally = this.cancellationTokenSource is null;
this.cancellationTokenSource ??= new CancellationTokenSource();
var aiText = new ContentText
{
// We have to wait for the remote
@@ -270,11 +270,17 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, this.lastUserPrompt, this.chatThread, this.cancellationTokenSource!.Token);
this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.providerSettings.Model, this.lastUserPrompt, this.chatThread, this.cancellationTokenSource!.Token);
this.isProcessing = false;
this.StateHasChanged();
if(manageCancellationLocally)
{
this.cancellationTokenSource.Dispose();
this.cancellationTokenSource = null;
}
// Return the AI response:
return aiText.Text;
}
@@ -341,13 +347,15 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
private async Task InnerResetForm()
{
this.resultingContentBlock = null;
this.providerSettings = default;
this.providerSettings = Settings.Provider.NONE;
await this.JsRuntime.ClearDiv(RESULT_DIV_ID);
await this.JsRuntime.ClearDiv(AFTER_RESULT_DIV_ID);
this.ResetForm();
this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
this.inputIsValid = false;
this.inputIssues = [];
@@ -373,7 +381,17 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected override void DisposeResources()
{
this.formChangeTimer.Dispose();
try
{
this.formChangeTimer.Stop();
this.formChangeTimer.Dispose();
}
catch
{
// ignore
}
base.DisposeResources();
}
#endregion
@@ -5,10 +5,10 @@
<b>Links:</b>
</MudText>
<MudList T="string" Class="mb-6">
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://en.wikipedia.org/wiki/List_of_cognitive_biases">Wikipedia list of cognitive biases</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://commons.wikimedia.org/wiki/File:Cognitive_Bias_Codex_With_Definitions_1-2,_an_Extension_of_the_work_of_John_Manoogian_by_Brian_Rene_Morrissette.png">Extended bias poster</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://betterhumans.pub/cognitive-bias-cheat-sheet-55a472476b18">Blog post of Buster Benson: "Cognitive bias cheat sheet"</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://en.wikipedia.org/wiki/List_of_cognitive_biases">@T("Wikipedia list of cognitive biases")</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://commons.wikimedia.org/wiki/File:Cognitive_Bias_Codex_With_Definitions_1-2,_an_Extension_of_the_work_of_John_Manoogian_by_Brian_Rene_Morrissette.png">@T("Extended bias poster")</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://betterhumans.pub/cognitive-bias-cheat-sheet-55a472476b18">@T("Blog post of Buster Benson:") "Cognitive bias cheat sheet"</MudListItem>
</MudList>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -10,18 +10,9 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
{
public override Tools.Components Component => Tools.Components.BIAS_DAY_ASSISTANT;
protected override string Title => "Bias of the Day";
protected override string Title => T("Bias of the Day");
protected override string Description =>
"""
Learn about a different cognitive bias every day. You can also ask the LLM your questions. The idea behind
"Bias of the Day" is based on work by Buster Benson, John Manoogian III, and Brian Rene Morrissette. Buster
Benson grouped the biases, and the original texts come from Wikipedia. Brian Rene Morrissette condensed them
into a shorter version. Finally, John Manoogian III created the original poster based on Benson's work and
Morrissette's texts. Thorsten Sommer compared all texts for integration into AI Studio with the current Wikipedia
versions, updated them, and added source references. The idea of learning about one bias each day based on John's
poster comes from Drew Nelson.
""";
protected override string Description => T("""Learn about a different cognitive bias every day. You can also ask the LLM your questions. The idea behind "Bias of the Day" is based on work by Buster Benson, John Manoogian III, and Brian Rene Morrissette. Buster Benson grouped the biases, and the original texts come from Wikipedia. Brian Rene Morrissette condensed them into a shorter version. Finally, John Manoogian III created the original poster based on Benson's work and Morrissette's texts. Thorsten Sommer compared all texts for integration into AI Studio with the current Wikipedia versions, updated them, and added source references. The idea of learning about one bias each day based on John's poster comes from Drew Nelson.""");
protected override string SystemPrompt => $"""
You are a friendly, helpful expert on cognitive bias. You studied psychology and
@@ -41,7 +32,7 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Show me the bias of the day";
protected override string SubmitText => T("Show me the bias of the day");
protected override Func<Task> SubmitAction => this.TellBias;
@@ -79,7 +70,7 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
private string? ValidateTargetLanguage(CommonLanguages language)
{
if(language is CommonLanguages.AS_IS)
return "Please select a target language for the bias.";
return T("Please select a target language for the bias.");
return null;
}
@@ -87,7 +78,7 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return T("Please provide a custom language.");
return null;
}
@@ -6,22 +6,22 @@
{
var codingContext = this.codingContexts[contextIndex];
var index = contextIndex;
<ExpansionPanel HeaderText="@codingContext.Id" HeaderIcon="@Icons.Material.Filled.Code" ShowEndButton="@true" EndButtonColor="Color.Error" EndButtonIcon="@Icons.Material.Filled.Delete" EndButtonTooltip="Delete context" EndButtonClickAsync="@(() => this.DeleteContext(index))">
<ExpansionPanel HeaderText="@codingContext.Id" HeaderIcon="@Icons.Material.Filled.Code" ShowEndButton="@true" EndButtonColor="Color.Error" EndButtonIcon="@Icons.Material.Filled.Delete" EndButtonTooltip="@T("Delete context")" EndButtonClickAsync="@(() => this.DeleteContext(index))">
<CodingContextItem @bind-CodingContext="@codingContext"/>
</ExpansionPanel>
}
</MudExpansionPanels>
<MudButton Variant="Variant.Filled" OnClick="() => this.AddCodingContext()" Class="mb-3">
Add context
@T("Add context")
</MudButton>
<MudStack Row="@false" Class="mb-3">
<MudTextSwitch Label="Do you want to provide compiler messages?" @bind-Value="@this.provideCompilerMessages" LabelOn="Yes, provide compiler messages" LabelOff="No, there are no compiler messages" />
<MudTextSwitch Label="@T("Do you want to provide compiler messages?")" @bind-Value="@this.provideCompilerMessages" LabelOn="@T("Yes, provide compiler messages")" LabelOff="@T("No, there are no compiler messages")" />
@if (this.provideCompilerMessages)
{
<MudTextField T="string" @bind-Text="@this.compilerMessages" Validation="@this.ValidatingCompilerMessages" AdornmentIcon="@Icons.Material.Filled.Error" Adornment="Adornment.Start" Label="Compiler messages" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @bind-Text="@this.compilerMessages" Validation="@this.ValidatingCompilerMessages" AdornmentIcon="@Icons.Material.Filled.Error" Adornment="Adornment.Start" Label="@T("Compiler messages")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
}
</MudStack>
<MudTextField T="string" @bind-Text="@this.questions" Validation="@this.ValidateQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionMark" Adornment="Adornment.Start" Label="Your question(s)" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @bind-Text="@this.questions" Validation="@this.ValidateQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionMark" Adornment="Adornment.Start" Label="@T("Your question(s)")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -8,14 +8,9 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
{
public override Tools.Components Component => Tools.Components.CODING_ASSISTANT;
protected override string Title => "Coding Assistant";
protected override string Title => T("Coding Assistant");
protected override string Description =>
"""
This coding assistant supports you in writing code. Provide some coding context by copying and pasting
your code into the input fields. You might assign an ID to your code snippet to easily reference it later.
When you have compiler messages, you can paste them into the input fields to get help with debugging as well.
""";
protected override string Description => T("This coding assistant supports you in writing code. Provide some coding context by copying and pasting your code into the input fields. You might assign an ID to your code snippet to easily reference it later. When you have compiler messages, you can paste them into the input fields to get help with debugging as well.");
protected override string SystemPrompt =>
"""
@@ -30,7 +25,7 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Get Support";
protected override string SubmitText => T("Get Support");
protected override Func<Task> SubmitAction => this.GetSupport;
@@ -80,7 +75,7 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
return null;
if(string.IsNullOrWhiteSpace(checkCompilerMessages))
return "Please provide the compiler messages.";
return T("Please provide the compiler messages.");
return null;
}
@@ -88,7 +83,7 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
private string? ValidateQuestions(string checkQuestions)
{
if(string.IsNullOrWhiteSpace(checkQuestions))
return "Please provide your questions.";
return T("Please provide your questions.");
return null;
}
@@ -97,7 +92,7 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
{
this.codingContexts.Add(new()
{
Id = $"Context {this.codingContexts.Count + 1}",
Id = string.Format(T("Context {0}"), this.codingContexts.Count + 1),
Language = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage : default,
OtherLanguage = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage : string.Empty,
});
@@ -1,14 +1,18 @@
<MudTextField T="string" @bind-Text="@this.CodingContext.Id" AdornmentIcon="@Icons.Material.Filled.Numbers" Adornment="Adornment.Start" Label="(Optional) Identifier" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
@inherits MSGComponentBase
<MudTextField T="string" @bind-Text="@this.CodingContext.Id" AdornmentIcon="@Icons.Material.Filled.Numbers" Adornment="Adornment.Start" Label="@T("(Optional) Identifier")" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudStack Row="@true" Class="mb-3">
<MudSelect T="CommonCodingLanguages" @bind-Value="@this.CodingContext.Language" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="Language" Variant="Variant.Outlined" Margin="Margin.Dense">
<MudSelect T="CommonCodingLanguages" @bind-Value="@this.CodingContext.Language" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="@T("Language")" Variant="Variant.Outlined" Margin="Margin.Dense">
@foreach (var language in Enum.GetValues<CommonCodingLanguages>())
{
<MudSelectItem Value="@language">@language.Name()</MudSelectItem>
<MudSelectItem Value="@language">
@language.Name()
</MudSelectItem>
}
</MudSelect>
@if (this.CodingContext.Language is CommonCodingLanguages.OTHER)
{
<MudTextField T="string" @bind-Text="@this.CodingContext.OtherLanguage" Validation="@this.ValidatingOtherLanguage" Label="Other language" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @bind-Text="@this.CodingContext.OtherLanguage" Validation="@this.ValidatingOtherLanguage" Label="@T("Other language")" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
}
</MudStack>
<MudTextField T="string" @bind-Text="@this.CodingContext.Code" Validation="@this.ValidatingCode" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your code" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" />
<MudTextField T="string" @bind-Text="@this.CodingContext.Code" Validation="@this.ValidatingCode" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your code")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" />
@@ -1,19 +1,16 @@
using AIStudio.Settings;
using AIStudio.Components;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Assistants.Coding;
public partial class CodingContextItem : ComponentBase
public partial class CodingContextItem : MSGComponentBase
{
[Parameter]
public CodingContext CodingContext { get; set; } = new();
[Parameter]
public EventCallback<CodingContext> CodingContextChanged { get; set; }
[Inject]
protected SettingsManager SettingsManager { get; set; } = null!;
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
@@ -32,7 +29,7 @@ public partial class CodingContextItem : ComponentBase
private string? ValidatingCode(string code)
{
if(string.IsNullOrWhiteSpace(code))
return $"{this.CodingContext.Id}: Please provide your input.";
return string.Format(T("{0}: Please provide your input."), this.CodingContext.Id);
return null;
}
@@ -43,7 +40,7 @@ public partial class CodingContextItem : ComponentBase
return null;
if(string.IsNullOrWhiteSpace(language))
return "Please specify the language.";
return T("Please specify the language.");
return null;
}
@@ -2,9 +2,11 @@
public static class CommonCodingLanguageExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(CommonCodingLanguageExtensions).Namespace, nameof(CommonCodingLanguageExtensions));
public static string Name(this CommonCodingLanguages language) => language switch
{
CommonCodingLanguages.NONE => "None",
CommonCodingLanguages.NONE => TB("None"),
CommonCodingLanguages.BASH => "Bash",
CommonCodingLanguages.BLAZOR => ".NET Blazor",
@@ -37,7 +39,7 @@ public static class CommonCodingLanguageExtensions
CommonCodingLanguages.TYPESCRIPT => "TypeScript",
CommonCodingLanguages.XML => "XML",
CommonCodingLanguages.OTHER => "Other",
_ => "Unknown"
CommonCodingLanguages.OTHER => TB("Other"),
_ => TB("Unknown")
};
}
@@ -10,7 +10,7 @@
}
<MudTextField T="string" @bind-Text="@this.inputGreeting" Label="@T("(Optional) The greeting phrase to use")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Placeholder="@T("Dear Colleagues")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputBulletPoints" Validation="@this.ValidateBulletPoints" AdornmentIcon="@Icons.Material.Filled.ListAlt" Adornment="Adornment.Start" Label="@T("Your bullet points")" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Bullet list the content of the e-mail roughly. Use dashes (-) to separate the items.")" Immediate="@false" DebounceInterval="1_000" OnDebounceIntervalElapsed="@this.OnContentChanged" Placeholder="@PLACEHOLDER_BULLET_POINTS"/>
<DebouncedTextField @bind-Text="@this.inputBulletPoints" ValidationFunc="@this.ValidateBulletPoints" Icon="@Icons.Material.Filled.ListAlt" Label="@T("Your bullet points")" Lines="6" MaxLines="12" Attributes="@USER_INPUT_ATTRIBUTES" HelpText="@T("Bullet list the content of the e-mail roughly. Use dashes (-) to separate the items.")" DebounceTime="TimeSpan.FromSeconds(1)" WhenTextCanged="@this.OnContentChanged" Placeholder="@PLACEHOLDER_BULLET_POINTS"/>
<MudSelect T="string" Label="@T("(Optional) Are any of your points particularly important?")" MultiSelection="@true" @bind-SelectedValues="@this.selectedFoci" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
@foreach (var contentLine in this.bulletPointsLines)
{
@@ -2,14 +2,16 @@ namespace AIStudio.Assistants.EMail;
public static class WritingStylesExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(WritingStylesExtensions).Namespace, nameof(WritingStylesExtensions));
public static string Name(this WritingStyles style) => style switch
{
WritingStyles.ACADEMIC => "Academic",
WritingStyles.PERSONAL => "Personal",
WritingStyles.BUSINESS_FORMAL => "Business formal",
WritingStyles.BUSINESS_INFORMAL => "Business informal",
WritingStyles.ACADEMIC => TB("Academic"),
WritingStyles.PERSONAL => TB("Personal"),
WritingStyles.BUSINESS_FORMAL => TB("Business formal"),
WritingStyles.BUSINESS_INFORMAL => TB("Business informal"),
_ => "Not specified",
_ => TB("Not specified"),
};
public static string Prompt(this WritingStyles style) => style switch
@@ -2,12 +2,14 @@ namespace AIStudio.Assistants.ERI;
public static class AllowedLLMProvidersExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(AllowedLLMProvidersExtensions).Namespace, nameof(AllowedLLMProvidersExtensions));
public static string Description(this AllowedLLMProviders provider) => provider switch
{
AllowedLLMProviders.NONE => "Please select what kind of LLM provider are allowed for this data source",
AllowedLLMProviders.ANY => "Any LLM provider is allowed: users might choose a cloud-based or a self-hosted provider",
AllowedLLMProviders.SELF_HOSTED => "Self-hosted LLM providers are allowed: users cannot choose any cloud-based provider",
AllowedLLMProviders.NONE => TB("Please select what kind of LLM provider are allowed for this data source"),
AllowedLLMProviders.ANY => TB("Any LLM provider is allowed: users might choose a cloud-based or a self-hosted provider"),
AllowedLLMProviders.SELF_HOSTED => TB("Self-hosted LLM providers are allowed: users cannot choose any cloud-based provider"),
_ => "Unknown option was selected"
_ => TB("Unknown option was selected")
};
}
@@ -4,36 +4,38 @@
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogERIServer>
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
You can imagine it like this: Hypothetically, when Wikipedia implemented the ERI, it would vectorize
all pages using an embedding method. All of Wikipedia’s data would remain with Wikipedia, including the
vector database (decentralized approach). Then, any AI Studio user could add Wikipedia as a data source to
significantly reduce the hallucination of the LLM in knowledge questions.
@T("You can imagine it like this: Hypothetically, when Wikipedia implemented the ERI, it would vectorize all pages using an embedding method. All of Wikipedia’s data would remain with Wikipedia, including the vector database (decentralized approach). Then, any AI Studio user could add Wikipedia as a data source to significantly reduce the hallucination of the LLM in knowledge questions.")
</MudJustifiedText>
<MudText Typo="Typo.body1">
<b>Related links:</b>
<b>
@T("Related links:")
</b>
</MudText>
<MudList T="string" Class="mb-6">
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://github.com/MindWorkAI/ERI">ERI repository with example implementation in .NET and C#</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://mindworkai.org/swagger-ui.html">Interactive documentation aka Swagger UI</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://github.com/MindWorkAI/ERI">
@T("ERI repository with example implementation in .NET and C#")
</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://mindworkai.org/swagger-ui.html">
@T("Interactive documentation aka Swagger UI")
</MudListItem>
</MudList>
<PreviewPrototype/>
<div class="mb-6"></div>
<MudText Typo="Typo.h4" Class="mb-3">
ERI server presets
@T("ERI server presets")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
Here you have the option to save different configurations for various ERI servers and switch between them. This is useful if
you are responsible for multiple ERI servers.
@T("Here you have the option to save different configurations for various ERI servers and switch between them. This is useful if you are responsible for multiple ERI servers.")
</MudJustifiedText>
@if(this.SettingsManager.ConfigurationData.ERI.ERIServers.Count is 0)
{
<MudText Typo="Typo.body1" Class="mb-3">
You have not yet added any ERI server presets.
@T("You have not yet added any ERI server presets.")
</MudText>
}
else
@@ -50,112 +52,116 @@ else
<MudStack Row="@true" Class="mt-1">
<MudButton Disabled="@this.AreServerPresetsBlocked" OnClick="@this.AddERIServer" Variant="Variant.Filled" Color="Color.Primary">
Add ERI server preset
@T("Add ERI server preset")
</MudButton>
<MudButton OnClick="@this.RemoveERIServer" Disabled="@(this.AreServerPresetsBlocked || this.IsNoneERIServerSelected)" Variant="Variant.Filled" Color="Color.Error">
Delete this server preset
@T("Delete this server preset")
</MudButton>
</MudStack>
@if(this.AreServerPresetsBlocked)
{
<MudJustifiedText Typo="Typo.body1" Class="mb-3 mt-3">
Hint: to allow this assistant to manage multiple presets, you must enable the preselection of values in the settings.
@T("Hint: to allow this assistant to manage multiple presets, you must enable the preselection of values in the settings.")
</MudJustifiedText>
}
<MudText Typo="Typo.h4" Class="mb-3 mt-6">
Auto save
@T("Auto save")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
The ERI specification will change over time. You probably want to keep your ERI server up to date. This means you might want to
regenerate the code for your ERI server. To avoid having to make all inputs each time, all your inputs and decisions can be
automatically saved. Would you like this?
@T("The ERI specification will change over time. You probably want to keep your ERI server up to date. This means you might want to regenerate the code for your ERI server. To avoid having to make all inputs each time, all your inputs and decisions can be automatically saved. Would you like this?")
</MudJustifiedText>
@if(this.AreServerPresetsBlocked)
{
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
Hint: to allow this assistant to automatically save your changes, you must enable the preselection of values in the settings.
@T("Hint: to allow this assistant to automatically save your changes, you must enable the preselection of values in the settings.")
</MudJustifiedText>
}
<MudTextSwitch Label="Should we automatically save any input made?" Disabled="@this.AreServerPresetsBlocked" @bind-Value="@this.autoSave" LabelOn="Yes, please save my inputs" LabelOff="No, I will enter everything again or configure it manually in the settings" />
<MudTextSwitch Label="@T("Should we automatically save any input made?")" Disabled="@this.AreServerPresetsBlocked" @bind-Value="@this.autoSave" LabelOn="@T("Yes, please save my inputs")" LabelOff="@T("No, I will enter everything again or configure it manually in the settings")" />
<hr style="width: 100%; border-width: 0.25ch;" class="mt-6"/>
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
Common ERI server settings
@T("Common ERI server settings")
</MudText>
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverName" Validation="@this.ValidateServerName" Immediate="@true" Label="ERI server name" HelperText="Please give your ERI server a name that provides information about the data source and/or its 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.ServerNameWasChanged()"/>
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverDescription" Validation="@this.ValidateServerDescription" Immediate="@true" Label="ERI server description" HelperText="Please provide a brief description of your ERI server. Describe or explain what your ERI server does and what data it uses for this purpose. 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"/>
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverName" Validation="@this.ValidateServerName" Immediate="@true" Label="@T("ERI server name")" HelperText="@T("Please give your ERI server a name that provides information about the data source and/or its 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.ServerNameWasChanged()"/>
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverDescription" Validation="@this.ValidateServerDescription" Immediate="@true" Label="@T("ERI server description")" HelperText="@T("Please provide a brief description of your ERI server. Describe or explain what your ERI server does and what data it uses for this purpose. 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"/>
<MudStack Row="@true" Class="mb-3">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ProgrammingLanguages" @bind-Value="@this.selectedProgrammingLanguage" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="Programming language" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateProgrammingLanguage">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ProgrammingLanguages" @bind-Value="@this.selectedProgrammingLanguage" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="@T("Programming language")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateProgrammingLanguage">
@foreach (var language in Enum.GetValues<ProgrammingLanguages>())
{
<MudSelectItem Value="@language">@language.Name()</MudSelectItem>
<MudSelectItem Value="@language">
@language.Name()
</MudSelectItem>
}
</MudSelect>
@if (this.selectedProgrammingLanguage is ProgrammingLanguages.OTHER)
{
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherProgrammingLanguage" Validation="@this.ValidateOtherLanguage" Label="Other language" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherProgrammingLanguage" Validation="@this.ValidateOtherLanguage" Label="@T("Other language")" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
}
</MudStack>
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ERIVersion" @bind-Value="@this.selectedERIVersion" Label="ERI specification version" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateERIVersion">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ERIVersion" @bind-Value="@this.selectedERIVersion" Label="@T("ERI specification version")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateERIVersion">
@foreach (var version in Enum.GetValues<ERIVersion>())
{
<MudSelectItem Value="@version">@version</MudSelectItem>
<MudSelectItem Value="@version">
@version
</MudSelectItem>
}
</MudSelect>
<MudButton Variant="Variant.Outlined" Size="Size.Small" Disabled="@(!this.selectedERIVersion.WasSpecificationSelected() || this.IsNoneERIServerSelected)" Href="@this.selectedERIVersion.SpecificationURL()" Target="_blank">
<MudIcon Icon="@Icons.Material.Filled.Link" Class="mr-2"/> Download specification
<MudIcon Icon="@Icons.Material.Filled.Link" Class="mr-2"/> @T("Download specification")
</MudButton>
</MudStack>
<MudText Typo="Typo.h4" Class="mt-9 mb-3">
Data source settings
@T("Data source settings")
</MudText>
<MudStack Row="@false" Spacing="1" Class="mb-3">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="DataSources" @bind-Value="@this.selectedDataSource" AdornmentIcon="@Icons.Material.Filled.Dataset" Adornment="Adornment.Start" Label="Data source" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateDataSource" SelectedValuesChanged="@this.DataSourceWasChanged">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="DataSources" @bind-Value="@this.selectedDataSource" AdornmentIcon="@Icons.Material.Filled.Dataset" Adornment="Adornment.Start" Label="@T("Data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateDataSource" SelectedValuesChanged="@this.DataSourceWasChanged">
@foreach (var dataSource in Enum.GetValues<DataSources>())
{
<MudSelectItem Value="@dataSource">@dataSource.Name()</MudSelectItem>
<MudSelectItem Value="@dataSource">
@dataSource.Name()
</MudSelectItem>
}
</MudSelect>
@if (this.selectedDataSource is DataSources.CUSTOM)
{
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherDataSource" Validation="@this.ValidateOtherDataSource" Label="Describe your data source" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherDataSource" Validation="@this.ValidateOtherDataSource" Label="@T("Describe your data source")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
}
</MudStack>
@if(this.selectedDataSource > DataSources.FILE_SYSTEM)
{
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceProductName" Label="Data source: product name" Validation="@this.ValidateDataSourceProductName" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceProductName" Label="@T("Data source: product name")" Validation="@this.ValidateDataSourceProductName" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
}
@if (this.NeedHostnamePort())
{
<div class="mb-3">
<MudStack Row="@true">
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceHostname" Label="Data source: hostname" Validation="@this.ValidateHostname" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudNumericField Disabled="@this.IsNoneERIServerSelected" Label="Data source: port" Immediate="@true" Min="1" Max="65535" Validation="@this.ValidatePort" @bind-Value="@this.dataSourcePort" Variant="Variant.Outlined" Margin="Margin.Dense" OnKeyUp="() => this.DataSourcePortWasTyped()"/>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceHostname" Label="@T("Data source: hostname")" Validation="@this.ValidateHostname" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudNumericField Disabled="@this.IsNoneERIServerSelected" Label="@T("Data source: port")" Immediate="@true" Min="1" Max="65535" Validation="@this.ValidatePort" @bind-Value="@this.dataSourcePort" Variant="Variant.Outlined" Margin="Margin.Dense" OnKeyUp="() => this.DataSourcePortWasTyped()"/>
</MudStack>
@if (this.dataSourcePort < 1024)
{
<MudText Typo="Typo.body2">
<b>Warning:</b> Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user).
<b>@T("Warning:")</b> @T("Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user).")
</MudText>
}
</div>
}
<MudText Typo="Typo.h4" Class="mt-9 mb-3">
Authentication settings
@T("Authentication settings")
</MudText>
<MudStack Row="@false" Spacing="1" Class="mb-1">
@@ -168,12 +174,14 @@ else
SelectedValues="@this.selectedAuthenticationMethods"
Validation="@this.ValidateAuthenticationMethods"
SelectedValuesChanged="@this.AuthenticationMethodWasChanged"
Label="Authentication method(s)"
Label="@T("Authentication method(s)")"
Variant="Variant.Outlined"
Margin="Margin.Dense">
@foreach (var authMethod in Enum.GetValues<Auth>())
{
<MudSelectItemExtended Value="@authMethod">@authMethod.Name()</MudSelectItemExtended>
<MudSelectItemExtended Value="@authMethod">
@authMethod.Name()
</MudSelectItemExtended>
}
</MudSelectExtended>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.authDescription" Label="@this.AuthDescriptionTitle()" Validation="@this.ValidateAuthDescription" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
@@ -181,40 +189,39 @@ else
@if (this.selectedAuthenticationMethods.Contains(Auth.KERBEROS))
{
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="OperatingSystem" @bind-Value="@this.selectedOperatingSystem" Label="Operating system on which your ERI will run" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateOperatingSystem" Class="mb-1">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="OperatingSystem" @bind-Value="@this.selectedOperatingSystem" Label="@T("Operating system on which your ERI will run")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateOperatingSystem" Class="mb-1">
@foreach (var os in Enum.GetValues<OperatingSystem>())
{
<MudSelectItem Value="@os">@os.Name()</MudSelectItem>
<MudSelectItem Value="@os">
@os.Name()
</MudSelectItem>
}
</MudSelect>
}
<MudText Typo="Typo.h4" Class="mt-11 mb-3">
Data protection settings
@T("Data protection settings")
</MudText>
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="AllowedLLMProviders" @bind-Value="@this.allowedLLMProviders" Label="Allowed LLM providers for this data source" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateAllowedLLMProviders" Class="mb-1">
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="AllowedLLMProviders" @bind-Value="@this.allowedLLMProviders" Label="@T("Allowed LLM providers for this data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateAllowedLLMProviders" Class="mb-1">
@foreach (var option in Enum.GetValues<AllowedLLMProviders>())
{
<MudSelectItem Value="@option">@option.Description()</MudSelectItem>
<MudSelectItem Value="@option">
@option.Description()
</MudSelectItem>
}
</MudSelect>
<MudText Typo="Typo.h4" Class="mt-11 mb-3">
Embedding settings
@T("Embedding settings")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector
space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't
have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You
store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't
need embeddings.
@T("You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings.")
</MudJustifiedText>
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
You can specify more than one embedding method. This can be useful when you want to use different embeddings for different queries
or data types. For example, one embedding for texts, another for images, and a third for videos, etc.
@T("You can specify more than one embedding method. This can be useful when you want to use different embeddings for different queries or data types. For example, one embedding for texts, another for images, and a third for videos, etc.")
</MudJustifiedText>
@if (!this.IsNoneERIServerSelected)
@@ -226,9 +233,9 @@ else
<col style="width: 34em;"/>
</ColGroup>
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Type</MudTh>
<MudTh>Actions</MudTh>
<MudTh>@T("Name")</MudTh>
<MudTh>@T("Type")</MudTh>
<MudTh>@T("Actions")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.EmbeddingName</MudTd>
@@ -236,10 +243,10 @@ else
<MudTd>
<MudStack Row="true" Class="mb-2 mt-2" Wrap="Wrap.Wrap">
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditEmbedding(context)">
Edit
@T("Edit")
</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteEmbedding(context)">
Delete
@T("Delete")
</MudButton>
</MudStack>
</MudTd>
@@ -248,23 +255,22 @@ else
@if (this.embeddings.Count == 0)
{
<MudText Typo="Typo.h6" Class="mt-3">No embedding methods configured yet.</MudText>
<MudText Typo="Typo.h6" Class="mt-3">
@T("No embedding methods configured yet.")
</MudText>
}
}
<MudButton Disabled="@this.IsNoneERIServerSelected" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbedding">
Add Embedding Method
@T("Add Embedding Method")
</MudButton>
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
Data retrieval settings
@T("Data retrieval settings")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
For your ERI server, you need to retrieve data that matches a chat or prompt in some way. We call this the retrieval process.
You must describe at least one such process. You may offer several retrieval processes from which users can choose. This allows
you to test with beta users which process works better. Or you might generally want to give users the choice so they can select
the process that best suits their circumstances.
@T("For your ERI server, you need to retrieve data that matches a chat or prompt in some way. We call this the retrieval process. You must describe at least one such process. You may offer several retrieval processes from which users can choose. This allows you to test with beta users which process works better. Or you might generally want to give users the choice so they can select the process that best suits their circumstances.")
</MudJustifiedText>
@if (!this.IsNoneERIServerSelected)
@@ -275,18 +281,18 @@ else
<col style="width: 34em;"/>
</ColGroup>
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Actions</MudTh>
<MudTh>@T("Name")</MudTh>
<MudTh>@T("Actions")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Name</MudTd>
<MudTd>
<MudStack Row="true" Class="mb-2 mt-2" Wrap="Wrap.Wrap">
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditRetrievalProcess(context)">
Edit
@T("Edit")
</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteRetrievalProcess(context)">
Delete
@T("Delete")
</MudButton>
</MudStack>
</MudTd>
@@ -295,59 +301,47 @@ else
@if (this.retrievalProcesses.Count == 0)
{
<MudText Typo="Typo.h6" Class="mt-3">No retrieval process configured yet.</MudText>
<MudText Typo="Typo.h6" Class="mt-3">
@T("No retrieval process configured yet.")
</MudText>
}
}
<MudButton Disabled="@this.IsNoneERIServerSelected" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddRetrievalProcess">
Add Retrieval Process
@T("Add Retrieval Process")
</MudButton>
<MudJustifiedText Typo="Typo.body1" Class="mb-1">
You can integrate additional libraries. Perhaps you want to evaluate the prompts in advance using a machine learning method or analyze them with a text
mining approach? Or maybe you want to preprocess images in the prompts? For such advanced scenarios, you can specify which libraries you want to use here.
It's best to describe which library you want to integrate for which purpose. This way, the LLM that writes the ERI server for you can try to use these
libraries effectively. This should result in less rework being necessary. If you don't know the necessary libraries, you can instead attempt to describe
the intended use. The LLM can then attempt to choose suitable libraries. However, hallucinations can occur, and fictional libraries might be selected.
@T("You can integrate additional libraries. Perhaps you want to evaluate the prompts in advance using a machine learning method or analyze them with a text mining approach? Or maybe you want to preprocess images in the prompts? For such advanced scenarios, you can specify which libraries you want to use here. It's best to describe which library you want to integrate for which purpose. This way, the LLM that writes the ERI server for you can try to use these libraries effectively. This should result in less rework being necessary. If you don't know the necessary libraries, you can instead attempt to describe the intended use. The LLM can then attempt to choose suitable libraries. However, hallucinations can occur, and fictional libraries might be selected.")
</MudJustifiedText>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.additionalLibraries" Label="(Optional) Additional libraries" HelperText="Do you want to include additional libraries? Then name them and briefly describe what you want to achieve with them." Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="12" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.additionalLibraries" Label="@T("(Optional) Additional libraries")" HelperText="@T("Do you want to include additional libraries? Then name them and briefly describe what you want to achieve with them.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="12" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudText Typo="Typo.h4" Class="mt-9 mb-1">
Provider selection for generation
@T("Provider selection for generation")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task.
Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model.
@T("The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model.")
</MudJustifiedText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
<b>Important:</b> The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number
of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this.
<b>However, generating all the files takes a certain amount of time.</b> Local or self-hosted models may work without these limitations
and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.
<b>@T("Important:")</b> @T("The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this.") <b>@T("However, generating all the files takes a certain amount of time.")</b> @T("Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.")
</MudJustifiedText>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudText Typo="Typo.h4" Class="mt-9 mb-1">
Write code to file system
@T("Write code to file system")
</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
AI Studio can save the generated code to the file system. You can select a base folder for this. AI Studio ensures that no files are created
outside of this base folder. Furthermore, we recommend that you create a Git repository in this folder. This way, you can see what changes the
AI has made in which files.
@T("AI Studio can save the generated code to the file system. You can select a base folder for this. AI Studio ensures that no files are created outside of this base folder. Furthermore, we recommend that you create a Git repository in this folder. This way, you can see what changes the AI has made in which files.")
</MudJustifiedText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All
other files you have created remain. Then, the AI generates the new files. <b>But beware:</b> It may happen that the AI generates a
file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore,
you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization,
you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose.
@T("When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files.") <b>@T("But beware:")</b> @T("It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose.")
</MudJustifiedText>
<MudTextSwitch Label="Should we write the generated code to the file system?" Disabled="@this.IsNoneERIServerSelected" @bind-Value="@this.writeToFilesystem" LabelOn="Yes, please write or update all generated code to the file system" LabelOff="No, just show me the code" />
<SelectDirectory Label="Base directory where to write the code" @bind-Directory="@this.baseDirectory" Disabled="@(this.IsNoneERIServerSelected || !this.writeToFilesystem)" DirectoryDialogTitle="Select the target directory for the ERI server" Validation="@this.ValidateDirectory" />
<MudTextSwitch Label="@T("Should we write the generated code to the file system?")" Disabled="@this.IsNoneERIServerSelected" @bind-Value="@this.writeToFilesystem" LabelOn="@T("Yes, please write or update all generated code to the file system")" LabelOff="@T("No, just show me the code")" />
<SelectDirectory Label="@T("Base directory where to write the code")" @bind-Directory="@this.baseDirectory" Disabled="@(this.IsNoneERIServerSelected || !this.writeToFilesystem)" DirectoryDialogTitle="@T("Select the target directory for the ERI server")" Validation="@this.ValidateDirectory" />
@@ -22,16 +22,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
public override Tools.Components Component => Tools.Components.ERI_ASSISTANT;
protected override string Title => "ERI Server";
protected override string Title => T("ERI Server");
protected override string Description =>
"""
The ERI is the External Retrieval Interface for AI Studio and other tools. The ERI acts as a contract
between decentralized data sources and, e.g., AI Studio. The ERI is implemented by the data sources,
allowing them to be integrated into AI Studio later. This means that the data sources assume the server
role and AI Studio (or any other LLM tool) assumes the client role of the API. This approach serves to
realize a Retrieval-Augmented Generation (RAG) process with external data.
""";
protected override string Description => T("The ERI is the External Retrieval Interface for AI Studio and other tools. The ERI acts as a contract between decentralized data sources and, e.g., AI Studio. The ERI is implemented by the data sources, allowing them to be integrated into AI Studio later. This means that the data sources assume the server role and AI Studio (or any other LLM tool) assumes the client role of the API. This approach serves to realize a Retrieval-Augmented Generation (RAG) process with external data.");
protected override string SystemPrompt
{
@@ -44,7 +37,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
// Introduction
// ---------------------------------
//
var programmingLanguage = this.selectedProgrammingLanguage is ProgrammingLanguages.OTHER ? this.otherProgrammingLanguage : this.selectedProgrammingLanguage.Name();
var programmingLanguage = this.selectedProgrammingLanguage is ProgrammingLanguages.OTHER ? this.otherProgrammingLanguage : this.selectedProgrammingLanguage.ToPrompt();
sb.Append($"""
# Introduction
You are an experienced {programmingLanguage} developer. Your task is to implement an API server in
@@ -159,7 +152,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{
sb.Append($"""
The server will run on {this.selectedOperatingSystem.Name()} operating systems. Keep
The server will run on {this.selectedOperatingSystem.ToPrompt()} operating systems. Keep
this in mind when implementing the SSO with Kerberos.
""");
}
@@ -304,7 +297,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
protected override bool ShowSendTo => false;
protected override string SubmitText => "Create the ERI server";
protected override string SubmitText => T("Create the ERI server");
protected override Func<Task> SubmitAction => this.GenerateServer;
@@ -469,7 +462,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{
this.SettingsManager.ConfigurationData.ERI.ERIServers.Add(new ()
{
ServerName = $"ERI Server {DateTimeOffset.UtcNow}",
ServerName = string.Format(T("ERI Server {0}"), DateTimeOffset.UtcNow),
});
await this.SettingsManager.StoreSettings();
@@ -480,12 +473,12 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
if(this.selectedERIServer is null)
return;
var dialogParameters = new DialogParameters
var dialogParameters = new DialogParameters<ConfirmDialog>
{
{ "Message", $"Are you sure you want to delete the ERI server preset '{this.selectedERIServer.ServerName}'?" },
{ x => x.Message, string.Format(T("Are you sure you want to delete the ERI server preset '{0}'?"), this.selectedERIServer.ServerName) },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete ERI server preset", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete ERI server preset"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -518,13 +511,13 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private string? ValidateServerName(string name)
{
if(string.IsNullOrWhiteSpace(name))
return "Please provide a name for your ERI server. This name will be used to identify the server in AI Studio.";
return T("Please provide a name for your ERI server. This name will be used to identify the server in AI Studio.");
if(name.Length is > 60 or < 6)
return "The name of your ERI server must be between 6 and 60 characters long.";
return T("The name of your ERI server must be between 6 and 60 characters long.");
if(this.SettingsManager.ConfigurationData.ERI.ERIServers.Where(n => n != this.selectedERIServer).Any(n => n.ServerName == name))
return "An ERI server preset with this name already exists. Please choose a different name.";
return T("An ERI server preset with this name already exists. Please choose a different name.");
return null;
}
@@ -532,10 +525,10 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private string? ValidateServerDescription(string description)
{
if(string.IsNullOrWhiteSpace(description))
return "Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server.";
return T("Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server.");
if(description.Length is < 32 or > 512)
return "The description of your ERI server must be between 32 and 512 characters long.";
return T("The description of your ERI server must be between 32 and 512 characters long.");
return null;
}
@@ -543,7 +536,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private string? ValidateERIVersion(ERIVersion version)
{
if (version == ERIVersion.NONE)
return "Please select an ERI specification version for the ERI server.";
return T("Please select an ERI specification version for the ERI server.");
return null;
}
@@ -554,7 +547,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if (language == ProgrammingLanguages.NONE)
return "Please select a programming language for the ERI server.";
return T("Please select a programming language for the ERI server.");
return null;
}
@@ -565,7 +558,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(string.IsNullOrWhiteSpace(language))
return "Please specify the custom programming language for the ERI server.";
return T("Please specify the custom programming language for the ERI server.");
return null;
}
@@ -576,7 +569,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if (dataSource == DataSources.NONE)
return "Please select a data source for the ERI server.";
return T("Please select a data source for the ERI server.");
return null;
}
@@ -587,7 +580,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(string.IsNullOrWhiteSpace(productName))
return "Please specify the product name of the data source, e.g., 'MongoDB', 'Redis', 'PostgreSQL', 'Neo4j', or 'MinIO', etc.";
return T("Please specify the product name of the data source, e.g., 'MongoDB', 'Redis', 'PostgreSQL', 'Neo4j', or 'MinIO', etc.");
return null;
}
@@ -598,7 +591,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(string.IsNullOrWhiteSpace(dataSource))
return "Please describe the data source of your ERI server.";
return T("Please describe the data source of your ERI server.");
return null;
}
@@ -613,10 +606,10 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(string.IsNullOrWhiteSpace(hostname))
return "Please provide the hostname of the data source. Use 'localhost' if the data source is on the same machine as the ERI server.";
return T("Please provide the hostname of the data source. Use 'localhost' if the data source is on the same machine as the ERI server.");
if(hostname.Length > 255)
return "The hostname of the data source must not exceed 255 characters.";
return T("The hostname of the data source must not exceed 255 characters.");
return null;
}
@@ -631,10 +624,10 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(port is null)
return "Please provide the port of the data source.";
return T("Please provide the port of the data source.");
if(port is < 1 or > 65535)
return "The port of the data source must be between 1 and 65535.";
return T("The port of the data source must be between 1 and 65535.");
return null;
}
@@ -679,7 +672,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{
var authenticationMethods = (this.selectedAuthenticationMethods as HashSet<Auth>)!;
if(authenticationMethods.Count == 0)
return "Please select at least one authentication method for the ERI server.";
return T("Please select at least one authentication method for the ERI server.");
return null;
}
@@ -709,7 +702,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(os is OperatingSystem.NONE)
return "Please select the operating system on which the ERI server will run. This is necessary when using SSO with Kerberos.";
return T("Please select the operating system on which the ERI server will run. This is necessary when using SSO with Kerberos.");
return null;
}
@@ -717,16 +710,12 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private string? ValidateAllowedLLMProviders(AllowedLLMProviders provider)
{
if(provider == AllowedLLMProviders.NONE)
return "Please select which types of LLMs users are allowed to use with the data from this ERI server.";
return T("Please select which types of LLMs users are allowed to use with the data from this ERI server.");
return null;
}
private string AuthDescriptionTitle()
{
const string TITLE = "Describe how you planned the authentication process";
return this.IsAuthDescriptionOptional() ? $"(Optional) {TITLE}" : TITLE;
}
private string AuthDescriptionTitle() => this.IsAuthDescriptionOptional() ? T("(Optional) Describe how you planned the authentication process") : T("Describe how you planned the authentication process");
private bool IsAuthDescriptionOptional()
{
@@ -746,10 +735,10 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{
var authenticationMethods = (this.selectedAuthenticationMethods as HashSet<Auth>)!;
if(authenticationMethods.Any(n => n == Auth.NONE) && authenticationMethods.Count > 1 && string.IsNullOrWhiteSpace(this.authDescription))
return "Please describe how the selected authentication methods should be used. Especially, explain for what data the NONE method (public access) is used.";
return T("Please describe how the selected authentication methods should be used. Especially, explain for what data the NONE method (public access) is used.");
if(authenticationMethods.Count > 1 && string.IsNullOrWhiteSpace(this.authDescription))
return "Please describe how the selected authentication methods should be used.";
return T("Please describe how the selected authentication methods should be used.");
return null;
}
@@ -760,7 +749,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
return null;
if(string.IsNullOrWhiteSpace(path))
return "Please provide a base directory for the ERI server to write files to.";
return T("Please provide a base directory for the ERI server to write files to.");
return null;
}
@@ -768,12 +757,12 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private string GetMultiSelectionAuthText(List<Auth> selectedValues)
{
if(selectedValues.Count == 0)
return "Please select at least one authentication method";
return T("Please select at least one authentication method");
if(selectedValues.Count == 1)
return $"You have selected 1 authentication method";
return T("You have selected 1 authentication method");
return $"You have selected {selectedValues.Count} authentication methods";
return string.Format(T("You have selected {0} authentication methods"), selectedValues.Count);
}
private bool NeedHostnamePort()
@@ -797,7 +786,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{ x => x.UsedEmbeddingMethodNames, this.embeddings.Select(n => n.EmbeddingName).ToList() },
};
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>("Add Embedding Method", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>(T("Add Embedding Method"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -821,7 +810,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{ x => x.IsEditing, true },
};
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>("Edit Embedding Method", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>(T("Edit Embedding Method"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -835,15 +824,15 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private async Task DeleteEmbedding(EmbeddingInfo embeddingInfo)
{
var message = this.retrievalProcesses.Any(n => n.Embeddings?.Contains(embeddingInfo) is true)
? $"The embedding '{embeddingInfo.EmbeddingName}' is used in one or more retrieval processes. Are you sure you want to delete it?"
: $"Are you sure you want to delete the embedding '{embeddingInfo.EmbeddingName}'?";
? string.Format(T("The embedding '{0}' is used in one or more retrieval processes. Are you sure you want to delete it?"), embeddingInfo.EmbeddingName)
: string.Format(T("Are you sure you want to delete the embedding '{0}'?"), embeddingInfo.EmbeddingName);
var dialogParameters = new DialogParameters
var dialogParameters = new DialogParameters<ConfirmDialog>
{
{ "Message", message },
{ x => x.Message, message },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Embedding", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete Embedding"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -863,7 +852,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{ x => x.UsedRetrievalProcessNames, this.retrievalProcesses.Select(n => n.Name).ToList() },
};
var dialogReference = await this.DialogService.ShowAsync<RetrievalProcessDialog>("Add Retrieval Process", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<RetrievalProcessDialog>(T("Add Retrieval Process"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -888,7 +877,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
{ x => x.UsedRetrievalProcessNames, this.retrievalProcesses.Where(n => n != retrievalInfo).Select(n => n.Name).ToList() },
};
var dialogReference = await this.DialogService.ShowAsync<RetrievalProcessDialog>("Edit Retrieval Process", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<RetrievalProcessDialog>(T("Edit Retrieval Process"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -901,12 +890,12 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
private async Task DeleteRetrievalProcess(RetrievalInfo retrievalInfo)
{
var dialogParameters = new DialogParameters
var dialogParameters = new DialogParameters<ConfirmDialog>
{
{ "Message", $"Are you sure you want to delete the retrieval process '{retrievalInfo.Name}'?" },
{ x => x.Message, string.Format(T("Are you sure you want to delete the retrieval process '{0}'?"), retrievalInfo.Name) },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Retrieval Process", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete Retrieval Process"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
@@ -957,14 +946,14 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
if(this.retrievalProcesses.Count == 0)
{
this.AddInputIssue("Please describe at least one retrieval process.");
this.AddInputIssue(T("Please describe at least one retrieval process."));
return;
}
this.eriSpecification = await this.selectedERIVersion.ReadSpecification(this.HttpClient);
if (string.IsNullOrWhiteSpace(this.eriSpecification))
{
this.AddInputIssue("The ERI specification could not be loaded. Please try again later.");
this.AddInputIssue(T("The ERI specification could not be loaded. Please try again later."));
return;
}
@@ -2,15 +2,17 @@ namespace AIStudio.Assistants.ERI;
public static class AuthExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(AuthExtensions).Namespace, nameof(AuthExtensions));
public static string Name(this Auth auth) => auth switch
{
Auth.NONE => "No login necessary: useful for public data sources",
Auth.NONE => TB("No login necessary: useful for public data sources"),
Auth.KERBEROS => "Login by single-sign-on (SSO) using Kerberos: very complex to implement and to operate, useful for many users",
Auth.USERNAME_PASSWORD => "Login by username and password: simple to implement and to operate, useful for few users; easy to use for users",
Auth.TOKEN => "Login by token: simple to implement and to operate, useful for few users; unusual for many users",
Auth.KERBEROS => TB("Login by single-sign-on (SSO) using Kerberos: very complex to implement and to operate, useful for many users"),
Auth.USERNAME_PASSWORD => TB("Login by username and password: simple to implement and to operate, useful for few users; easy to use for users"),
Auth.TOKEN => TB("Login by token: simple to implement and to operate, useful for few users; unusual for many users"),
_ => "Unknown login method"
_ => TB("Unknown login method")
};
public static string ToPrompt(this Auth auth) => auth switch
@@ -2,18 +2,20 @@ namespace AIStudio.Assistants.ERI;
public static class DataSourcesExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(DataSourcesExtensions).Namespace, nameof(DataSourcesExtensions));
public static string Name(this DataSources dataSource) => dataSource switch
{
DataSources.NONE => "No data source selected",
DataSources.CUSTOM => "Custom description",
DataSources.NONE => TB("No data source selected"),
DataSources.CUSTOM => TB("Custom description"),
DataSources.FILE_SYSTEM => "File system (local or network share)",
DataSources.OBJECT_STORAGE => "Object storage, like Amazon S3, MinIO, etc.",
DataSources.KEY_VALUE_STORE => "Key-Value store, like Redis, etc.",
DataSources.DOCUMENT_STORE => "Document store, like MongoDB, etc.",
DataSources.RELATIONAL_DATABASE => "Relational database, like MySQL, PostgreSQL, etc.",
DataSources.GRAPH_DATABASE => "Graph database, like Neo4j, ArangoDB, etc.",
DataSources.FILE_SYSTEM => TB("File system (local or network share)"),
DataSources.OBJECT_STORAGE => TB("Object storage, like Amazon S3, MinIO, etc."),
DataSources.KEY_VALUE_STORE => TB("Key-Value store, like Redis, etc."),
DataSources.DOCUMENT_STORE => TB("Document store, like MongoDB, etc."),
DataSources.RELATIONAL_DATABASE => TB("Relational database, like MySQL, PostgreSQL, etc."),
DataSources.GRAPH_DATABASE => TB("Graph database, like Neo4j, ArangoDB, etc."),
_ => "Unknown data source"
_ => TB("Unknown data source")
};
}
@@ -2,7 +2,19 @@ namespace AIStudio.Assistants.ERI;
public static class OperatingSystemExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(OperatingSystemExtensions).Namespace, nameof(OperatingSystemExtensions));
public static string Name(this OperatingSystem os) => os switch
{
OperatingSystem.NONE => TB("No operating system specified"),
OperatingSystem.WINDOWS => TB("Windows"),
OperatingSystem.LINUX => TB("Linux"),
_ => TB("Unknown operating system")
};
public static string ToPrompt(this OperatingSystem os) => os switch
{
OperatingSystem.NONE => "No operating system specified",
@@ -2,7 +2,29 @@ namespace AIStudio.Assistants.ERI;
public static class ProgrammingLanguagesExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(ProgrammingLanguagesExtensions).Namespace, nameof(ProgrammingLanguagesExtensions));
public static string Name(this ProgrammingLanguages language) => language switch
{
ProgrammingLanguages.NONE => TB("No programming language selected"),
ProgrammingLanguages.C => "C",
ProgrammingLanguages.CPP => "C++",
ProgrammingLanguages.CSHARP => "C#",
ProgrammingLanguages.GO => "Go",
ProgrammingLanguages.JAVA => "Java",
ProgrammingLanguages.JAVASCRIPT => "JavaScript",
ProgrammingLanguages.JULIA => "Julia",
ProgrammingLanguages.MATLAB => "MATLAB",
ProgrammingLanguages.PHP => "PHP",
ProgrammingLanguages.PYTHON => "Python",
ProgrammingLanguages.RUST => "Rust",
ProgrammingLanguages.OTHER => TB("Other"),
_ => TB("Unknown")
};
public static string ToPrompt(this ProgrammingLanguages language) => language switch
{
ProgrammingLanguages.NONE => "No programming language selected",
@@ -2,35 +2,35 @@
@using AIStudio.Settings
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogI18N>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" SelectionUpdated="_ => this.OnChangedLanguage()" />
<ConfigurationSelect OptionDescription="Language plugin used for comparision" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="Select the language plugin used for comparision."/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" SelectionUpdated="_ => this.OnChangedLanguage()" />
<ConfigurationSelect OptionDescription="@T("Language plugin used for comparision")" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="@T("Select the language plugin used for comparision.")"/>
@if (this.isLoading)
{
<MudText Typo="Typo.body1" Class="mb-6">
The data is being loaded, please wait...
@T("The data is being loaded, please wait...")
</MudText>
} else if (!this.isLoading && !string.IsNullOrWhiteSpace(this.loadingIssue))
{
<MudText Typo="Typo.body1" Class="mb-6">
While loading the I18N data, an issue occurred: @this.loadingIssue
@T("While loading the I18N data, an issue occurred:") @this.loadingIssue
</MudText>
}
else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
{
<MudText Typo="Typo.h6">
Added Content (@this.addedContent.Count entries)
@this.AddedContentText
</MudText>
<MudTable Items="@this.addedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
<ToolBarContent>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
</ToolBarContent>
<ColGroup>
<col/>
<col/>
</ColGroup>
<HeaderContent>
<MudTh>Key</MudTh>
<MudTh>Text</MudTh>
<MudTh>@T("Key")</MudTh>
<MudTh>@T("Text")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>
@@ -48,19 +48,19 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
</MudTable>
<MudText Typo="Typo.h6">
Removed Content (@this.removedContent.Count entries)
@this.RemovedContentText
</MudText>
<MudTable Items="@this.removedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
<ToolBarContent>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
</ToolBarContent>
<ColGroup>
<col/>
<col/>
</ColGroup>
<HeaderContent>
<MudTh>Key</MudTh>
<MudTh>Text</MudTh>
<MudTh>@T("Key")</MudTh>
<MudTh>@T("Text")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>
@@ -80,7 +80,7 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
@if (this.selectedTargetLanguage is CommonLanguages.EN_US)
{
<MudJustifiedText Typo="Typo.body1" Class="mb-6">
Please note: neither is a translation needed nor performed for English (USA). Anyway, you might want to generate the related Lua code.
@T("Please note: neither is a translation needed nor performed for English (USA). Anyway, you might want to generate the related Lua code.")
</MudJustifiedText>
}
else
@@ -92,19 +92,19 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
{
<hr style="width: 100%; border-width: 0.25ch;" class="mt-6 mb-6"/>
<MudText Typo="Typo.h6">
Localized Content (@this.localizedContent.Count entries of @this.NumTotalItems)
@this.LocalizedContentText
</MudText>
<MudTable Items="@this.localizedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
<ToolBarContent>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
</ToolBarContent>
<ColGroup>
<col/>
<col/>
</ColGroup>
<HeaderContent>
<MudTh>Key</MudTh>
<MudTh>Text</MudTh>
<MudTh>@T("Key")</MudTh>
<MudTh>@T("Text")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>
@@ -18,12 +18,9 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
{
public override Tools.Components Component => Tools.Components.I18N_ASSISTANT;
protected override string Title => "Localization";
protected override string Title => T("Localization");
protected override string Description =>
"""
Translate MindWork AI Studio text content into another language.
""";
protected override string Description => T("Translate MindWork AI Studio text content into another language.");
protected override string SystemPrompt =>
$"""
@@ -59,7 +56,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
[
new ButtonData
{
Text = "Copy Lua code to clipboard",
Text = T("Copy Lua code to clipboard"),
Icon = Icons.Material.Filled.Extension,
Color = Color.Default,
AsyncAction = async () => await this.RustService.CopyText2Clipboard(this.Snackbar, this.finalLuaCode.ToString()),
@@ -67,7 +64,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
},
];
protected override string SubmitText => "Localize AI Studio & generate the Lua code";
protected override string SubmitText => T("Localize AI Studio & generate the Lua code");
protected override Func<Task> SubmitAction => this.LocalizeTextContent;
@@ -143,12 +140,12 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
this.localizationPossible = false;
if (PluginFactory.RunningPlugins.FirstOrDefault(n => n is PluginLanguage && n.Id == this.selectedLanguagePluginId) is not PluginLanguage comparisonPlugin)
{
this.loadingIssue = $"Was not able to load the language plugin for comparison ({this.selectedLanguagePluginId}). Please select a valid, loaded & running language plugin.";
this.loadingIssue = string.Format(T("Was not able to load the language plugin for comparison ({0}). Please select a valid, loaded & running language plugin."), this.selectedLanguagePluginId);
this.selectedLanguagePlugin = null;
}
else if (comparisonPlugin.IETFTag != this.selectedTargetLanguage.ToIETFTag())
{
this.loadingIssue = $"The selected language plugin for comparison uses the IETF tag '{comparisonPlugin.IETFTag}' which does not match the selected target language '{this.selectedTargetLanguage.ToIETFTag()}'. Please select a valid, loaded & running language plugin which matches the target language.";
this.loadingIssue = string.Format(T("The selected language plugin for comparison uses the IETF tag '{0}' which does not match the selected target language '{1}'. Please select a valid, loaded & running language plugin which matches the target language."), comparisonPlugin.IETFTag, this.selectedTargetLanguage.ToIETFTag());
this.selectedLanguagePlugin = null;
}
else
@@ -165,7 +162,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
{
if (this.selectedLanguagePlugin is null)
{
this.loadingIssue = "Please select a language plugin for comparison.";
this.loadingIssue = T("Please select a language plugin for comparison.");
this.localizationPossible = false;
this.isLoading = false;
this.StateHasChanged();
@@ -182,7 +179,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
var filePath = Path.Join(Environment.CurrentDirectory, "Assistants", "I18N");
var resourceFileProvider = new PhysicalFileProvider(filePath);
#else
var resourceFileProvider = new ManifestEmbeddedFileProvider(Assembly.GetAssembly(type: typeof(Program))!, "Assistants.I18N");
var resourceFileProvider = new ManifestEmbeddedFileProvider(Assembly.GetAssembly(type: typeof(Program))!, "Assistants/I18N");
#endif
var file = resourceFileProvider.GetFileInfo("allTexts.lua");
@@ -202,7 +199,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
break;
case NoPlugin:
this.loadingIssue = "Was not able to load the I18N plugin. Please check the plugin code.";
this.loadingIssue = T("Was not able to load the I18N plugin. Please check the plugin code.");
break;
case { IsValid: false } plugin when plugin.Issues.Any():
@@ -241,7 +238,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
private string? ValidatingTargetLanguage(CommonLanguages language)
{
if(language == CommonLanguages.AS_IS)
return "Please select a target language.";
return T("Please select a target language.");
return null;
}
@@ -249,13 +246,19 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return T("Please provide a custom language.");
return null;
}
private int NumTotalItems => (this.selectedLanguagePlugin?.Content.Count ?? 0) + this.addedContent.Count - this.removedContent.Count;
private string AddedContentText => string.Format(T("Added Content ({0} entries)"), this.addedContent.Count);
private string RemovedContentText => string.Format(T("Removed Content ({0} entries)"), this.removedContent.Count);
private string LocalizedContentText => string.Format(T("Localized Content ({0} entries of {1})"), this.localizedContent.Count, this.NumTotalItems);
private async Task LocalizeTextContent()
{
await this.form!.Validate();
File diff suppressed because it is too large. Load diff
@@ -1,15 +1,15 @@
@attribute [Route(Routes.ASSISTANT_JOB_POSTING)]
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogJobPostings>
<MudTextField T="string" @bind-Text="@this.inputCompanyName" Label="(Optional) The company name" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Warehouse" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputCountryLegalFramework" Label="Provide the country, where the company is located" Validation="@this.ValidateCountryLegalFramework" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Flag" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" HelperText="This is important to consider the legal framework of the country."/>
<MudTextField T="string" @bind-Text="@this.inputMandatoryInformation" Label="(Optional) Provide mandatory information" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.TextSnippet" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Mandatory information that your company requires for all job postings. This can include the company description, etc." />
<MudTextField T="string" @bind-Text="@this.inputJobDescription" Label="Job description" Validation="@this.ValidateJobDescription" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe what the person is supposed to do in the company. This might be just short bullet points." />
<MudTextField T="string" @bind-Text="@this.inputQualifications" Label="(Optional) Provide necessary job qualifications" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe what the person should bring to the table. This might be just short bullet points." />
<MudTextField T="string" @bind-Text="@this.inputResponsibilities" Label="(Optional) Provide job responsibilities" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe the responsibilities the person should take on in the company." />
<MudTextField T="string" @bind-Text="@this.inputWorkLocation" Label="(Optional) Provide the work location" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.MyLocation" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputEntryDate" Label="(Optional) Provide the entry date" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputValidUntil" Label="(Optional) Provide the date until the job posting is valid" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputCompanyName" Label="@T("(Optional) The company name")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Warehouse" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputCountryLegalFramework" Label="@T("Provide the country, where the company is located")" Validation="@this.ValidateCountryLegalFramework" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Flag" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" HelperText="@T("This is important to consider the legal framework of the country.")"/>
<MudTextField T="string" @bind-Text="@this.inputMandatoryInformation" Label="@T("(Optional) Provide mandatory information")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.TextSnippet" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Mandatory information that your company requires for all job postings. This can include the company description, etc.")" />
<MudTextField T="string" @bind-Text="@this.inputJobDescription" Label="@T("Job description")" Validation="@this.ValidateJobDescription" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Describe what the person is supposed to do in the company. This might be just short bullet points.")" />
<MudTextField T="string" @bind-Text="@this.inputQualifications" Label="@T("(Optional) Provide necessary job qualifications")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Describe what the person should bring to the table. This might be just short bullet points.")" />
<MudTextField T="string" @bind-Text="@this.inputResponsibilities" Label="@T("(Optional) Provide job responsibilities")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Settings" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Describe the responsibilities the person should take on in the company.")" />
<MudTextField T="string" @bind-Text="@this.inputWorkLocation" Label="@T("(Optional) Provide the work location")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.MyLocation" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputEntryDate" Label="@T("(Optional) Provide the entry date")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputValidUntil" Label="@T("(Optional) Provide the date until the job posting is valid")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -7,13 +7,9 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
{
public override Tools.Components Component => Tools.Components.JOB_POSTING_ASSISTANT;
protected override string Title => "Job Posting";
protected override string Title => T("Job Posting");
protected override string Description =>
"""
Provide some key points about the job you want to post. The AI will then
formulate a suggestion that you can finalize.
""";
protected override string Description => T("Provide some key points about the job you want to post. The AI will then formulate a suggestion that you can finalize.");
protected override string SystemPrompt =>
$"""
@@ -47,7 +43,7 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Create the job posting";
protected override string SubmitText => T("Create the job posting");
protected override Func<Task> SubmitAction => this.CreateJobPosting;
@@ -126,7 +122,7 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom target language.";
return T("Please provide a custom target language.");
return null;
}
@@ -134,7 +130,7 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
private string? ValidateJobDescription(string jobDescription)
{
if(string.IsNullOrWhiteSpace(jobDescription))
return "Please provide a job description.";
return T("Please provide a job description.");
return null;
}
@@ -142,7 +138,7 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
private string? ValidateCountryLegalFramework(string countryLegalFramework)
{
if(string.IsNullOrWhiteSpace(countryLegalFramework))
return "Please provide the country where the job is posted (legal framework).";
return T("Please provide the country where the job is posted (legal framework).");
return null;
}
@@ -3,9 +3,10 @@
@if (!this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)
{
<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)"/>
<ReadWebContent @bind-Content="@this.inputLegalDocument" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" @bind-Preselect="@this.showWebContentReader" @bind-PreselectContentCleanerAgent="@this.useContentCleanerAgent"/>
}
<ReadFileContent @bind-FileContent="@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"/>
@@ -37,11 +37,27 @@ public partial class AssistantLegalCheck : AssistantBaseCore<SettingsDialogLegal
{
this.inputLegalDocument = string.Empty;
this.inputQuestions = string.Empty;
this.MightPreselectValues();
if (!this.MightPreselectValues())
{
this.showWebContentReader = false;
this.useContentCleanerAgent = false;
}
}
protected override bool MightPreselectValues() => false;
protected override bool MightPreselectValues()
{
if (this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)
{
this.showWebContentReader = this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader;
this.useContentCleanerAgent = this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent;
return true;
}
return false;
}
private bool showWebContentReader;
private bool useContentCleanerAgent;
private bool isAgentRunning;
private string inputLegalDocument = string.Empty;
private string inputQuestions = string.Empty;
@@ -85,7 +85,7 @@ public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
private string? ValidateProfile(Profile profile)
{
if(profile == default || profile == Profile.NO_PROFILE)
if(profile == Profile.NO_PROFILE)
return T("Please select one of your profiles.");
return null;
@@ -2,12 +2,14 @@ namespace AIStudio.Assistants.RewriteImprove;
public static class SentenceStructureExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(SentenceStructureExtensions).Namespace, nameof(SentenceStructureExtensions));
public static string Name(this SentenceStructure sentenceStructure) => sentenceStructure switch
{
SentenceStructure.ACTIVE => "Active voice",
SentenceStructure.PASSIVE => "Passive voice",
SentenceStructure.ACTIVE => TB("Active voice"),
SentenceStructure.PASSIVE => TB("Passive voice"),
_ => "Not Specified",
_ => TB("Not Specified"),
};
public static string Prompt(this SentenceStructure sentenceStructure) => sentenceStructure switch
@@ -13,4 +13,5 @@ public enum WritingStyles
MARKETING,
ACADEMIC,
LEGAL,
CHANGELOG,
}
@@ -2,19 +2,22 @@ namespace AIStudio.Assistants.RewriteImprove;
public static class WritingStylesExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(WritingStylesExtensions).Namespace, nameof(WritingStylesExtensions));
public static string Name(this WritingStyles style) => style switch
{
WritingStyles.EVERYDAY => "Everyday (personal texts, social media)",
WritingStyles.BUSINESS => "Business (business emails, reports, presentations)",
WritingStyles.SCIENTIFIC => "Scientific (scientific papers, research reports)",
WritingStyles.JOURNALISTIC => "Journalistic (magazines, newspapers, news)",
WritingStyles.LITERARY => "Literary (fiction, poetry)",
WritingStyles.TECHNICAL => "Technical (manuals, documentation)",
WritingStyles.MARKETING => "Marketing (advertisements, sales texts)",
WritingStyles.ACADEMIC => "Academic (essays, seminar papers)",
WritingStyles.LEGAL => "Legal (legal texts, contracts)",
WritingStyles.EVERYDAY => TB("Everyday (personal texts, social media)"),
WritingStyles.BUSINESS => TB("Business (business emails, reports, presentations)"),
WritingStyles.SCIENTIFIC => TB("Scientific (scientific papers, research reports)"),
WritingStyles.JOURNALISTIC => TB("Journalistic (magazines, newspapers, news)"),
WritingStyles.LITERARY => TB("Literary (fiction, poetry)"),
WritingStyles.TECHNICAL => TB("Technical (manuals, documentation)"),
WritingStyles.MARKETING => TB("Marketing (advertisements, sales texts)"),
WritingStyles.ACADEMIC => TB("Academic (essays, seminar papers)"),
WritingStyles.LEGAL => TB("Legal (legal texts, contracts)"),
WritingStyles.CHANGELOG => TB("Changelog (release notes, version history)"),
_ => "Not specified",
_ => TB("Not specified"),
};
public static string Prompt(this WritingStyles style) => style switch
@@ -28,6 +31,7 @@ public static class WritingStylesExtensions
WritingStyles.MARKETING => "Use a marketing style like for advertisements, sales texts, and promotional content. Most important is persuasiveness and engagement.",
WritingStyles.ACADEMIC => "Use a academic style like for essays, seminar papers, and academic writing. Most important is clarity and objectivity.",
WritingStyles.LEGAL => "Use a legal style like for legal texts, contracts, and official documents. Most important is precision and legal correctness. Use formal legal language.",
WritingStyles.CHANGELOG => "Use a changelog style like for release notes, version history, and software updates. Most important is clarity and conciseness. The changelog is structured as a Markdown list. Most list items start with one of the following verbs: Added, Changed, Deprecated, Removed, Fixed, Refactored, Improved, or Upgraded -- these verbs should also translated to the target language. Also, changelogs use past tense.",
_ => "Keep the style of the text as it is.",
};
@@ -3,10 +3,12 @@
@if (!this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)
{
<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)"/>
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" @bind-Preselect="@this.showWebContentReader" @bind-PreselectContentCleanerAgent="@this.useContentCleanerAgent"/>
}
<ReadFileContent @bind-FileContent="@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" />
<MudTextField T="string" AutoGrow="true" Lines="2" @bind-Text="@this.importantAspects" class="mb-3" Label="@T("(Optional) Important Aspects")" HelperText="@T("(Optional) Specify aspects for the LLM to focus on when generating a summary, such as summary length or specific topics to emphasize.")" ShrinkLabel="true" Variant="Variant.Outlined" AdornmentIcon="@Icons.Material.Filled.List" Adornment="Adornment.Start"/>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -12,13 +12,13 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
protected override string Description => T("Summarize long text into a shorter version while retaining the main points. You might want to change the language of the summary to make it more readable. It is also possible to change the complexity of the summary to make it easy to understand.");
protected override string SystemPrompt =>
"""
You get a long text as input. The user wants to get a summary of the text.
The user might want to change the language of the summary. In this case,
you should provide a summary in the requested language. Eventually, the user
want to change the complexity of the text. In this case, you should provide
a summary with the requested complexity. In any case, do not add any information.
""";
$"""
You get a long text as input. The text is marked with ```. The user wants to get a summary of the text.
{this.selectedTargetLanguage.PromptSummarizing(this.customTargetLanguage)}
{this.selectedComplexity.Prompt(this.expertInField)}
{this.PromptImportantAspects()}
In any case, only use information that is provided in the text for the summary.
""";
protected override bool AllowProfiles => false;
@@ -40,10 +40,13 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
this.inputText = string.Empty;
if(!this.MightPreselectValues())
{
this.showWebContentReader = false;
this.useContentCleanerAgent = false;
this.selectedTargetLanguage = CommonLanguages.AS_IS;
this.customTargetLanguage = string.Empty;
this.selectedComplexity = Complexity.NO_CHANGE;
this.expertInField = string.Empty;
this.importantAspects = string.Empty;
}
}
@@ -51,22 +54,28 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
{
if (this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)
{
this.showWebContentReader = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader;
this.useContentCleanerAgent = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent;
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage;
this.customTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage;
this.selectedComplexity = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity;
this.expertInField = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField;
this.importantAspects = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedImportantAspects;
return true;
}
return false;
}
private bool showWebContentReader;
private bool useContentCleanerAgent;
private string inputText = string.Empty;
private bool isAgentRunning;
private CommonLanguages selectedTargetLanguage;
private string customTargetLanguage = string.Empty;
private Complexity selectedComplexity;
private string expertInField = string.Empty;
private string importantAspects = string.Empty;
#region Overrides of ComponentBase
@@ -105,6 +114,17 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
return null;
}
private string PromptImportantAspects()
{
if (string.IsNullOrWhiteSpace(this.importantAspects))
return string.Empty;
return $"""
Emphasize the following aspects in your summary:
{this.importantAspects}
""";
}
private async Task SummarizeText()
{
await this.form!.Validate();
@@ -114,11 +134,7 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
this.CreateChatThread();
var time = this.AddUserRequest(
$"""
{this.selectedTargetLanguage.PromptSummarizing(this.customTargetLanguage)}
{this.selectedComplexity.Prompt(this.expertInField)}
Please summarize the following text:
```
{this.inputText}
```
@@ -2,18 +2,20 @@ namespace AIStudio.Assistants.TextSummarizer;
public static class ComplexityExtensions
{
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(ComplexityExtensions).Namespace, nameof(ComplexityExtensions));
public static string Name(this Complexity complexity) => complexity switch
{
Complexity.NO_CHANGE => "No change in complexity",
Complexity.NO_CHANGE => TB("No change in complexity"),
Complexity.SIMPLE_LANGUAGE => "Simple language, e.g., for children",
Complexity.TEEN_LANGUAGE => "Teen language, e.g., for teenagers",
Complexity.EVERYDAY_LANGUAGE => "Everyday language, e.g., for adults",
Complexity.POPULAR_SCIENCE_LANGUAGE => "Popular science language, e.g., for people interested in science",
Complexity.SCIENTIFIC_LANGUAGE_FIELD_EXPERTS => "Scientific language for experts in this field",
Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS => "Scientific language for experts from other fields (interdisciplinary)",
Complexity.SIMPLE_LANGUAGE => TB("Simple language, e.g., for children"),
Complexity.TEEN_LANGUAGE => TB("Teen language, e.g., for teenagers"),
Complexity.EVERYDAY_LANGUAGE => TB("Everyday language, e.g., for adults"),
Complexity.POPULAR_SCIENCE_LANGUAGE => TB("Popular science language, e.g., for people interested in science"),
Complexity.SCIENTIFIC_LANGUAGE_FIELD_EXPERTS => TB("Scientific language for experts in this field"),
Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS => TB("Scientific language for experts from other fields (interdisciplinary)"),
_ => "No change in complexity",
_ => TB("No change in complexity"),
};
public static string Prompt(this Complexity complexity, string expertInField) => complexity switch
@@ -3,13 +3,15 @@
@if (!this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)
{
<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)"/>
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" @bind-Preselect="@this.showWebContentReader" @bind-PreselectContentCleanerAgent="@this.useContentCleanerAgent"/>
}
<ReadFileContent @bind-FileContent="@this.inputText"/>
<MudTextSwitch Label="@T("Live translation")" @bind-Value="@this.liveTranslation" LabelOn="@T("Live translation")" LabelOff="@T("No live translation")"/>
@if (this.liveTranslation)
{
<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" Immediate="@true" DebounceInterval="@this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds" OnDebounceIntervalElapsed="() => this.TranslateText(force: false)" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<DebouncedTextField Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" ValidationFunc="@this.ValidatingText" Icon="@Icons.Material.Filled.DocumentScanner" Label="@T("Your input")" Lines="6" MaxLines="12" DebounceTime="@TimeSpan.FromMilliseconds(this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds)" WhenTextChangedAsync="async _ => await this.TranslateText(force: false)" Attributes="@USER_INPUT_ATTRIBUTES"/>
}
else
{
@@ -40,6 +40,8 @@ public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTran
this.inputTextLastTranslation = string.Empty;
if (!this.MightPreselectValues())
{
this.showWebContentReader = false;
this.useContentCleanerAgent = false;
this.liveTranslation = false;
this.selectedTargetLanguage = CommonLanguages.AS_IS;
this.customTargetLanguage = string.Empty;
@@ -50,6 +52,8 @@ public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTran
{
if (this.SettingsManager.ConfigurationData.Translation.PreselectOptions)
{
this.showWebContentReader = this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader;
this.useContentCleanerAgent = this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent;
this.liveTranslation = this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation;
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage;
this.customTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage;
@@ -59,6 +63,8 @@ public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTran
return false;
}
private bool showWebContentReader;
private bool useContentCleanerAgent;
private bool liveTranslation;
private bool isAgentRunning;
private string inputText = string.Empty;
-48
View File
@@ -12,52 +12,4 @@ public enum ChatRole
USER,
AI,
AGENT,
}
/// <summary>
/// Extensions for the ChatRole enum.
/// </summary>
public static class ExtensionsChatRole
{
/// <summary>
/// Returns the name of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The name of the role.</returns>
public static string ToName(this ChatRole role) => role switch
{
ChatRole.SYSTEM => "System",
ChatRole.USER => "You",
ChatRole.AI => "AI",
_ => "Unknown",
};
/// <summary>
/// Returns the color of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The color of the role.</returns>
public static Color ToColor(this ChatRole role) => role switch
{
ChatRole.SYSTEM => Color.Info,
ChatRole.USER => Color.Primary,
ChatRole.AI => Color.Tertiary,
_ => Color.Error,
};
/// <summary>
/// Returns the icon of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The icon of the role.</returns>
public static string ToIcon(this ChatRole role) => role switch
{
ChatRole.SYSTEM => Icons.Material.Filled.Settings,
ChatRole.USER => Icons.Material.Filled.Person,
ChatRole.AI => Icons.Material.Filled.AutoAwesome,
_ => Icons.Material.Filled.Help,
};
}
@@ -0,0 +1,75 @@
using AIStudio.Tools.PluginSystem;
namespace AIStudio.Chat;
public static class ChatRoleExtensions
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ChatRoleExtensions).Namespace, nameof(ChatRoleExtensions));
/// <summary>
/// Returns the name of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The name of the role.</returns>
public static string ToName(this ChatRole role) => role switch
{
ChatRole.SYSTEM => TB("System"),
ChatRole.USER => TB("You"),
ChatRole.AI => TB("AI"),
_ => TB("Unknown"),
};
/// <summary>
/// Returns the color of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The color of the role.</returns>
public static Color ToColor(this ChatRole role) => role switch
{
ChatRole.SYSTEM => Color.Info,
ChatRole.USER => Color.Primary,
ChatRole.AI => Color.Tertiary,
_ => Color.Error,
};
/// <summary>
/// Returns the icon of the role.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The icon of the role.</returns>
public static string ToIcon(this ChatRole role) => role switch
{
ChatRole.SYSTEM => Icons.Material.Filled.Settings,
ChatRole.USER => Icons.Material.Filled.Person,
ChatRole.AI => Icons.Material.Filled.AutoAwesome,
_ => Icons.Material.Filled.Help,
};
/// <summary>
/// Returns the specific name of the role for the chat template.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The name of the role.</returns>
public static string ToChatTemplateName(this ChatRole role) => role switch
{
ChatRole.SYSTEM => TB("System"),
ChatRole.USER => TB("User"),
ChatRole.AI => TB("Assistant"),
_ => TB("Unknown"),
};
/// <summary>
/// Selects the next role for a chat template.
/// </summary>
/// <param name="currentRole">The current role.</param>
/// <returns>The next role for the chat template.</returns>
public static ChatRole SelectNextRoleForTemplate(this ChatRole currentRole) => currentRole switch
{
ChatRole.USER => ChatRole.AI,
_ => ChatRole.USER,
};
}
+10
View File
@@ -0,0 +1,10 @@
namespace AIStudio.Chat;
public static class ChatRoles
{
public static IEnumerable<ChatRole> ChatTemplateRoles()
{
yield return ChatRole.USER;
yield return ChatRole.AI;
}
}
+59 -15
View File
@@ -10,6 +10,8 @@ namespace AIStudio.Chat;
/// </summary>
public sealed record ChatThread
{
private static readonly ILogger<ChatThread> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ChatThread>();
/// <summary>
/// The unique identifier of the chat thread.
/// </summary>
@@ -29,6 +31,11 @@ public sealed record ChatThread
/// Specifies the profile selected for the chat thread.
/// </summary>
public string SelectedProfile { get; set; } = string.Empty;
/// <summary>
/// Specifies the profile selected for the chat thread.
/// </summary>
public string SelectedChatTemplate { get; set; } = string.Empty;
/// <summary>
/// The data source options for this chat thread.
@@ -54,11 +61,6 @@ public sealed record ChatThread
/// The name of the chat thread. Usually generated by an AI model or manually edited by the user.
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// The seed for the chat thread. Some providers use this to generate deterministic results.
/// </summary>
public int Seed { get; init; }
/// <summary>
/// The current system prompt for the chat thread.
@@ -69,6 +71,8 @@ public sealed record ChatThread
/// The content blocks of the chat thread.
/// </summary>
public List<ContentBlock> Blocks { get; init; } = [];
private bool allowProfile = true;
/// <summary>
/// Prepares the system prompt for the chat thread.
@@ -80,33 +84,73 @@ public sealed record ChatThread
/// </remarks>
/// <param name="settingsManager">The settings manager instance to use.</param>
/// <param name="chatThread">The chat thread to prepare the system prompt for.</param>
/// <param name="logger">The logger instance to use.</param>
/// <returns>The prepared system prompt.</returns>
public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread chatThread, ILogger logger)
public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread chatThread)
{
//
// Use the information from the chat template, if provided. Otherwise, use the default system prompt
//
string systemPromptTextWithChatTemplate;
var logMessage = $"Using no chat template for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedChatTemplate))
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
if(!Guid.TryParse(chatThread.SelectedChatTemplate, out var chatTemplateId))
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
if(chatThread.SelectedChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE.Id || chatTemplateId == Guid.Empty)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
var chatTemplate = settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatThread.SelectedChatTemplate);
if(chatTemplate == null)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
logMessage = $"Using chat template '{chatTemplate.Name}' for chat thread '{chatThread.Name}'.";
this.allowProfile = chatTemplate.AllowProfileUsage;
systemPromptTextWithChatTemplate = chatTemplate.ToSystemPrompt();
}
}
}
}
// We need a way to save the changed system prompt in our chat thread.
// Otherwise, the chat thread will always tell us that it is using the
// default system prompt:
chatThread = chatThread with { SystemPrompt = systemPromptTextWithChatTemplate };
LOGGER.LogInformation(logMessage);
//
// Add augmented data, if available:
//
var isAugmentedDataAvailable = !string.IsNullOrWhiteSpace(chatThread.AugmentedData);
var systemPromptWithAugmentedData = isAugmentedDataAvailable switch
{
true => $"""
{chatThread.SystemPrompt}
{systemPromptTextWithChatTemplate}
{chatThread.AugmentedData}
""",
false => chatThread.SystemPrompt,
false => systemPromptTextWithChatTemplate,
};
if(isAugmentedDataAvailable)
logger.LogInformation("Augmented data is available for the chat thread.");
LOGGER.LogInformation("Augmented data is available for the chat thread.");
else
logger.LogInformation("No augmented data is available for the chat thread.");
LOGGER.LogInformation("No augmented data is available for the chat thread.");
//
// Prepare the system prompt:
// Add information from the profile if available and allowed:
//
string systemPromptText;
var logMessage = $"Using no profile for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedProfile))
logMessage = $"Using no profile for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedProfile) || this.allowProfile is false)
systemPromptText = systemPromptWithAugmentedData;
else
{
@@ -134,7 +178,7 @@ public sealed record ChatThread
}
}
logger.LogInformation(logMessage);
LOGGER.LogInformation(logMessage);
return systemPromptText;
}
+12 -3
View File
@@ -18,15 +18,24 @@ public class ContentBlock
/// <summary>
/// The content of the block.
/// </summary>
public IContent? Content { get; init; }
public IContent? Content { get; set; }
/// <summary>
/// The role of the content block in the chat thread, e.g., user, AI, etc.
/// </summary>
public ChatRole Role { get; init; } = ChatRole.NONE;
public ChatRole Role { get; set; } = ChatRole.NONE;
/// <summary>
/// Should the content block be hidden from the user?
/// </summary>
public bool HideFromUser { get; set; }
public bool HideFromUser { get; init; }
public ContentBlock DeepClone(bool changeHideState = false, bool hideFromUser = true) => new()
{
Time = this.Time,
ContentType = this.ContentType,
Content = this.Content?.DeepClone(),
Role = this.Role,
HideFromUser = changeHideState ? hideFromUser : this.HideFromUser,
};
}
@@ -1,6 +1,8 @@
@using AIStudio.Tools
@using MudBlazor
@using AIStudio.Components
@inherits AIStudio.Components.MSGComponentBase
<MudCard Class="@this.CardClasses" Outlined="@true">
<MudCardHeader>
<CardHeaderAvatar>
@@ -10,10 +12,18 @@
</CardHeaderAvatar>
<CardHeaderContent>
<MudText Typo="Typo.body1">
@this.Role.ToName() (@this.Time)
@this.Role.ToName() (@this.Time.LocalDateTime)
</MudText>
</CardHeaderContent>
<CardHeaderActions>
@if (this.Content.Sources.Count > 0)
{
<MudTooltip Text="@T("Number of sources")" Placement="Placement.Bottom">
<MudBadge Content="@this.Content.Sources.Count" Color="Color.Primary" Overlap="true" BadgeClass="sources-card-header">
<MudIconButton Icon="@Icons.Material.Filled.Link" />
</MudBadge>
</MudTooltip>
}
@if (this.IsSecondToLastBlock && this.Role is ChatRole.USER && this.EditLastUserBlockFunc is not null)
{
<MudTooltip Text="@T("Edit")" Placement="Placement.Bottom">
@@ -38,9 +48,14 @@
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@this.RemoveBlock"/>
</MudTooltip>
}
<MudTooltip Text="@T("Copies the content to the clipboard")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Color="Color.Default" OnClick="@this.CopyToClipboard"/>
</MudTooltip>
@if (this.Role is ChatRole.AI)
{
<MudTooltip Text="@T("Export Chat to Microsoft Word")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="@this.ExportToWord"/>
</MudTooltip>
}
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type" Size="Size.Medium"/>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
@@ -67,12 +82,16 @@
@if (this.Content.IsStreaming)
{
<MudText Typo="Typo.body1" Style="white-space: pre-wrap;">
@textContent.Text
@textContent.Text.RemoveThinkTags()
</MudText>
}
else
{
<MudMarkdown Value="@textContent.Text" OverrideHeaderTypo="@Markdown.OverrideHeaderTypo" CodeBlockTheme="@this.CodeColorPalette"/>
<MudMarkdown Value="@textContent.Text.RemoveThinkTags().Trim()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" />
@if (textContent.Sources.Count > 0)
{
<MudMarkdown Value="@textContent.Sources.ToMarkdown()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" />
}
}
}
}
@@ -1,6 +1,5 @@
using AIStudio.Components;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Chat;
@@ -61,15 +60,12 @@ public partial class ContentBlockComponent : MSGComponentBase
[Parameter]
public Func<bool> RegenerateEnabled { get; set; } = () => false;
[Inject]
private RustService RustService { get; init; } = null!;
[Inject]
private ISnackbar Snackbar { get; init; } = null!;
[Inject]
private IDialogService DialogService { get; init; } = null!;
[Inject]
private RustService RustService { get; init; } = null!;
private bool HideContent { get; set; }
#region Overrides of ComponentBase
@@ -115,33 +111,15 @@ public partial class ContentBlockComponent : MSGComponentBase
}
#endregion
/// <summary>
/// Copy this block's content to the clipboard.
/// </summary>
private async Task CopyToClipboard()
{
switch (this.Type)
{
case ContentType.TEXT:
var textContent = (ContentText) this.Content;
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text);
break;
default:
this.Snackbar.Add(T("Cannot copy this content type to clipboard!"), Severity.Error, config =>
{
config.Icon = Icons.Material.Filled.ContentCopy;
config.IconSize = Size.Large;
config.IconColor = Color.Error;
});
break;
}
}
private string CardClasses => $"my-2 rounded-lg {this.Class}";
private CodeBlockTheme CodeColorPalette => this.SettingsManager.IsDarkMode ? CodeBlockTheme.Dark : CodeBlockTheme.Default;
private MudMarkdownStyling MarkdownStyling => new()
{
CodeBlock = { Theme = this.CodeColorPalette },
};
private async Task RemoveBlock()
{
@@ -158,6 +136,11 @@ public partial class ContentBlockComponent : MSGComponentBase
await this.RemoveBlockFunc(this.Content);
}
private async Task ExportToWord()
{
await PandocExport.ToMicrosoftWord(this.RustService, this.DialogService, T("Export Chat to Microsoft Word"), this.Content);
}
private async Task RegenerateBlock()
{
if (this.RegenerateFunc is null)
@@ -204,4 +187,5 @@ public partial class ContentBlockComponent : MSGComponentBase
if (edit.HasValue && edit.Value)
await this.EditLastUserBlockFunc(this.Content);
}
}
+15 -3
View File
@@ -13,11 +13,11 @@ public sealed class ContentImage : IContent, IImageSource
/// <inheritdoc />
[JsonIgnore]
public bool InitialRemoteWait { get; set; } = false;
public bool InitialRemoteWait { get; set; }
/// <inheritdoc />
[JsonIgnore]
public bool IsStreaming { get; set; } = false;
public bool IsStreaming { get; set; }
/// <inheritdoc />
[JsonIgnore]
@@ -28,10 +28,22 @@ public sealed class ContentImage : IContent, IImageSource
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;
/// <inheritdoc />
public Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default)
public List<Source> Sources { get; set; } = [];
/// <inheritdoc />
public Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatChatThread, CancellationToken token = default)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public IContent DeepClone() => new ContentImage
{
Source = this.Source,
InitialRemoteWait = this.InitialRemoteWait,
IsStreaming = this.IsStreaming,
SourceType = this.SourceType,
};
#endregion
+26 -10
View File
@@ -11,6 +11,8 @@ namespace AIStudio.Chat;
/// </summary>
public sealed class ContentText : IContent
{
private static readonly ILogger<ContentText> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ContentText>();
/// <summary>
/// The minimum time between two streaming events, when the user
/// enables the energy saving mode.
@@ -24,7 +26,7 @@ public sealed class ContentText : IContent
public bool InitialRemoteWait { get; set; }
/// <inheritdoc />
// [JsonIgnore]
[JsonIgnore]
public bool IsStreaming { get; set; }
/// <inheritdoc />
@@ -36,30 +38,31 @@ public sealed class ContentText : IContent
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;
/// <inheritdoc />
public async Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatThread, CancellationToken token = default)
public List<Source> Sources { get; set; } = [];
/// <inheritdoc />
public async Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatThread, CancellationToken token = default)
{
if(chatThread is null)
return new();
if(!chatThread.IsLLMProviderAllowed(provider))
{
var logger = Program.SERVICE_PROVIDER.GetService<ILogger<ContentText>>()!;
logger.LogError("The provider is not allowed for this chat thread due to data security reasons. Skipping the AI process.");
LOGGER.LogError("The provider is not allowed for this chat thread due to data security reasons. Skipping the AI process.");
return chatThread;
}
// Call the RAG process. Right now, we only have one RAG process:
if (lastPrompt is not null)
if (lastUserPrompt is not null)
{
try
{
var rag = new AISrcSelWithRetCtxVal();
chatThread = await rag.ProcessAsync(provider, lastPrompt, chatThread, token);
chatThread = await rag.ProcessAsync(provider, lastUserPrompt, chatThread, token);
}
catch (Exception e)
{
var logger = Program.SERVICE_PROVIDER.GetService<ILogger<ContentText>>()!;
logger.LogError(e, "Skipping the RAG process due to an error.");
LOGGER.LogError(e, "Skipping the RAG process due to an error.");
}
}
@@ -80,7 +83,7 @@ public sealed class ContentText : IContent
this.InitialRemoteWait = true;
// Iterate over the responses from the AI:
await foreach (var deltaText in provider.StreamChatCompletion(chatModel, chatThread, settings, token))
await foreach (var contentStreamChunk in provider.StreamChatCompletion(chatModel, chatThread, settings, token))
{
// When the user cancels the request, we stop the loop:
if (token.IsCancellationRequested)
@@ -91,7 +94,10 @@ public sealed class ContentText : IContent
this.IsStreaming = true;
// Add the response to the text:
this.Text += deltaText;
this.Text += contentStreamChunk;
// Merge the sources:
this.Sources.MergeSources(contentStreamChunk.Sources);
// Notify the UI that the content has changed,
// depending on the energy saving mode:
@@ -119,12 +125,22 @@ public sealed class ContentText : IContent
this.InitialRemoteWait = false;
this.IsStreaming = false;
}, token);
this.Text = this.Text.RemoveThinkTags().Trim();
// Inform the UI that the streaming is done:
await this.StreamingDone();
return chatThread;
}
/// <inheritdoc />
public IContent DeepClone() => new ContentText
{
Text = this.Text,
InitialRemoteWait = this.InitialRemoteWait,
IsStreaming = this.IsStreaming,
};
#endregion
/// <summary>
+17 -1
View File
@@ -37,12 +37,28 @@ public interface IContent
/// </summary>
[JsonIgnore]
public Func<Task> StreamingDone { get; set; }
/// <summary>
/// The provided sources, if any.
/// </summary>
/// <remarks>
/// We cannot use ISource here because System.Text.Json does not support
/// interface serialization. So we have to use a concrete class.
/// </remarks>
[JsonIgnore]
public List<Source> Sources { get; set; }
/// <summary>
/// Uses the provider to create the content.
/// </summary>
public Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default);
public Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatChatThread, CancellationToken token = default);
/// <summary>
/// Creates a deep copy
/// </summary>
/// <returns>The copy</returns>
public IContent DeepClone();
/// <summary>
/// Returns the corresponding ERI content type.
/// </summary>
@@ -0,0 +1,18 @@
namespace AIStudio.Chat;
public static class StringExtensions
{
public static string RemoveThinkTags(this string input)
{
const string OPEN_TAG = "<think>";
const string CLOSE_TAG = "</think>";
if (string.IsNullOrWhiteSpace(input) || !input.StartsWith(OPEN_TAG, StringComparison.Ordinal))
return input;
var endIndex = input.IndexOf(CLOSE_TAG, StringComparison.Ordinal);
if (endIndex == -1)
return string.Empty;
return input[(endIndex + CLOSE_TAG.Length)..];
}
}
@@ -13,6 +13,18 @@ public partial class Changelog
public static readonly Log[] LOGS =
[
new (228, "v0.9.53, build 228 (2025-11-14 13:14 UTC)", "v0.9.53.md"),
new (227, "v0.9.52, build 227 (2025-10-24 06:00 UTC)", "v0.9.52.md"),
new (226, "v0.9.51, build 226 (2025-09-04 18:02 UTC)", "v0.9.51.md"),
new (225, "v0.9.50, build 225 (2025-08-10 16:40 UTC)", "v0.9.50.md"),
new (224, "v0.9.49, build 224 (2025-07-02 12:12 UTC)", "v0.9.49.md"),
new (223, "v0.9.48, build 223 (2025-06-10 13:15 UTC)", "v0.9.48.md"),
new (222, "v0.9.47, build 222 (2025-06-02 18:25 UTC)", "v0.9.47.md"),
new (221, "v0.9.46, build 221 (2025-06-01 19:19 UTC)", "v0.9.46.md"),
new (220, "v0.9.45, build 220 (2025-05-25 13:56 UTC)", "v0.9.45.md"),
new (219, "v0.9.44, build 219 (2025-05-18 19:33 UTC)", "v0.9.44.md"),
new (218, "v0.9.43, build 218 (2025-05-11 17:22 UTC)", "v0.9.43.md"),
new (217, "v0.9.42, build 217 (2025-05-04 13:03 UTC)", "v0.9.42.md"),
new (216, "v0.9.41, build 216 (2025-04-27 14:18 UTC)", "v0.9.41.md"),
new (215, "v0.9.40, build 215 (2025-04-20 13:30 UTC)", "v0.9.40.md"),
new (214, "v0.9.39, build 214 (2025-04-07 17:39 UTC)", "v0.9.39.md"),
@@ -6,4 +6,4 @@
}
</MudSelect>
<MudMarkdown Value="@this.LogContent" OverrideHeaderTypo="@Markdown.OverrideHeaderTypo"/>
<MudMarkdown Value="@this.LogContent" Props="Markdown.DefaultConfig"/>
@@ -80,7 +80,9 @@
<MudIconButton Icon="@Icons.Material.Filled.CommentBank" OnClick="() => this.StartNewChat(useSameWorkspace: true)"/>
</MudTooltip>
}
<ChatTemplateSelection CanChatThreadBeUsedForTemplate="@this.CanThreadBeSaved" CurrentChatThread="@this.ChatThread" CurrentChatTemplate="@this.currentChatTemplate" CurrentChatTemplateChanged="@this.ChatTemplateWasChanged"/>
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
{
<MudTooltip Text="@T("Delete this chat & start a new one.")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
@@ -106,9 +108,9 @@
<MudIconButton Icon="@Icons.Material.Filled.Stop" Color="Color.Error" OnClick="() => this.CancelStreaming()"/>
</MudTooltip>
}
<ProfileSelection CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged"/>
<ProfileSelection CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged" Disabled="@(!this.currentChatTemplate.AllowProfileUsage)" DisabledText="@T("Profile usage is disabled according to your chat template settings.")"/>
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
{
<DataSourceSelection @ref="@this.dataSourceSelectionComponent" PopoverTriggerMode="PopoverTriggerMode.BUTTON" PopoverButtonClasses="ma-3" LLMProvider="@this.Provider" DataSourceOptions="@this.GetCurrentDataSourceOptions()" DataSourceOptionsChanged="@(async options => await this.SetCurrentDataSourceOptions(options))" DataSourcesAISelected="@this.GetAgentSelectedDataSources()"/>
@@ -18,9 +18,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
[Parameter]
public EventCallback<ChatThread?> ChatThreadChanged { get; set; }
[Parameter]
public AIStudio.Settings.Provider Provider { get; set; }
public AIStudio.Settings.Provider Provider { get; set; } = AIStudio.Settings.Provider.NONE;
[Parameter]
public EventCallback<AIStudio.Settings.Provider> ProviderChanged { get; set; }
@@ -34,9 +34,6 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
[Inject]
private ILogger<ChatComponent> Logger { get; set; } = null!;
[Inject]
private ThreadSafeRandom RNG { get; init; } = null!;
[Inject]
private IDialogService DialogService { get; init; } = null!;
@@ -46,6 +43,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
private DataSourceSelection? dataSourceSelectionComponent;
private DataSourceOptions earlyDataSourceOptions = new();
private Profile currentProfile = Profile.NO_PROFILE;
private ChatTemplate currentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE;
private bool hasUnsavedChanges;
private bool mustScrollToBottomAfterRender;
private InnerScrolling scrollingArea = null!;
@@ -59,7 +57,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
private string currentWorkspaceName = string.Empty;
private Guid currentWorkspaceId = Guid.Empty;
private CancellationTokenSource? cancellationTokenSource;
// Unfortunately, we need the input field reference to blur the focus away. Without
// this, we cannot clear the input field.
private MudTextField<string> inputField = null!;
@@ -77,6 +75,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Get the preselected profile:
this.currentProfile = this.SettingsManager.GetPreselectedProfile(Tools.Components.CHAT);
// Get the preselected chat template:
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(Tools.Components.CHAT);
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
//
// Check for deferred messages of the kind 'SEND_TO_CHAT',
// aka the user sends an assistant result to the chat:
@@ -268,9 +270,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
}
}
private bool CanThreadBeSaved => this.ChatThread is not null && this.ChatThread.Blocks.Count > 0;
private bool CanThreadBeSaved => this.ChatThread is not null && this.ChatThread.Blocks.Any(b => !b.HideFromUser);
private string TooltipAddChatToWorkspace => string.Format(T(@"Start new chat in workspace ""{0}"""), this.currentWorkspaceName);
private string TooltipAddChatToWorkspace => string.Format(T("Start new chat in workspace '{0}'"), this.currentWorkspaceName);
private string UserInputStyle => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? this.Provider.UsedLLMProvider.GetConfidence(this.SettingsManager).SetColorStyle(this.SettingsManager) : string.Empty;
@@ -291,6 +293,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// We select the first 10 words of the user input:
var words = firstUserInput.Split(' ', StringSplitOptions.RemoveEmptyEntries);
var threadName = string.Join(' ', words.Take(10));
threadName = threadName.Trim();
// Remove all line breaks:
threadName = threadName.Replace("\r", string.Empty);
threadName = threadName.Replace("\n", " ");
threadName = threadName.Replace("\t", " ");
// If the thread name is empty, we use a default name:
if (string.IsNullOrWhiteSpace(threadName))
@@ -312,6 +320,18 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
}
private async Task ChatTemplateWasChanged(ChatTemplate chatTemplate)
{
this.currentChatTemplate = chatTemplate;
if(!string.IsNullOrWhiteSpace(this.currentChatTemplate.PredefinedUserPrompt))
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
if(this.ChatThread is null)
return;
await this.StartNewChat(true);
}
private IReadOnlyList<DataSourceAgentSelected> GetAgentSelectedDataSources()
{
@@ -407,13 +427,13 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
{
SelectedProvider = this.Provider.Id,
SelectedProfile = this.currentProfile.Id,
SelectedChatTemplate = this.currentChatTemplate.Id,
SystemPrompt = SystemPrompts.DEFAULT,
WorkspaceId = this.currentWorkspaceId,
ChatId = Guid.NewGuid(),
DataSourceOptions = this.earlyDataSourceOptions,
Name = this.ExtractThreadName(this.userInput),
Seed = this.RNG.Next(),
Blocks = [],
Blocks = this.currentChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE ? [] : this.currentChatTemplate.ExampleConversation.Select(x => x.DeepClone()).ToList(),
};
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
@@ -424,9 +444,15 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
if (string.IsNullOrWhiteSpace(this.ChatThread.Name))
this.ChatThread.Name = this.ExtractThreadName(this.userInput);
// Update provider and profile:
// Update provider, profile and chat template:
this.ChatThread.SelectedProvider = this.Provider.Id;
this.ChatThread.SelectedProfile = this.currentProfile.Id;
//
// Remark: We do not update the chat template here
// because the chat template is only used when starting a new chat.
// Updating the chat template afterward is not supported.
//
}
var time = DateTimeOffset.Now;
@@ -479,7 +505,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
});
// Clear the input field:
await this.inputField.FocusAsync();
this.userInput = string.Empty;
await this.inputField.BlurAsync();
// Enable the stream state for the chat component:
this.isStreaming = true;
@@ -500,7 +528,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
this.ChatThread = await aiText.CreateFromProviderAsync(this.Provider.CreateProvider(this.Logger), this.Provider.Model, lastUserPrompt, this.ChatThread, this.cancellationTokenSource.Token);
this.ChatThread = await aiText.CreateFromProviderAsync(this.Provider.CreateProvider(), this.Provider.Model, lastUserPrompt, this.ChatThread, this.cancellationTokenSource.Token);
}
this.cancellationTokenSource = null;
@@ -555,9 +583,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
//
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
{
var dialogParameters = new DialogParameters
var dialogParameters = new DialogParameters<ConfirmDialog>
{
{ "Message", "Are you sure you want to start a new chat? All unsaved changes will be lost." },
{ x => x.Message, "Are you sure you want to start a new chat? All unsaved changes will be lost." },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN);
@@ -602,7 +630,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
default:
case AddChatProviderBehavior.ADDED_CHATS_USE_LATEST_PROVIDER:
if(this.Provider == default)
if(this.Provider == AIStudio.Settings.Provider.NONE)
{
this.Provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.CHAT);
await this.ProviderChanged.InvokeAsync(this.Provider);
@@ -637,15 +665,17 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
{
SelectedProvider = this.Provider.Id,
SelectedProfile = this.currentProfile.Id,
SelectedChatTemplate = this.currentChatTemplate.Id,
SystemPrompt = SystemPrompts.DEFAULT,
WorkspaceId = this.currentWorkspaceId,
ChatId = Guid.NewGuid(),
Name = string.Empty,
Seed = this.RNG.Next(),
Blocks = [],
Blocks = this.currentChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE ? [] : this.currentChatTemplate.ExampleConversation.Select(x => x.DeepClone()).ToList(),
};
}
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
// Now, we have to reset the data source options as well:
this.ApplyStandardDataSourceOptions();
@@ -660,9 +690,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
{
var confirmationDialogParameters = new DialogParameters
var confirmationDialogParameters = new DialogParameters<ConfirmDialog>
{
{ "Message", T("Are you sure you want to move this chat? All unsaved changes will be lost.") },
{ x => x.Message, T("Are you sure you want to move this chat? All unsaved changes will be lost.") },
};
var confirmationDialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Unsaved Changes", confirmationDialogParameters, DialogOptions.FULLSCREEN);
@@ -671,11 +701,11 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
return;
}
var dialogParameters = new DialogParameters
var dialogParameters = new DialogParameters<WorkspaceSelectionDialog>
{
{ "Message", T("Please select the workspace where you want to move the chat to.") },
{ "SelectedWorkspace", this.ChatThread?.WorkspaceId },
{ "ConfirmText", T("Move chat") },
{ x => x.Message, T("Please select the workspace where you want to move the chat to.") },
{ x => x.SelectedWorkspace, this.ChatThread?.WorkspaceId ?? Guid.Empty },
{ x => x.ConfirmText, T("Move chat") },
};
var dialogReference = await this.DialogService.ShowAsync<WorkspaceSelectionDialog>(T("Move Chat to Workspace"), dialogParameters, DialogOptions.FULLSCREEN);
@@ -748,6 +778,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
{
var chatProvider = this.ChatThread?.SelectedProvider;
var chatProfile = this.ChatThread?.SelectedProfile;
var chatChatTemplate = this.ChatThread?.SelectedChatTemplate;
switch (this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior)
{
@@ -761,7 +792,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
break;
case LoadingChatProviderBehavior.ALWAYS_USE_LATEST_CHAT_PROVIDER:
if(this.Provider == default)
if(this.Provider == AIStudio.Settings.Provider.NONE)
this.Provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.CHAT);
break;
}
@@ -770,10 +801,13 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Try to select the profile:
if (!string.IsNullOrWhiteSpace(chatProfile))
this.currentProfile = this.SettingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == chatProfile) ?? Profile.NO_PROFILE;
// Try to select the chat template:
if (!string.IsNullOrWhiteSpace(chatChatTemplate))
{
this.currentProfile = this.SettingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == chatProfile);
if(this.currentProfile == default)
this.currentProfile = Profile.NO_PROFILE;
var selectedTemplate = this.SettingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatChatTemplate);
this.currentChatTemplate = selectedTemplate ?? ChatTemplate.NO_CHAT_TEMPLATE;
}
}
@@ -0,0 +1,31 @@
@using AIStudio.Settings
@inherits MSGComponentBase
<MudTooltip Placement="Placement.Top" Text="@T("Start a new chat with a chat template")">
<MudMenu AnchorOrigin="Origin.TopLeft" TransformOrigin="@Origin.BottomLeft" Class="@this.MarginClass">
<ActivatorContent>
@if (this.CurrentChatTemplate != ChatTemplate.NO_CHAT_TEMPLATE)
{
<MudButton IconSize="Size.Large" StartIcon="@Icons.Material.Filled.RateReview" IconColor="Color.Default">
@this.CurrentChatTemplate.Name
</MudButton>
}
else
{
<MudIconButton Icon="@Icons.Material.Filled.RateReview" />
}
</ActivatorContent>
<ChildContent>
<MudMenuItem Icon="@Icons.Material.Filled.Settings" Label="@T("Manage your templates")" OnClick="async () => await this.OpenSettingsDialog()" />
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.AddComment" Label="@T("Create template from current chat")" OnClick="async () => await this.CreateNewChatTemplateFromChat()" Disabled="@(!this.CanChatThreadBeUsedForTemplate)"/>
<MudDivider/>
@foreach (var chatTemplate in this.SettingsManager.ConfigurationData.ChatTemplates.GetAllChatTemplates())
{
<MudMenuItem Icon="@Icons.Material.Filled.RateReview" OnClick="async () => await this.SelectionChanged(chatTemplate)">
@chatTemplate.Name
</MudMenuItem>
}
</ChildContent>
</MudMenu>
</MudTooltip>
@@ -0,0 +1,56 @@
using AIStudio.Chat;
using AIStudio.Dialogs.Settings;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
using DialogOptions = AIStudio.Dialogs.DialogOptions;
namespace AIStudio.Components;
public partial class ChatTemplateSelection : MSGComponentBase
{
[Parameter]
public ChatTemplate CurrentChatTemplate { get; set; } = ChatTemplate.NO_CHAT_TEMPLATE;
[Parameter]
public bool CanChatThreadBeUsedForTemplate { get; set; }
[Parameter]
public ChatThread? CurrentChatThread { get; set; }
[Parameter]
public EventCallback<ChatTemplate> CurrentChatTemplateChanged { get; set; }
[Parameter]
public string MarginLeft { get; set; } = "ml-1";
[Parameter]
public string MarginRight { get; set; } = string.Empty;
[Inject]
private IDialogService DialogService { get; init; } = null!;
private string MarginClass => $"{this.MarginLeft} {this.MarginRight}";
private async Task SelectionChanged(ChatTemplate chatTemplate)
{
this.CurrentChatTemplate = chatTemplate;
await this.CurrentChatTemplateChanged.InvokeAsync(chatTemplate);
}
private async Task OpenSettingsDialog()
{
var dialogParameters = new DialogParameters();
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
}
private async Task CreateNewChatTemplateFromChat()
{
var dialogParameters = new DialogParameters<SettingsDialogChatTemplate>
{
{ x => x.CreateTemplateFromExistingChatThread, true },
{ x => x.ExistingChatThread, this.CurrentChatThread }
};
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
}
}
@@ -0,0 +1,22 @@
@if (!this.IsInline)
{
@if (this.ParentTabs is null)
{
<MudPaper Class="code-block no-elevation" Style="@this.BlockPadding">
<pre>
<code>
@this.ChildContent
</code>
</pre>
</MudPaper>
}
}
else
{
<span class="inline-code-block">
<kbd>
@this.ChildContent
</kbd>
</span>
}
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace AIStudio.Components;
public partial class CodeBlock : ComponentBase
{
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public string? Title { get; set; } = string.Empty;
[Parameter]
public bool IsInline { get; set; }
[CascadingParameter]
public CodeTabs? ParentTabs { get; set; }
protected override void OnInitialized()
{
if (this.ParentTabs is not null && this.Title is not null)
{
void BlockSelf(RenderTreeBuilder builder)
{
builder.OpenComponent<CodeBlock>(0);
builder.AddAttribute(1, "Title", this.Title);
builder.AddAttribute(2, "ChildContent", this.ChildContent);
builder.CloseComponent();
}
this.ParentTabs.RegisterBlock(this.Title, BlockSelf);
}
}
private string BlockPadding => this.ParentTabs is null ? "padding: 16px !important;" : "padding: 8px !important";
}
@@ -0,0 +1,11 @@
<MudTabs ActivePanelIndex="this.SelectedIndex" ActivePanelIndexChanged="async idx => await this.TabChanged(idx)" PanelClass="code-block mt-1" MinimumTabWidth="30px" Class="mt-2">
@foreach (var block in this.blocks)
{
<MudTabPanel Text="@block.Title">
@block.Fragment
</MudTabPanel>
}
</MudTabs>
<CascadingValue Value="this">
@this.ChildContent
</CascadingValue>
@@ -0,0 +1,42 @@
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class CodeTabs : ComponentBase
{
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public int SelectedIndex { get; set; }
[Parameter]
public EventCallback<int> SelectedIndexChanged { get; set; }
private readonly List<CodeTabItem> blocks = new();
internal void RegisterBlock(string title, RenderFragment fragment)
{
this.blocks.Add(new CodeTabItem
{
Title = title,
Fragment = fragment,
});
this.StateHasChanged();
}
private class CodeTabItem
{
public string Title { get; init; } = string.Empty;
public RenderFragment Fragment { get; init; } = null!;
}
private async Task TabChanged(int index)
{
this.SelectedIndex = index;
await this.SelectedIndexChanged.InvokeAsync(index);
await this.InvokeAsync(this.StateHasChanged);
}
}
@@ -44,7 +44,7 @@ public partial class ConfidenceInfo : MSGComponentBase
{
var index = 0;
foreach (var source in this.currentConfidence.Sources)
yield return ($"Source {++index}", source);
yield return (string.Format(T("Source {0}"), ++index), source);
}
private string GetCurrentConfidenceColor() => $"color: {this.currentConfidence.Level.GetColor(this.SettingsManager)};";
@@ -1 +1,23 @@
@inherits MSGComponentBase
@inherits MSGComponentBase
@if (this.Body is not null)
{
@if (!this.Disabled() && this.IsLocked())
{
<MudField Label="@this.Label" Variant="@this.Variant" Underline="false" HelperText="@this.OptionHelp" Class="@this.Classes" InnerPadding="false">
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.FlexStart" Wrap="Wrap.NoWrap" StretchItems="this.StretchItems">
@* MudTooltip.RootStyle is set as a workaround for issue -> https://github.com/MudBlazor/MudBlazor/issues/10882 *@
<MudTooltip Text="@TB("This feature is managed by your organization and has therefore been disabled.")" 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>
@this.Body
</MudStack>
</MudField>
}
else
{
<MudField Label="@this.Label" Variant="@this.Variant" Underline="false" HelperText="@this.OptionHelp" Class="@this.Classes" InnerPadding="false">
@this.Body
</MudField>
}
}
@@ -5,7 +5,7 @@ namespace AIStudio.Components;
/// <summary>
/// A base class for configuration options.
/// </summary>
public partial class ConfigurationBase : MSGComponentBase
public abstract partial class ConfigurationBase : MSGComponentBase
{
/// <summary>
/// The description of the option, i.e., the name. Should be
@@ -26,7 +26,42 @@ public partial class ConfigurationBase : MSGComponentBase
[Parameter]
public Func<bool> Disabled { get; set; } = () => false;
protected const string MARGIN_CLASS = "mb-6";
/// <summary>
/// Is the option locked by a configuration plugin?
/// </summary>
[Parameter]
public Func<bool> IsLocked { get; set; } = () => false;
/// <summary>
/// Should the option be stretched to fill the available space?
/// </summary>
protected abstract bool Stretch { get; }
/// <summary>
/// The CSS class to apply to the component.
/// </summary>
protected virtual string GetClassForBase => string.Empty;
/// <summary>
/// The visual variant of the option.
/// </summary>
protected virtual Variant Variant => Variant.Text;
/// <summary>
/// The label to display for the option.
/// </summary>
protected virtual string Label => string.Empty;
private StretchItems StretchItems => this.Stretch ? StretchItems.End : StretchItems.None;
protected bool IsDisabled => this.Disabled() || this.IsLocked();
private string Classes => $"{this.GetClassForBase} {MARGIN_CLASS}";
private protected virtual RenderFragment? Body => null;
private const string MARGIN_CLASS = "mb-6";
protected static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
#region Overrides of ComponentBase
@@ -39,7 +74,9 @@ public partial class ConfigurationBase : MSGComponentBase
}
#endregion
private string TB(string fallbackEN) => this.T(fallbackEN, typeof(ConfigurationBase).Namespace, nameof(ConfigurationBase));
protected async Task InformAboutChange() => await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
#region Overrides of MSGComponentBase
@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace AIStudio.Components;
public abstract class ConfigurationBaseCore : ConfigurationBase
{
private protected sealed override RenderFragment Body => this.BuildRenderTree;
// Allow content to be provided by a .razor file but without
// overriding the content of the base class
protected new virtual void BuildRenderTree(RenderTreeBuilder builder)
{
}
}
@@ -1,3 +1,3 @@
@using AIStudio.Settings
@inherits MSGComponentBase
<ConfigurationSelect 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" 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,17 +18,17 @@ public partial class ConfigurationMinConfidenceSelection : MSGComponentBase
[Parameter]
public Action<ConfidenceLevel> SelectionUpdate { get; set; } = _ => { };
/// <summary>
/// Is the selection component disabled?
/// </summary>
[Parameter]
public Func<bool> Disabled { get; set; } = () => false;
/// <summary>
/// Boolean value indicating whether the selection is restricted to a global minimum confidence level.
/// </summary>
[Parameter]
public bool RestrictToGlobalMinimumConfidence { get; set; }
[Parameter]
public Func<bool> Disabled { get; set; } = () => false;
[Parameter]
public Func<bool> IsLocked { get; set; } = () => false;
private ConfidenceLevel FilteredSelectedValue()
{
@@ -1,4 +1,4 @@
@inherits ConfigurationBase
@inherits ConfigurationBaseCore
@typeparam TData
<MudSelectExtended
@@ -7,12 +7,10 @@
MultiSelectionTextFunc="@this.GetMultiSelectionText"
SelectedValues="@this.SelectedValues()"
Strict="@true"
Disabled="@this.Disabled()"
Disabled="@this.IsDisabled"
Margin="Margin.Dense"
Label="@this.OptionDescription"
Class="@GetClass"
Variant="Variant.Outlined"
HelperText="@this.OptionHelp"
Class="rounded-lg"
Underline="false"
SelectedValuesChanged="@this.OptionChanged">
@foreach (var data in this.Data)
{
@@ -8,7 +8,7 @@ namespace AIStudio.Components;
/// Configuration component for selecting many values from a list.
/// </summary>
/// <typeparam name="TData">The type of the value to select.</typeparam>
public partial class ConfigurationMultiSelect<TData> : ConfigurationBase
public partial class ConfigurationMultiSelect<TData> : ConfigurationBaseCore
{
/// <summary>
/// The data to select from.
@@ -28,6 +28,19 @@ public partial class ConfigurationMultiSelect<TData> : ConfigurationBase
[Parameter]
public Action<HashSet<TData>> SelectionUpdate { get; set; } = _ => { };
#region Overrides of ConfigurationBase
/// <inheritdoc />
protected override bool Stretch => true;
/// <inheritdoc />
protected override Variant Variant => Variant.Outlined;
/// <inheritdoc />
protected override string Label => this.OptionDescription;
#endregion
private async Task OptionChanged(IEnumerable<TData?>? updatedValues)
{
if(updatedValues is null)
@@ -39,8 +52,6 @@ public partial class ConfigurationMultiSelect<TData> : ConfigurationBase
await this.InformAboutChange();
}
private static string GetClass => $"{MARGIN_CLASS} rounded-lg";
private string GetMultiSelectionText(List<TData?>? selectedValues)
{
if(selectedValues is null || selectedValues.Count == 0)
@@ -1,7 +1,5 @@
@inherits ConfigurationBase
@inherits ConfigurationBaseCore
<MudField Disabled="@this.Disabled()" Label="@this.OptionDescription" Variant="Variant.Outlined" HelperText="@this.OptionHelp" Class="@MARGIN_CLASS">
<MudSwitch T="bool" Disabled="@this.Disabled()" Value="@this.State()" ValueChanged="@this.OptionChanged" Color="Color.Primary">
@(this.State() ? this.LabelOn : this.LabelOff)
</MudSwitch>
</MudField>
<MudSwitch T="bool" Disabled="@this.IsDisabled" Value="@this.State()" ValueChanged="@this.OptionChanged" Color="Color.Primary">
@(this.State() ? this.LabelOn : this.LabelOff)
</MudSwitch>
@@ -5,7 +5,7 @@ namespace AIStudio.Components;
/// <summary>
/// Configuration component for any boolean option.
/// </summary>
public partial class ConfigurationOption : ConfigurationBase
public partial class ConfigurationOption : ConfigurationBaseCore
{
/// <summary>
/// Text to display when the option is true.
@@ -31,6 +31,19 @@ public partial class ConfigurationOption : ConfigurationBase
[Parameter]
public Action<bool> StateUpdate { get; set; } = _ => { };
#region Overrides of ConfigurationBase
/// <inheritdoc />
protected override bool Stretch => true;
/// <inheritdoc />
protected override Variant Variant => Variant.Outlined;
/// <inheritdoc />
protected override string Label => this.OptionDescription;
#endregion
private async Task OptionChanged(bool updatedState)
{
this.StateUpdate(updatedState);
@@ -1,2 +1,2 @@
@inherits MSGComponentBase
<ConfigurationSelect OptionDescription="@T("Preselected provider")" Disabled="@this.Disabled" OptionHelp="@this.HelpText()" Data="@this.FilteredData()" SelectedValue="@this.SelectedValue" SelectionUpdate="@this.SelectionUpdate"/>
<ConfigurationSelect IsLocked="@this.IsLocked" OptionDescription="@T("Preselected provider")" Disabled="@(() => this.Disabled())" OptionHelp="@this.HelpText()" Data="@this.FilteredData()" SelectedValue="@this.SelectedValue" SelectionUpdate="@this.SelectionUpdate"/>
@@ -2,13 +2,15 @@ using System.Diagnostics.CodeAnalysis;
using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.PluginSystem;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class ConfigurationProviderSelection : MSGComponentBase
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfigurationProviderSelection).Namespace, nameof(ConfigurationProviderSelection));
[Parameter]
public Func<string> SelectedValue { get; set; } = () => string.Empty;
@@ -18,27 +20,17 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
[Parameter]
public IEnumerable<ConfigurationSelectData<string>> Data { get; set; } = new List<ConfigurationSelectData<string>>();
/// <summary>
/// Is the selection component disabled?
/// </summary>
[Parameter]
public Func<string> HelpText { get; set; } = () => TB("Select a provider that is preselected.");
[Parameter]
public Tools.Components Component { get; set; } = Tools.Components.NONE;
[Parameter]
public Func<bool> Disabled { get; set; } = () => false;
[Parameter]
public Func<string> HelpText { get; set; } = () => "Select a provider that is preselected.";
[Parameter]
public Tools.Components Component { get; set; } = Tools.Components.NONE;
#region Overrides of ComponentBase
protected override async Task OnParametersSetAsync()
{
this.ApplyFilters([], [ Event.CONFIGURATION_CHANGED ]);
await base.OnParametersSetAsync();
}
#endregion
public Func<bool> IsLocked { get; set; } = () => false;
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable<ConfigurationSelectData<string>> FilteredData()
@@ -50,6 +42,9 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
foreach (var providerId in this.Data)
{
var provider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == providerId.Value);
if (provider is null)
continue;
if (provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
yield return providerId;
}
@@ -1,7 +1,7 @@
@inherits ConfigurationBase
@typeparam T
@inherits ConfigurationBaseCore
@typeparam TConfig
<MudSelect T="T" Value="@this.SelectedValue()" Strict="@true" ShrinkLabel="@true" Disabled="@this.Disabled()" Margin="Margin.Dense" Label="@this.OptionDescription" Class="@GetClass" Variant="Variant.Outlined" HelperText="@this.OptionHelp" ValueChanged="@this.OptionChanged">
<MudSelect T="TConfig" Value="@this.SelectedValue()" Strict="@true" ShrinkLabel="@true" Disabled="@this.IsDisabled" Margin="Margin.Dense" Class="rounded-lg mb-0" Underline="false" ValueChanged="@this.OptionChanged">
@foreach (var data in this.Data)
{
<MudSelectItem Value="@data.Value">
@@ -7,33 +7,44 @@ namespace AIStudio.Components;
/// <summary>
/// Configuration component for selecting a value from a list.
/// </summary>
/// <typeparam name="T">The type of the value to select.</typeparam>
public partial class ConfigurationSelect<T> : ConfigurationBase
/// <typeparam name="TConfig">The type of the value to select.</typeparam>
public partial class ConfigurationSelect<TConfig> : ConfigurationBaseCore
{
/// <summary>
/// The data to select from.
/// </summary>
[Parameter]
public IEnumerable<ConfigurationSelectData<T>> Data { get; set; } = [];
public IEnumerable<ConfigurationSelectData<TConfig>> Data { get; set; } = [];
/// <summary>
/// The selected value.
/// </summary>
[Parameter]
public Func<T> SelectedValue { get; set; } = () => default!;
public Func<TConfig> SelectedValue { get; set; } = () => default!;
/// <summary>
/// An action that is called when the selection changes.
/// </summary>
[Parameter]
public Action<T> SelectionUpdate { get; set; } = _ => { };
public Action<TConfig> SelectionUpdate { get; set; } = _ => { };
private async Task OptionChanged(T updatedValue)
#region Overrides of ConfigurationBase
/// <inheritdoc />
protected override bool Stretch => true;
/// <inheritdoc />
protected override string Label => this.OptionDescription;
/// <inheritdoc />
protected override Variant Variant => Variant.Outlined;
#endregion
private async Task OptionChanged(TConfig updatedValue)
{
this.SelectionUpdate(updatedValue);
await this.SettingsManager.StoreSettings();
await this.InformAboutChange();
}
private static string GetClass => $"{MARGIN_CLASS} rounded-lg";
}
@@ -1,8 +1,6 @@
@typeparam T
@inherits ConfigurationBase
@inherits ConfigurationBaseCore
<MudField Label="@this.OptionDescription" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.Disabled()">
<MudSlider T="@T" Size="Size.Medium" Value="@this.Value()" ValueChanged="@this.OptionChanged" Min="@this.Min" Max="@this.Max" Step="@this.Step" Immediate="@true" Disabled="@this.Disabled()">
@this.Value() @this.Unit
</MudSlider>
</MudField>
<MudSlider T="@T" Size="Size.Medium" Value="@this.Value()" ValueChanged="@this.OptionChanged" Min="@this.Min" Max="@this.Max" Step="@this.Step" Immediate="@true" Disabled="@this.IsDisabled" Class="mb-1">
@this.Value() @this.Unit
</MudSlider>
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class ConfigurationSlider<T> : ConfigurationBase where T : struct, INumber<T>
public partial class ConfigurationSlider<T> : ConfigurationBaseCore where T : struct, INumber<T>
{
/// <summary>
/// The minimum value for the slider.
@@ -42,6 +42,18 @@ public partial class ConfigurationSlider<T> : ConfigurationBase where T : struct
[Parameter]
public Action<T> ValueUpdate { get; set; } = _ => { };
#region Overrides of ConfigurationBase
/// <inheritdoc />
protected override bool Stretch => true;
/// <inheritdoc />
protected override Variant Variant => Variant.Outlined;
protected override string Label => this.OptionDescription;
#endregion
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
@@ -1,12 +1,10 @@
@inherits ConfigurationBase
@inherits ConfigurationBaseCore
<MudTextField
T="string"
Text="@this.Text()"
TextChanged="@this.InternalUpdate"
Label="@this.OptionDescription"
Disabled="@this.Disabled()"
Class="@MARGIN_CLASS"
Disabled="@this.IsDisabled"
Adornment="Adornment.Start"
AdornmentIcon="@this.Icon"
AdornmentColor="@this.IconColor"
@@ -15,5 +13,5 @@
AutoGrow="@this.AutoGrow"
MaxLines="@this.GetMaxLines"
Immediate="@true"
Variant="Variant.Outlined"
Underline="false"
/>
@@ -4,7 +4,7 @@ using Timer = System.Timers.Timer;
namespace AIStudio.Components;
public partial class ConfigurationText : ConfigurationBase
public partial class ConfigurationText : ConfigurationBaseCore
{
/// <summary>
/// The text used for the textfield.
@@ -43,10 +43,21 @@ public partial class ConfigurationText : ConfigurationBase
public int MaxLines { get; set; } = 12;
private string internalText = string.Empty;
private Timer timer = new(TimeSpan.FromMilliseconds(500))
private readonly Timer timer = new(TimeSpan.FromMilliseconds(500))
{
AutoReset = false
};
#region Overrides of ConfigurationBase
/// <inheritdoc />
protected override bool Stretch => true;
protected override Variant Variant => Variant.Outlined;
protected override string Label => this.OptionDescription;
#endregion
#region Overrides of ConfigurationBase
@@ -56,8 +67,6 @@ public partial class ConfigurationText : ConfigurationBase
await base.OnInitializedAsync();
}
#region Overrides of ComponentBase
protected override async Task OnParametersSetAsync()
{
this.internalText = this.Text();
@@ -66,8 +75,6 @@ public partial class ConfigurationText : ConfigurationBase
#endregion
#endregion
private bool AutoGrow => this.NumLines > 1;
private int GetMaxLines => this.AutoGrow ? this.MaxLines : 1;
@@ -85,4 +92,23 @@ public partial class ConfigurationText : ConfigurationBase
await this.SettingsManager.StoreSettings();
await this.InformAboutChange();
}
#region Overrides of MSGComponentBase
protected override void DisposeResources()
{
try
{
this.timer.Stop();
this.timer.Dispose();
}
catch
{
// ignore
}
base.DisposeResources();
}
#endregion
}
@@ -27,7 +27,7 @@
</MudText>
<MudSpacer/>
<MudTooltip Text="@T("Manage your data sources")" Placement="Placement.Top">
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Settings" OnClick="@this.OpenSettingsDialog"/>
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="@this.OpenSettingsDialog"/>
</MudTooltip>
</MudStack>
</CardHeaderContent>
@@ -56,7 +56,7 @@
}
else if (this.showDataSourceSelection)
{
<MudTextSwitch Label="Are data sources enabled?" Value="@this.areDataSourcesEnabled" LabelOn="@T("Yes, I want to use data sources.")" LabelOff="@T("No, I don't want to use data sources.")" ValueChanged="@this.EnabledChanged"/>
<MudTextSwitch Label="@T("Are data sources enabled?")" Value="@this.areDataSourcesEnabled" LabelOn="@T("Yes, I want to use data sources.")" LabelOff="@T("No, I don't want to use data sources.")" ValueChanged="@this.EnabledChanged"/>
@if (this.areDataSourcesEnabled)
{
<MudTextSwitch Label="@T("AI-based data source selection")" Value="@this.aiBasedSourceSelection" LabelOn="@T("Yes, let the AI decide which data sources are needed.")" LabelOff="@T("No, I manually decide which data source to use.")" ValueChanged="@this.AutoModeChanged"/>
@@ -0,0 +1,3 @@
@inherits MudComponentBase
<MudTextField T="string" Disabled="@this.Disabled" Text="@this.text" TextChanged="@this.OnTextChanged" Validation="@this.ValidationFunc" Label="@this.Label" Variant="Variant.Outlined" Lines="@this.Lines" MaxLines="@this.MaxLines" AutoGrow="@(this.MaxLines > this.Lines)" Margin="Margin.Dense" UserAttributes="@this.Attributes" HelperText="@this.HelpText" Placeholder="@this.Placeholder" Class="mb-3" Immediate="true" Adornment="Adornment.Start" AdornmentIcon="@this.Icon"/>
@@ -0,0 +1,123 @@
using Microsoft.AspNetCore.Components;
using Timer = System.Timers.Timer;
namespace AIStudio.Components;
public partial class DebouncedTextField : MudComponentBase, IDisposable
{
[Parameter]
public string Label { get; set; } = string.Empty;
[Parameter]
public string Text { get; set; } = string.Empty;
[Parameter]
public EventCallback<string> TextChanged { get; set; }
[Parameter]
public Func<string, Task> WhenTextChangedAsync { get; set; } = _ => Task.CompletedTask;
[Parameter]
public Action<string> WhenTextCanged { get; set; } = _ => { };
[Parameter]
public int Lines { get; set; } = 1;
[Parameter]
public int MaxLines { get; set; } = 1;
[Parameter]
public Dictionary<string, object?> Attributes { get; set; } = [];
[Parameter]
public Func<string, string?> ValidationFunc { get; set; } = _ => null;
[Parameter]
public string HelpText { get; set; } = string.Empty;
[Parameter]
public string Placeholder { get; set; } = string.Empty;
[Parameter]
public string Icon { get; set; } = string.Empty;
[Parameter]
public TimeSpan DebounceTime { get; set; } = TimeSpan.FromMilliseconds(800);
[Parameter]
public bool Disabled { get; set; }
private readonly Timer debounceTimer = new();
private string text = string.Empty;
private string lastParameterText = string.Empty;
private bool isInitialized;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
this.text = this.Text;
this.lastParameterText = this.Text;
this.debounceTimer.AutoReset = false;
this.debounceTimer.Interval = this.DebounceTime.TotalMilliseconds;
this.debounceTimer.Elapsed += (_, _) =>
{
this.debounceTimer.Stop();
this.InvokeAsync(async () => await this.TextChanged.InvokeAsync(this.text));
this.InvokeAsync(async () => await this.WhenTextChangedAsync(this.text));
this.InvokeAsync(() => this.WhenTextCanged(this.text));
};
this.isInitialized = true;
await base.OnInitializedAsync();
}
protected override async Task OnParametersSetAsync()
{
// Ensure the timer uses the latest debouncing interval:
if (!this.isInitialized)
return;
if(Math.Abs(this.debounceTimer.Interval - this.DebounceTime.TotalMilliseconds) > 1)
this.debounceTimer.Interval = this.DebounceTime.TotalMilliseconds;
// Only sync when the parent's parameter actually changed since the last change:
if (this.Text != this.lastParameterText)
{
this.text = this.Text;
this.lastParameterText = this.Text;
}
this.debounceTimer.Stop();
this.debounceTimer.Start();
await base.OnParametersSetAsync();
}
#endregion
private void OnTextChanged(string value)
{
this.text = value;
this.debounceTimer.Stop();
this.debounceTimer.Start();
}
#region IDisposable
public void Dispose()
{
try
{
this.debounceTimer.Stop();
this.debounceTimer.Dispose();
}
catch
{
// ignore
}
}
#endregion
}
@@ -1,4 +1,4 @@
<MudExpansionPanel Class="border-solid border rounded-lg" Expanded="@this.IsExpanded">
<MudExpansionPanel Class="border-solid border rounded-lg" Expanded="@this.IsExpanded" MaxHeight="@this.MaxHeight" ExpandedChanged="async s => await this.ExpandedChanged(s)">
<TitleContent>
<div class="d-flex align-center">
<MudIcon Icon="@this.HeaderIcon" Size="@this.IconSize" Color="@this.IconColor" class="mr-3"/>
@@ -16,6 +16,12 @@ public partial class ExpansionPanel : ComponentBase
[Parameter]
public string HeaderText { get; set; } = "n/a";
[Parameter]
public int? MaxHeight { get; set; }
[Parameter]
public Func<bool, Task> ExpandedChanged { get; set; } = _ => Task.CompletedTask;
[Parameter]
public RenderFragment? ChildContent { get; set; }
Loaded 100 of 457 files, more files were not shown because too many files have changed in this diff. Show more