From ddf1fba85cbc54ec97963a08bdc50440f019afff Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 17 Feb 2026 14:39:57 +0100 Subject: [PATCH] Added PowerShell example script --- documentation/Enterprise IT.md | 90 +++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/documentation/Enterprise IT.md b/documentation/Enterprise IT.md index 0b8c7388..279214d2 100644 --- a/documentation/Enterprise IT.md +++ b/documentation/Enterprise IT.md @@ -35,6 +35,94 @@ MINDWORK_AI_STUDIO_ENTERPRISE_CONFIGS=9072b77d-ca81-40da-be6a-861da525ef7b@https **Priority:** When multiple configurations define the same setting (e.g., a provider with the same ID), the first definition wins. The order of entries in the variable determines priority. Place the organization-wide configuration first, followed by department-specific configurations if the organization should have higher priority. +### Windows GPO / PowerShell example for `configs` + +If you distribute multiple GPOs, each GPO should read and write the same registry value (`configs`) and only update its own `id@url` entry. Other entries must stay untouched. + +The following PowerShell example provides helper functions for appending and removing entries safely: + +```powershell +$RegistryPath = "HKCU:\Software\github\MindWork AI Studio\Enterprise IT" +$ConfigsValueName = "configs" + +function Get-ConfigEntries { + param([string]$RawValue) + + if ([string]::IsNullOrWhiteSpace($RawValue)) { return @() } + + $entries = @() + foreach ($part in $RawValue.Split(';')) { + $trimmed = $part.Trim() + if ([string]::IsNullOrWhiteSpace($trimmed)) { continue } + + $pair = $trimmed.Split('@', 2) + if ($pair.Count -ne 2) { continue } + + $id = $pair[0].Trim().ToLowerInvariant() + $url = $pair[1].Trim() + if ([string]::IsNullOrWhiteSpace($id) -or [string]::IsNullOrWhiteSpace($url)) { continue } + + $entries += [PSCustomObject]@{ + Id = $id + Url = $url + } + } + + return $entries +} + +function ConvertTo-ConfigValue { + param([array]$Entries) + + return ($Entries | ForEach-Object { "$($_.Id)@$($_.Url)" }) -join ';' +} + +function Add-EnterpriseConfigEntry { + param( + [Parameter(Mandatory=$true)][Guid]$ConfigId, + [Parameter(Mandatory=$true)][string]$ServerUrl + ) + + if (-not (Test-Path $RegistryPath)) { + New-Item -Path $RegistryPath -Force | Out-Null + } + + $raw = (Get-ItemProperty -Path $RegistryPath -Name $ConfigsValueName -ErrorAction SilentlyContinue).$ConfigsValueName + $entries = Get-ConfigEntries -RawValue $raw + $normalizedId = $ConfigId.ToString().ToLowerInvariant() + $normalizedUrl = $ServerUrl.Trim() + + # Replace only this one ID, keep all other entries unchanged. + $entries = @($entries | Where-Object { $_.Id -ne $normalizedId }) + $entries += [PSCustomObject]@{ + Id = $normalizedId + Url = $normalizedUrl + } + + Set-ItemProperty -Path $RegistryPath -Name $ConfigsValueName -Type String -Value (ConvertTo-ConfigValue -Entries $entries) +} + +function Remove-EnterpriseConfigEntry { + param( + [Parameter(Mandatory=$true)][Guid]$ConfigId + ) + + if (-not (Test-Path $RegistryPath)) { return } + + $raw = (Get-ItemProperty -Path $RegistryPath -Name $ConfigsValueName -ErrorAction SilentlyContinue).$ConfigsValueName + $entries = Get-ConfigEntries -RawValue $raw + $normalizedId = $ConfigId.ToString().ToLowerInvariant() + + # Remove only this one ID, keep all other entries unchanged. + $updated = @($entries | Where-Object { $_.Id -ne $normalizedId }) + Set-ItemProperty -Path $RegistryPath -Name $ConfigsValueName -Type String -Value (ConvertTo-ConfigValue -Entries $updated) +} + +# Example usage: +# Add-EnterpriseConfigEntry -ConfigId "9072b77d-ca81-40da-be6a-861da525ef7b" -ServerUrl "https://intranet.example.org:30100/ai-studio/configuration" +# Remove-EnterpriseConfigEntry -ConfigId "9072b77d-ca81-40da-be6a-861da525ef7b" +``` + ### Single configuration (legacy) The following single-configuration keys and variables are still supported for backwards compatibility. AI Studio always reads both the multi-config and legacy variables and merges all found configurations into one list. If a configuration ID appears in both, the entry from the multi-config format takes priority (first occurrence wins). This means you can migrate to the new format incrementally without losing existing configurations: @@ -179,4 +267,4 @@ CONFIG["LLM_PROVIDERS"][#CONFIG["LLM_PROVIDERS"]+1] = { } ``` -The API key will be automatically decrypted when the configuration is loaded and stored securely in the operating system's credential store (Windows Credential Manager / macOS Keychain). \ No newline at end of file +The API key will be automatically decrypted when the configuration is loaded and stored securely in the operating system's credential store (Windows Credential Manager / macOS Keychain).