mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-05 03:09:40 +00:00
Improved enterprise IT (#497)
This commit is contained in:
1 parent
7a498d524e
commit
32e1ab977d
9 files changed
+200
-21
No files matched your search
+2
-2
@@ -1129,7 +1129,7 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T3032662264"] = "Benutzerdefinierte Sprache"
|
||||
|
||||
-- Your input to improve
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T3037449423"] = "Ihr Vorschlag zur Verbesserung"
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T3037449423"] = "Ihr Text, der verbessert werden soll"
|
||||
|
||||
-- Writing style
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T3754048862"] = "Schreibstil"
|
||||
@@ -4213,7 +4213,7 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "Diese Bibliothek wird
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "Für die sichere Kommunikation zwischen der Benutzeroberfläche und der Laufzeit müssen wir Zertifikate erstellen. Diese Rust-Bibliothek eignet sich hervorragend dafür."
|
||||
|
||||
-- AI Studio runs without an enterprise configuration.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2244723851"] = "AI Studio läuft ohne eine Konfiguration ihrer Organisation."
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2244723851"] = "Dies ist eine private AI Studio-Installation. Es wird keine Konfiguration einer Organisation verwendet."
|
||||
|
||||
-- OK
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK"
|
||||
|
||||
+1
-1
@@ -4213,7 +4213,7 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "This library is used t
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose."
|
||||
|
||||
-- AI Studio runs without an enterprise configuration.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2244723851"] = "AI Studio runs without an enterprise configuration."
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2244723851"] = "This is a private AI Studio installation. It runs without an enterprise configuration."
|
||||
|
||||
-- OK
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK"
|
||||
|
||||
@@ -42,6 +42,7 @@ public static partial class PluginFactory
|
||||
var tempDownloadFile = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
await LockHotReloadAsync();
|
||||
using var httpClient = new HttpClient();
|
||||
var response = await httpClient.GetAsync(downloadUrl, cancellationToken);
|
||||
if (response.IsSuccessStatusCode)
|
||||
@@ -80,6 +81,8 @@ public static partial class PluginFactory
|
||||
LOG.LogError(e, "Failed to delete the temporary download file.");
|
||||
}
|
||||
}
|
||||
|
||||
UnlockHotReload();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -46,12 +46,41 @@ public static partial class PluginFactory
|
||||
try
|
||||
{
|
||||
LOG.LogInformation($"File changed ({changeType}): {args.FullPath}. Reloading plugins...");
|
||||
|
||||
// Wait for parallel writes to finish:
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
if (File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||
{
|
||||
LOG.LogInformation("Hot reload lock file exists. Waiting for it to be released before proceeding with the reload.");
|
||||
|
||||
var lockFileCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
||||
var token = lockFileCancellationTokenSource.Token;
|
||||
var waitTime = TimeSpan.FromSeconds(1);
|
||||
while (File.Exists(HOT_RELOAD_LOCK_FILE) && !token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
LOG.LogDebug("Waiting for hot reload lock to be released...");
|
||||
await Task.Delay(waitTime, token);
|
||||
waitTime = TimeSpan.FromSeconds(Math.Min(waitTime.TotalSeconds * 2, 120)); // Exponential backoff with a cap
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// Case: The cancellation token was triggered, meaning the lock file is still present.
|
||||
// We expect that something goes wrong. So, we try to delete the lock file:
|
||||
LOG.LogWarning("Hot reload lock file still exists after 30 seconds. Attempting to delete it...");
|
||||
UnlockHotReload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.LogInformation("Hot reload lock file released. Proceeding with plugin reload.");
|
||||
}
|
||||
|
||||
await LoadAll();
|
||||
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.LogError(e, $"Error while reloading plugins after change in file '{args.FullPath}' with change type '{changeType}'.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
HOT_RELOAD_SEMAPHORE.Release();
|
||||
|
||||
@@ -13,6 +13,7 @@ public static partial class PluginFactory
|
||||
private static string PLUGINS_ROOT = string.Empty;
|
||||
private static string INTERNAL_PLUGINS_ROOT = string.Empty;
|
||||
private static string CONFIGURATION_PLUGINS_ROOT = string.Empty;
|
||||
private static string HOT_RELOAD_LOCK_FILE = string.Empty;
|
||||
private static FileSystemWatcher HOT_RELOAD_WATCHER = null!;
|
||||
private static ILanguagePlugin BASE_LANGUAGE_PLUGIN = NoPluginLanguage.INSTANCE;
|
||||
|
||||
@@ -30,6 +31,7 @@ public static partial class PluginFactory
|
||||
LOG.LogInformation("Initializing plugin factory...");
|
||||
DATA_DIR = SettingsManager.DataDirectory!;
|
||||
PLUGINS_ROOT = Path.Join(DATA_DIR, "plugins");
|
||||
HOT_RELOAD_LOCK_FILE = Path.Join(PLUGINS_ROOT, ".lock");
|
||||
INTERNAL_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".internal");
|
||||
CONFIGURATION_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".config");
|
||||
|
||||
@@ -41,6 +43,51 @@ public static partial class PluginFactory
|
||||
LOG.LogInformation("Plugin factory initialized successfully.");
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async Task LockHotReloadAsync()
|
||||
{
|
||||
if (!IS_INITIALIZED)
|
||||
{
|
||||
LOG.LogError("PluginFactory is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||
{
|
||||
LOG.LogWarning("Hot reload lock file already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
await File.WriteAllTextAsync(HOT_RELOAD_LOCK_FILE, DateTime.UtcNow.ToString("o"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.LogError(e, "An error occurred while trying to lock hot reloading.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UnlockHotReload()
|
||||
{
|
||||
if (!IS_INITIALIZED)
|
||||
{
|
||||
LOG.LogError("PluginFactory is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||
File.Delete(HOT_RELOAD_LOCK_FILE);
|
||||
else
|
||||
LOG.LogWarning("Hot reload lock file does not exist. Nothing to unlock.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.LogError(e, "An error occurred while trying to unlock hot reloading.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
# v0.9.48, build 223 (2025-06-xx xx:xx UTC)
|
||||
- Improved German translation.
|
||||
- Improved how configurations are applied in organizations and made the process more robust.
|
||||
Reference in new issue
Block a user