<# .SYNOPSIS Downloads the AI workspace ZIP from Ka-Note and extracts it to work/. .PARAMETER Prod Target production server instead of dev (localhost:3001). .PARAMETER Token Bearer token for prod auth. Falls back to $env:KA_NOTE_TOKEN. .PARAMETER Force Skip the work-directory cleanup confirmation prompt. .EXAMPLE .\download.ps1 .\download.ps1 -Prod -Token eyJ... .\download.ps1 -Force #> param( [switch]$Prod, [string]$Token, [switch]$Force ) $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-Err([string]$Msg) { Write-Host " [!!] $Msg" -ForegroundColor Red } function Write-Hint([string]$Msg) { Write-Host " -> $Msg" -ForegroundColor DarkCyan } # --- Paths ------------------------------------------------------------------- $RepoRoot = Resolve-Path "$PSScriptRoot\..\.." $WorkDir = Join-Path $RepoRoot "work" $ZipPath = Join-Path $WorkDir "workspace.zip" # --- Clean work directory ---------------------------------------------------- Write-Header "Ka-Note AI Download" if (Test-Path $WorkDir) { $ExistingItems = @(Get-ChildItem -Path $WorkDir) if ($ExistingItems.Count -gt 0) { Write-KV "work dir" $WorkDir Write-Host "" Write-Host " The work directory contains $($ExistingItems.Count) item(s)." -ForegroundColor DarkGray Write-Host "" if (-not $Force) { $Answer = Read-Host " Delete all contents and proceed? [y/N]" if ($Answer -notmatch '^[yY]$') { Write-Host " Aborted." -ForegroundColor Yellow Write-Host "" exit 0 } } Remove-Item -Path "$WorkDir\*" -Recurse -Force Write-Ok "Work directory cleared." } } else { New-Item -ItemType Directory -Path $WorkDir | Out-Null Write-Ok "Created work directory: $WorkDir" } # --- 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" } $Env = "prod" } else { $BaseUrl = "http://localhost:3001" $Headers = @{} $Env = "dev" } Write-KV "server" $BaseUrl $(if ($Prod) { "Yellow" } else { "Cyan" }) Write-KV "mode" $Env Write-KV "work" $WorkDir Write-Host "" Write-Host " Downloading workspace.zip..." -ForegroundColor DarkGray # --- Download ---------------------------------------------------------------- try { Invoke-WebRequest -Uri "$BaseUrl/api/ai/download" ` -Method GET -Headers $Headers -OutFile $ZipPath -UseBasicParsing } catch { $Code = $_.Exception.Response.StatusCode.value__ Write-Err "HTTP $Code - $($_.Exception.Message)" exit 1 } $LockToken = $null # Lock token also in ZIP manifest (read after extract) # --- Extract ----------------------------------------------------------------- Write-Host " Extracting..." -ForegroundColor DarkGray Expand-Archive -Path $ZipPath -DestinationPath $WorkDir -Force Remove-Item -Path $ZipPath -Force # --- Stats ------------------------------------------------------------------- $ManifestPath = Join-Path $WorkDir "manifest.json" $Manifest = Get-Content $ManifestPath -Raw -Encoding UTF8 | ConvertFrom-Json $LockToken = $Manifest.lockToken $HistoryCount = @(Get-ChildItem -Path (Join-Path $WorkDir "history") -Filter "*.md" -ErrorAction SilentlyContinue).Count $ImageCount = @(Get-ChildItem -Path (Join-Path $WorkDir "images") -ErrorAction SilentlyContinue).Count $CtxJson = Get-Content (Join-Path $WorkDir "contexts.json") -Raw -Encoding UTF8 | ConvertFrom-Json $TopJson = Get-Content (Join-Path $WorkDir "topics.json") -Raw -Encoding UTF8 | ConvertFrom-Json $RatJson = Get-Content (Join-Path $WorkDir "ratings.json") -Raw -Encoding UTF8 | ConvertFrom-Json Write-Header "Result" Write-KV "contexts" @($CtxJson).Count Write-KV "topics" @($TopJson).Count Write-KV "history" $HistoryCount Write-KV "ratings" @($RatJson).Count Write-KV "images" $ImageCount Write-KV "lock" $LockToken "Yellow" Write-KV "expires" $Manifest.expiresAt Write-Host "" Write-Ok "Workspace extracted to work/. Lock acquired - sync is paused." Write-Host "" Write-Host " Next steps:" -ForegroundColor DarkGray Write-Hint "Edit work/history/*.md with your AI tool" Write-Hint ".\upload.ps1$(if ($Prod) { ' -Prod' }) - upload changes + release lock" Write-Hint ".\unlock.ps1$(if ($Prod) { ' -Prod' }) - discard changes, release lock only" Write-Host ""