118 lines
3.7 KiB
PowerShell
118 lines
3.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Releases the AI lock without uploading data.
|
|
Reads the lock token from <repo-root>/work/kai-bundle.json by default.
|
|
|
|
.PARAMETER LockToken
|
|
Override lock token directly.
|
|
|
|
.PARAMETER BundleFile
|
|
Override bundle file to read token from.
|
|
|
|
.PARAMETER Prod
|
|
Target production server.
|
|
|
|
.PARAMETER Token
|
|
Bearer token for prod auth. Falls back to $env:KA_NOTE_TOKEN.
|
|
|
|
.EXAMPLE
|
|
.\unlock.ps1
|
|
.\unlock.ps1 -LockToken "abc-123"
|
|
.\unlock.ps1 -Prod -Token eyJ...
|
|
#>
|
|
param(
|
|
[string]$LockToken,
|
|
[string]$BundleFile,
|
|
[switch]$Prod,
|
|
[string]$Token
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# --- Helpers -----------------------------------------------------------------
|
|
|
|
function Write-Header([string]$Text) {
|
|
Write-Host ""
|
|
Write-Host " $Text" -ForegroundColor White
|
|
Write-Host (" " + ("-" * $Text.Length)) -ForegroundColor DarkGray
|
|
}
|
|
|
|
function Write-KV([string]$Key, [string]$Value, [string]$Color = "Gray") {
|
|
Write-Host (" {0,-14} " -f $Key) -NoNewline -ForegroundColor DarkGray
|
|
Write-Host $Value -ForegroundColor $Color
|
|
}
|
|
|
|
function Write-Ok([string]$Msg) { Write-Host " [OK] $Msg" -ForegroundColor Green }
|
|
function Write-Warn([string]$Msg) { Write-Host " [!!] $Msg" -ForegroundColor Yellow }
|
|
function Write-Err([string]$Msg) { Write-Host " [!!] $Msg" -ForegroundColor Red }
|
|
function Write-Hint([string]$Msg) { Write-Host " -> $Msg" -ForegroundColor DarkCyan }
|
|
|
|
# --- Resolve lock token ------------------------------------------------------
|
|
|
|
$RepoRoot = Resolve-Path "$PSScriptRoot\..\.."
|
|
$WorkDir = Join-Path $RepoRoot "work"
|
|
# Support legacy BundleFile param and new manifest.json
|
|
if (-not $BundleFile) { $BundleFile = Join-Path $WorkDir "manifest.json" }
|
|
|
|
if (-not $LockToken) {
|
|
if (Test-Path $BundleFile) {
|
|
$BundleContent = Get-Content $BundleFile -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
# manifest.json has lockToken directly; legacy kai-bundle.json has manifest.lockToken
|
|
$LockToken = if ($BundleContent.lockToken) { $BundleContent.lockToken } else { $BundleContent.manifest.lockToken }
|
|
$TokenSource = $BundleFile
|
|
}
|
|
if (-not $LockToken) {
|
|
Write-Err "No lock token found. Pass -LockToken or run .\download.ps1 first."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# --- Server ------------------------------------------------------------------
|
|
|
|
if ($Prod) {
|
|
$BaseUrl = "https://ka-note.azurewebsites.net"
|
|
$BearerToken = if ($Token) { $Token } elseif ($env:KA_NOTE_TOKEN) { $env:KA_NOTE_TOKEN } else {
|
|
Write-Host " Acquiring token via MSAL..." -ForegroundColor DarkGray
|
|
& "$PSScriptRoot\get-token.ps1"
|
|
}
|
|
if (-not $BearerToken) {
|
|
Write-Err "Failed to acquire a Bearer token."
|
|
exit 1
|
|
}
|
|
$Headers = @{ Authorization = "Bearer $BearerToken"; "Content-Type" = "application/json" }
|
|
$Env = "prod"
|
|
} else {
|
|
$BaseUrl = "http://localhost:3001"
|
|
$Headers = @{ "Content-Type" = "application/json" }
|
|
$Env = "dev"
|
|
}
|
|
|
|
Write-Header "Ka-Note AI Unlock"
|
|
Write-KV "server" $BaseUrl $(if ($Prod) { "Yellow" } else { "Cyan" })
|
|
Write-KV "mode" $Env
|
|
Write-KV "lock" $LockToken "Yellow"
|
|
if ($TokenSource) { Write-KV "from" $TokenSource }
|
|
Write-Host ""
|
|
Write-Host " Unlocking..." -ForegroundColor DarkGray
|
|
|
|
$Json = @{ lockToken = $LockToken } | ConvertTo-Json -Compress
|
|
|
|
try {
|
|
Invoke-WebRequest -Uri "$BaseUrl/api/ai/unlock" `
|
|
-Method POST -Headers $Headers -Body $Json -UseBasicParsing | Out-Null
|
|
|
|
Write-Host ""
|
|
Write-Ok "Lock released. Sync is active again."
|
|
Write-Host ""
|
|
} catch {
|
|
$StatusCode = $_.Exception.Response.StatusCode.value__
|
|
Write-Host ""
|
|
if ($StatusCode -eq 401) {
|
|
Write-Warn "401 — lock token invalid or already expired (lock may have auto-expired)."
|
|
} else {
|
|
Write-Err "HTTP $StatusCode — $($_.Exception.Message)"
|
|
exit 1
|
|
}
|
|
Write-Host ""
|
|
}
|