122 lines
4.4 KiB
PowerShell
122 lines
4.4 KiB
PowerShell
$ErrorActionPreference = "Stop"
|
|
|
|
function Invoke-RemotePowerShell {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$SshTarget,
|
|
[Parameter(Mandatory = $true)][string]$Script
|
|
)
|
|
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Script))
|
|
ssh $SshTarget "powershell -NoProfile -EncodedCommand $encoded"
|
|
}
|
|
|
|
function New-AppArchive {
|
|
$archive = Join-Path $env:TEMP "llm-model-chat-app.zip"
|
|
Remove-Item -Force $archive -ErrorAction SilentlyContinue
|
|
Get-ChildItem -Path "scripts", "tools", "plugins" -Recurse -Directory -Filter "__pycache__" -ErrorAction SilentlyContinue |
|
|
Sort-Object FullName -Descending |
|
|
ForEach-Object {
|
|
Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
$items = @(
|
|
"config",
|
|
"scripts",
|
|
"tools",
|
|
"registry",
|
|
"plugins",
|
|
"docs",
|
|
"evals",
|
|
"datasets",
|
|
"requirements.txt",
|
|
"requirements-training.txt",
|
|
"README.md"
|
|
)
|
|
Compress-Archive -Path $items -DestinationPath $archive -Force
|
|
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$zip = [System.IO.Compression.ZipFile]::Open($archive, [System.IO.Compression.ZipArchiveMode]::Update)
|
|
try {
|
|
@($zip.Entries | Where-Object { $_.FullName.Replace("\", "/") -match "/__pycache__/" }) |
|
|
ForEach-Object { $_.Delete() }
|
|
} finally {
|
|
$zip.Dispose()
|
|
}
|
|
|
|
$preflightReport = "reports/model-chat/preflight.json"
|
|
if (Test-Path -LiteralPath $preflightReport) {
|
|
$zip = [System.IO.Compression.ZipFile]::Open($archive, [System.IO.Compression.ZipArchiveMode]::Update)
|
|
try {
|
|
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
|
|
$zip,
|
|
(Get-Item -LiteralPath $preflightReport).FullName,
|
|
"reports/model-chat/preflight.json"
|
|
) | Out-Null
|
|
} finally {
|
|
$zip.Dispose()
|
|
}
|
|
}
|
|
return $archive
|
|
}
|
|
|
|
function Test-AppArchive {
|
|
param([Parameter(Mandatory = $true)][string]$Archive)
|
|
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$requiredEntries = @(
|
|
"config/gpu_profiles.json",
|
|
"scripts/model_chat_server.py",
|
|
"scripts/transformers_plugin_server.py",
|
|
"scripts/common.py",
|
|
"tools/model-chat/index.html",
|
|
"registry/index.json",
|
|
"plugins/1c/rag/profiles.yaml",
|
|
"requirements.txt",
|
|
"requirements-training.txt",
|
|
"README.md"
|
|
)
|
|
if (Test-Path -LiteralPath "reports/model-chat/preflight.json") {
|
|
$requiredEntries += "reports/model-chat/preflight.json"
|
|
}
|
|
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($Archive)
|
|
try {
|
|
$entryNames = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
|
|
foreach ($entry in $zip.Entries) {
|
|
[void]$entryNames.Add($entry.FullName.Replace("\", "/"))
|
|
}
|
|
$missing = @($requiredEntries | Where-Object { -not $entryNames.Contains($_) })
|
|
if ($missing.Count -gt 0) {
|
|
throw "Archive is missing required entries: $($missing -join ', ')"
|
|
}
|
|
$pycacheEntries = @($entryNames | Where-Object { $_ -match "/__pycache__/" })
|
|
if ($pycacheEntries.Count -gt 0) {
|
|
throw "Archive contains __pycache__ entries: $($pycacheEntries[0])"
|
|
}
|
|
Write-Host "Archive validation passed: $Archive"
|
|
} finally {
|
|
$zip.Dispose()
|
|
}
|
|
}
|
|
|
|
function Sync-AppDirectory {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$SshTarget,
|
|
[Parameter(Mandatory = $true)][string]$RemoteArchive,
|
|
[Parameter(Mandatory = $true)][string]$RemoteAppDir,
|
|
[string]$Archive
|
|
)
|
|
if (-not $Archive) {
|
|
$Archive = New-AppArchive
|
|
Test-AppArchive -Archive $Archive
|
|
}
|
|
ssh $SshTarget "cmd /c if not exist C:\ProgramData\LLM mkdir C:\ProgramData\LLM"
|
|
$remoteArchiveForScp = $RemoteArchive.Replace("\", "/")
|
|
scp $Archive "${SshTarget}:$remoteArchiveForScp"
|
|
$unpackScript = @"
|
|
New-Item -ItemType Directory -Force '$RemoteAppDir' | Out-Null
|
|
Remove-Item -Recurse -Force '$RemoteAppDir\*' -ErrorAction SilentlyContinue
|
|
Expand-Archive -Path '$RemoteArchive' -DestinationPath '$RemoteAppDir' -Force
|
|
New-Item -ItemType Directory -Force '$RemoteAppDir\reports','$RemoteAppDir\models\incoming' | Out-Null
|
|
"@
|
|
Invoke-RemotePowerShell -SshTarget $SshTarget -Script $unpackScript
|
|
}
|