XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWorkflow

【WinUI】XFE基于windows的工作流

公开
关注 0 Fork 0 Star 0
UTF-8
param([Parameter(Mandatory)][string]$Output, [ValidateSet('x64','x86','ARM64','AnyCPU')][string]$Platform = 'x64')
$ErrorActionPreference = 'Stop'
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression') | Out-Null
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
function AgentFileHash([string]$Path) {
    $agentStream = [IO.File]::OpenRead($Path); $agentHasher = [Security.Cryptography.SHA256]::Create()
    try { return [BitConverter]::ToString($agentHasher.ComputeHash($agentStream)).Replace('-','').ToLowerInvariant() }
    finally { $agentHasher.Dispose(); $agentStream.Dispose() }
}
$agentRepo = Split-Path $PSScriptRoot
$agentArchitecture = if ($Platform -eq 'AnyCPU') { 'x64' } else { $Platform.ToLowerInvariant() }
$agentPins = @{
    x64 = @('24.19.0','57f71ab3652e797d84acddc79c81cc9ff1c6ddb2a1974cdb83f00fee9bff4c73')
    arm64 = @('24.19.0','8502f4a50b458d4cc38ed8f2001556c2cd239d464920f74017926ccb1e1c157f')
    x86 = @('22.23.3','1e07ac00e61b41b7ecf242de8e38883d237d5ad3fdcad7c16f2dd3a88670e2b6')
}
$agentVersion, $agentHash = $agentPins[$agentArchitecture]
$agentCache = Join-Path $agentRepo '.artifacts/agent-runtime'
New-Item -ItemType Directory -Force -Path $agentCache | Out-Null
$agentLock = $null
for ($agentAttempt = 0; $agentAttempt -lt 120 -and !$agentLock; $agentAttempt++) {
    try { $agentLock = [IO.File]::Open((Join-Path $agentCache '.restore.lock'), [IO.FileMode]::OpenOrCreate, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None) }
    catch [IO.IOException] { Start-Sleep -Milliseconds 500 }
}
if (!$agentLock) { throw 'Timed out waiting for the Agent runtime build cache.' }
try {
    $agentArchiveName = "node-v$agentVersion-win-$agentArchitecture"
    $agentArchive = Join-Path $agentCache ($agentArchiveName + '.zip')
    if (!(Test-Path -LiteralPath $agentArchive)) {
        $agentDownload = [Net.WebClient]::new()
        try { $agentDownload.DownloadFile("https://nodejs.org/dist/v$agentVersion/$agentArchiveName.zip", $agentArchive) }
        finally { $agentDownload.Dispose() }
    }
    if ((AgentFileHash $agentArchive) -ne $agentHash) { throw 'Bundled Node.js archive SHA256 mismatch.' }
    $agentNodeRoot = Join-Path $agentCache $agentArchiveName
    if (!(Test-Path -LiteralPath (Join-Path $agentNodeRoot 'node.exe')) -or !(Test-Path -LiteralPath (Join-Path $agentNodeRoot 'node_modules/npm/bin/npm-cli.js'))) {
        $agentExtractionRoot = [IO.Path]::GetFullPath($agentCache).TrimEnd('\','/') + [IO.Path]::DirectorySeparatorChar
        $agentZip = [IO.Compression.ZipFile]::OpenRead($agentArchive)
        try {
            foreach ($agentEntry in $agentZip.Entries) {
                $agentTarget = [IO.Path]::GetFullPath((Join-Path $agentExtractionRoot $agentEntry.FullName))
                if (!$agentTarget.StartsWith($agentExtractionRoot, [StringComparison]::OrdinalIgnoreCase)) { throw 'Runtime archive extraction path escapes cache.' }
                if ($agentEntry.FullName.EndsWith('/')) { [IO.Directory]::CreateDirectory($agentTarget) | Out-Null; continue }
                [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($agentTarget)) | Out-Null
                [IO.Compression.ZipFileExtensions]::ExtractToFile($agentEntry, $agentTarget, $true)
            }
        } finally { $agentZip.Dispose() }
    }
    $agentSkillSource = Join-Path $agentRepo 'XFEWorkflow/XFEWorkflow.Plugins.AgentBrowser/Skill'
    $agentPackageLock = Join-Path $agentSkillSource 'package-lock.json'
    $agentDependencyHash = AgentFileHash $agentPackageLock
    $agentDependencies = Join-Path $agentCache ('dependencies-' + $agentDependencyHash)
    if (!(Test-Path -LiteralPath (Join-Path $agentDependencies '.complete'))) {
        New-Item -ItemType Directory -Force -Path $agentDependencies | Out-Null
        Copy-Item -LiteralPath (Join-Path $agentSkillSource 'package.json'), $agentPackageLock -Destination $agentDependencies -Force
        Push-Location -LiteralPath $agentDependencies
        try {
            & (Join-Path $agentNodeRoot 'node.exe') (Join-Path $agentNodeRoot 'node_modules/npm/bin/npm-cli.js') ci --ignore-scripts --no-audit --no-fund
            if ($LASTEXITCODE -ne 0) { throw 'Agent browser locked dependency restore failed.' }
        } finally { Pop-Location }
        Set-Content -LiteralPath (Join-Path $agentDependencies '.complete') -Value $agentDependencyHash -Encoding ASCII
    }
    $agentSkillDestination = Join-Path $Output 'Skill'
    New-Item -ItemType Directory -Force -Path $agentSkillDestination | Out-Null
    Get-ChildItem -LiteralPath $agentSkillSource | ForEach-Object { Copy-Item -LiteralPath $_.FullName -Destination $agentSkillDestination -Recurse -Force }
    Copy-Item -LiteralPath (Join-Path $agentDependencies 'node_modules') -Destination $agentSkillDestination -Recurse -Force
    $agentRuntimeDestination = Join-Path $Output 'Runtime'
    New-Item -ItemType Directory -Force -Path $agentRuntimeDestination | Out-Null
    Copy-Item -LiteralPath (Join-Path $agentNodeRoot 'node.exe'), (Join-Path $agentNodeRoot 'LICENSE') -Destination $agentRuntimeDestination -Force
    @{ nodeVersion=$agentVersion; architecture=$agentArchitecture; archiveSha256=$agentHash; source="https://nodejs.org/dist/v$agentVersion/$agentArchiveName.zip"; dependencyLockSha256=$agentDependencyHash } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $agentRuntimeDestination 'sources.json') -Encoding UTF8
} finally { $agentLock.Dispose() }