param( [string]$Tarball, [switch]$AuthOnly ) $ErrorActionPreference = 'Stop' $Root = Resolve-Path (Join-Path $PSScriptRoot '..\..\..') $PackageRoot = Join-Path $Root 'claude-code\claude-code-qiwe-assistant' $SharedEnvPath = Join-Path $PSScriptRoot '..\claude-code-voc-intelligence\.env.local' function Read-LocalToken([string]$FilePath) { if (-not (Test-Path -LiteralPath $FilePath)) { return '' } foreach ($raw in Get-Content -LiteralPath $FilePath) { $line = $raw.Trim() if (-not $line -or $line.StartsWith('#') -or -not $line.Contains('=')) { continue } $parts = $line.Split('=', 2) if ($parts[0].Trim() -in @('NPM_TOKEN', 'NODE_AUTH_TOKEN')) { return $parts[1].Trim().Trim('"').Trim("'") } } return '' } $token = if ($env:NPM_TOKEN) { $env:NPM_TOKEN } elseif ($env:NODE_AUTH_TOKEN) { $env:NODE_AUTH_TOKEN } else { Read-LocalToken $SharedEnvPath } if (-not $token) { throw 'npm token is not configured in the local release environment.' } $npmrc = Join-Path $env:TEMP ('fmode-qiwei-' + [guid]::NewGuid().ToString('N') + '.npmrc') try { Set-Content -LiteralPath $npmrc -Value "//registry.npmjs.org/:_authToken=$token" -Encoding ascii $env:NPM_CONFIG_USERCONFIG = $npmrc $account = npm whoami --registry=https://registry.npmjs.org/ if ($LASTEXITCODE -ne 0) { throw 'npm authentication check failed.' } Write-Host "[auth] npm account: $account" if ($AuthOnly) { return } if (-not $Tarball) { throw 'Tarball is required unless -AuthOnly is used.' } $resolvedTarball = Resolve-Path -LiteralPath $Tarball npm publish $resolvedTarball --access public --registry=https://registry.npmjs.org/ if ($LASTEXITCODE -ne 0) { throw 'npm publish failed.' } } finally { Remove-Item Env:NPM_CONFIG_USERCONFIG -ErrorAction SilentlyContinue Remove-Item -LiteralPath $npmrc -Force -ErrorAction SilentlyContinue $token = $null }