From 3316f08c9280e2f6c0ffb4b513d301cf6f0d023a Mon Sep 17 00:00:00 2001 From: jkooe <62494645+jkooe@users.noreply.github.com> Date: Sun, 27 Sep 2026 19:32:53 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Windows=20=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E5=90=8E=E6=97=A0=E6=B3=95=E5=90=AF=E5=8A=A8=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20PowerShell=20=E5=86=99=E5=85=A5=E7=9A=84?= =?UTF-8?q?=20JSON=20=E5=B8=A6=20UTF-8=20BOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 真机报错:启动失败: Unexpected token '', "{"a"... is not valid JSON 根因:Windows PowerShell 5.1 的 Set-Content -Encoding UTF8 会写入 BOM(U+FEFF), Node 侧 JSON.parse 拒绝解析带 BOM 的文本。 双管齐下修复: 1. 写端 install.ps1:改用 [System.IO.File]::WriteAllText + UTF8Encoding($false) 写出无 BOM 的 UTF-8 2. 读端容错(兼容已被写坏的配置): - apps/agent/src/config.ts:读配置时剥离开头 BOM - packages/client/src/config.ts:同上 验证:构造带 BOM 的 agent.json(ef bb bf 开头),agent 可正常启动; 单元 26/26、E2E 21/21 全绿 --- apps/agent/src/config.ts | 5 ++++- packages/client/src/config.ts | 4 +++- scripts/install.ps1 | 7 +++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/agent/src/config.ts b/apps/agent/src/config.ts index b3b7b30..ea62753 100644 --- a/apps/agent/src/config.ts +++ b/apps/agent/src/config.ts @@ -92,7 +92,10 @@ export function defaultAgentConfig(): AgentConfig { export function loadAgentConfig(): { config: AgentConfig; isNew: boolean } { const p = agentConfigPath(); if (existsSync(p)) { - const cfg = JSON.parse(readFileSync(p, 'utf8')) as AgentConfig; + // 剥离 UTF-8 BOM:Windows 上由 PowerShell 写出的 JSON 可能带 BOM, + // 直接 JSON.parse 会报 "Unexpected token ''" + const text = readFileSync(p, 'utf8').replace(/^\uFEFF/, ''); + const cfg = JSON.parse(text) as AgentConfig; const envKey = process.env['NODEAGENT_KEY']; if (envKey) cfg.key = envKey; return { config: cfg, isNew: false }; diff --git a/packages/client/src/config.ts b/packages/client/src/config.ts index bd5712b..d79a38c 100644 --- a/packages/client/src/config.ts +++ b/packages/client/src/config.ts @@ -85,7 +85,9 @@ function migrate(raw: Record): ClientConfig { export function loadConfig(): ClientConfig | null { const p = configPath(); if (!existsSync(p)) return null; - const raw = JSON.parse(readFileSync(p, 'utf8')) as Record; + // 剥离 UTF-8 BOM(跨平台健壮:某些编辑器 / PowerShell 会写入 BOM) + const text = readFileSync(p, 'utf8').replace(/^\uFEFF/, ''); + const raw = JSON.parse(text) as Record; const cfg = migrate(raw); const envKey = process.env['NODEAGENT_KEY']; const cur = cfg.nodes[cfg.current]; diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 4cd5334..4f7cdb2 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -105,7 +105,7 @@ if (-not $Key) { Write-Ok "Generated a new pre-shared key" } -@{ +$cfgJson = @{ node_id = $NodeId host = "0.0.0.0" port = $Port @@ -114,7 +114,10 @@ if (-not $Key) { log_level = "info" allow_input = [bool]$AllowInput auth_mode = "psk" -} | ConvertTo-Json | Set-Content -Path $cfgPath -Encoding UTF8 +} | ConvertTo-Json +# 必须写「无 BOM」的 UTF-8:Windows PowerShell 5.1 的 `Set-Content -Encoding UTF8` +# 会写入 BOM(U+FEFF),导致 Node 侧 JSON.parse 报 "Unexpected token ''" +[System.IO.File]::WriteAllText($cfgPath, $cfgJson, (New-Object System.Text.UTF8Encoding($false))) Write-Ok "Config written: $cfgPath" # 5. Firewall (inbound, agent listens)