8a8d94c14a
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 16s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 18s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 18s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 12s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 16s
Project CI / Backend tests (pull_request) Failing after 21s
Project CI / Native shell tests (pull_request) Failing after 20s
Project CI / Frontend tests (pull_request) Failing after 8s
Project CI / AI game creator shell web tests (pull_request) Failing after 17s
Project CI / Repository checks (pull_request) Failing after 17s
- 自动环境预检接入首页与 Direct 后端:新建 Web 游戏在生成前完成 Node/npm、真实构建与双端浏览器检查 - 新增宿主权威执行账本与交付合同:冻结核验项、绑定当前输入证据、封口后拒绝新副作用并产出宿主报告 - 原生 shell、内置浏览器/托管命令与第三方 MCP 共用执行许可和累计执行时间预算,按执行批次与墙钟分别约束 - 新增固定种子 runner 物理基线、真实双端输入与公平窗口负例,可复用且不冒充完整关卡 - 新增请求与工具分段计时、有界并行批读和首轮上下文预取,未知耗时不补零 - 移除 SDK 全局串行的 apply_patch/update_plan 注册,改由宿主 agc_apply_patch/agc_update_plan 提供等价能力,独立工具可并发 - 付费提交与本地写入绑定原回合租约:封口、取消或耗尽后零新增提交,已受理操作保留 GET 对账 - 捆绑 Codex 由 0.147.0 升级到 0.155.1,固定版本收敛到 build_support/codex_bundle.rs,vendor 解析源码按 rust-v0.155.1 重取并更新 UPSTREAM 证据 - 适配 0.155 统一 exec(exec_command/write_stdin),生产夹具新增会话用例,宿主 Job 与期限约束保持有效 - 同步更新 AGC 主规范、Skill 与提示词、共享记忆和发行载荷校验
96 lines
5.5 KiB
PowerShell
96 lines
5.5 KiB
PowerShell
# 只读取 Windows Installer 已登记的同版本 Node.js 缓存;不执行安装、不访问网络。
|
|
$ErrorActionPreference = 'Stop'
|
|
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
|
|
$expectedVersion = $env:AGC_STAGING_NODE_VERSION
|
|
if ($expectedVersion -notmatch '^\d+\.\d+\.\d+$') { throw 'Invalid Node version' }
|
|
|
|
# WinVerifyTrust 强制仅使用本地证书缓存,禁止吊销/证书 URL 网络检索。
|
|
Add-Type -TypeDefinition @'
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
public static class AgcOfflineSignature {
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct FileInfo { public uint Size; public IntPtr Path; public IntPtr File; public IntPtr Subject; }
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct TrustData {
|
|
public uint Size; public IntPtr Policy; public IntPtr Sip; public uint Ui;
|
|
public uint Revocation; public uint Choice; public IntPtr File;
|
|
public uint StateAction; public IntPtr State; public IntPtr Url;
|
|
public uint Flags; public uint Context;
|
|
}
|
|
[DllImport("wintrust.dll", ExactSpelling=true, PreserveSig=true)]
|
|
static extern int WinVerifyTrust(IntPtr window, ref Guid action, ref TrustData data);
|
|
public static bool Verify(string path) {
|
|
IntPtr name = Marshal.StringToCoTaskMemUni(path);
|
|
IntPtr file = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileInfo)));
|
|
try {
|
|
var info = new FileInfo { Size=(uint)Marshal.SizeOf(typeof(FileInfo)), Path=name };
|
|
Marshal.StructureToPtr(info, file, false);
|
|
var data = new TrustData { Size=(uint)Marshal.SizeOf(typeof(TrustData)), Ui=2, Choice=1, File=file, Flags=0x1000|0x10 };
|
|
var action = new Guid("00AAC56B-CD44-11d0-8CC2-00C04FC295EE");
|
|
return WinVerifyTrust(new IntPtr(-1), ref action, ref data) == 0;
|
|
} finally { Marshal.FreeHGlobal(file); Marshal.FreeCoTaskMem(name); }
|
|
}
|
|
}
|
|
'@
|
|
|
|
function Read-Property($database, [string]$name) {
|
|
$view = $database.OpenView("SELECT ``Value`` FROM ``Property`` WHERE ``Property`` = '$name'")
|
|
try {
|
|
[void]$view.Execute()
|
|
$record = $view.Fetch()
|
|
if ($null -ne $record) { return $record.StringData(1) }
|
|
return ''
|
|
} finally { [void]$view.Close() }
|
|
}
|
|
|
|
$installer = New-Object -ComObject WindowsInstaller.Installer
|
|
$cacheRoot = [System.IO.Path]::GetFullPath((Join-Path ([Environment]::GetFolderPath('Windows')) 'Installer'))
|
|
$registrations = @(
|
|
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
|
|
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
|
|
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
|
)
|
|
$products = Get-ItemProperty $registrations -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.DisplayName -eq 'Node.js' -and $_.DisplayVersion -eq $expectedVersion -and $_.PSChildName -match '^\{[0-9A-Fa-f-]{36}\}$' } |
|
|
Select-Object -ExpandProperty PSChildName -Unique
|
|
foreach ($product in $products) {
|
|
try {
|
|
if ($installer.ProductInfo($product, 'ProductName') -ne 'Node.js') { continue }
|
|
if ($installer.ProductInfo($product, 'VersionString') -ne $expectedVersion) { continue }
|
|
$package = [System.IO.Path]::GetFullPath($installer.ProductInfo($product, 'LocalPackage'))
|
|
if (-not [string]::Equals([System.IO.Path]::GetDirectoryName($package), $cacheRoot, [StringComparison]::OrdinalIgnoreCase)) { continue }
|
|
if ([System.IO.Path]::GetExtension($package) -ne '.msi') { continue }
|
|
$entry = Get-Item -LiteralPath $package -Force
|
|
$cache = Get-Item -LiteralPath $cacheRoot -Force
|
|
if (($entry.Attributes -band [IO.FileAttributes]::ReparsePoint) -or ($cache.Attributes -band [IO.FileAttributes]::ReparsePoint)) { continue }
|
|
if (-not [AgcOfflineSignature]::Verify($package)) { continue }
|
|
$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([System.Security.Cryptography.X509Certificates.X509Certificate]::CreateFromSignedFile($package))
|
|
if ($certificate.Subject -notmatch '(^|,\s*)O=OpenJS Foundation(,|$)') { continue }
|
|
$database = $installer.OpenDatabase($package, 0)
|
|
if ((Read-Property $database 'ProductName') -ne 'Node.js') { continue }
|
|
if ((Read-Property $database 'ProductVersion') -ne $expectedVersion) { continue }
|
|
if ((Read-Property $database 'ProductCode') -ne $product) { continue }
|
|
$manufacturer = Read-Property $database 'Manufacturer'
|
|
if ($manufacturer -notin @('Node.js Foundation', 'OpenJS Foundation')) { continue }
|
|
$view = $database.OpenView('SELECT `Text` FROM `Control` WHERE `Dialog_` = ''LicenseAgreementDlg'' AND `Control` = ''LicenseText''')
|
|
try {
|
|
[void]$view.Execute()
|
|
$record = $view.Fetch()
|
|
if ($null -eq $record) { continue }
|
|
$content = $record.StringData(1)
|
|
} finally { [void]$view.Close() }
|
|
if (-not $content.StartsWith('{\rtf') -or $content.Length -gt 1048576) { continue }
|
|
if (-not $content.Contains('Node.js') -or -not $content.Contains('Permission is hereby granted')) { continue }
|
|
[pscustomobject]@{
|
|
productName = 'Node.js'; version = $expectedVersion; manufacturer = $manufacturer
|
|
signatureVerified = $true; signer = 'OpenJS Foundation'; format = 'rtf'; content = $content
|
|
} | ConvertTo-Json -Compress
|
|
exit 0
|
|
} catch {
|
|
# 单个损坏/无权限缓存不能绕过验证;继续查找其它已登记候选。
|
|
continue
|
|
}
|
|
}
|
|
throw 'No matching trusted installed Node.js license'
|