<# .SYNOPSIS Przygotowuje pierwszy projekt (lekcja PROJEKT) po stronie operatora Windows: git init w folderze projektu, ustawienia .env panelu oraz projects_registry.json. .DESCRIPTION Uruchamiaj Z KATALOGU INSTALACJI Gema0 lub podaj parametr -Gema0Root. Nie ustawiamy GEMINI_API_KEY - uzupelnij recznie w gema0\.env jesli pusto. .PARAMETER ProjectRoot Folder workspace (tam .gema0 i kod). Domyślnie C:\xampp\htdocs\PROJEKT .PARAMETER Gema0Root Folder z package.json Gema0. Domyślnie: folder nadrzędny do tools\ .PARAMETER Port PORT panelu (domyślnie 7878). Ustawia też panel_base_url w registry. .PARAMETER SkipGitInit Nie wywołuj git init. .PARAMETER SkipRegistry Nie zapisuj backend\config\projects_registry.json. .PARAMETER SkipEnv Nie modyfikuj .env. .PARAMETER DryRun Tylko wypisz co zostałoby zrobione. #> param( [string]$ProjectRoot = "C:\xampp\htdocs\PROJEKT", [string]$Gema0Root = "", [int]$Port = 7878, [switch]$SkipGitInit, [switch]$SkipRegistry, [switch]$SkipEnv, [switch]$DryRun ) $ErrorActionPreference = "Stop" if (-not $Gema0Root) { $Gema0Root = Split-Path -Parent $PSScriptRoot } $Gema0Root = [System.IO.Path]::GetFullPath($Gema0Root) $ProjectRoot = [System.IO.Path]::GetFullPath($ProjectRoot) $notesDir = [System.IO.Path]::GetFullPath((Join-Path $ProjectRoot ".gema0")) function To-JsonSlash([string]$p) { return ($p -replace "\\", "/") } function Write-Utf8NoBom([string]$path, [string[]]$lines) { $enc = New-Object System.Text.UTF8Encoding $false [System.IO.File]::WriteAllLines($path, $lines, $enc) } function Remove-EnvLines([string]$path, [string[]]$keys) { if (-not (Test-Path $path)) { return @() } $alt = ($keys | ForEach-Object { [regex]::Escape($_) }) -join "|" $pattern = "^\s*($alt)\s*=" return Get-Content -LiteralPath $path -ErrorAction SilentlyContinue | Where-Object { $_ -notmatch $pattern } } Write-Host "[GEMA-0] setup-first-project (Windows)" Write-Host " Gema0Root: $Gema0Root" Write-Host " ProjectRoot: $ProjectRoot" Write-Host " notes (.gema0): $notesDir" Write-Host " Port: $Port" if (-not $SkipGitInit) { $gitDir = Join-Path $ProjectRoot ".git" if (-not (Test-Path $gitDir)) { Write-Host "[GEMA-0] git init -> $ProjectRoot" if (-not $DryRun) { Push-Location $ProjectRoot try { & git init if ($LASTEXITCODE -ne 0) { throw "git init zwrócił kod $LASTEXITCODE" } } finally { Pop-Location } } } else { Write-Host "[GEMA-0] .git juz istnieje - pomijam git init." } } else { Write-Host "[GEMA-0] SkipGitInit - bez git init." } $venvPy = Join-Path $Gema0Root "rpa_workers\venv\Scripts\python.exe" if (-not (Test-Path $venvPy)) { Write-Warning "Brak $venvPy - uruchom wczesniej: powershell -File tools\install.ps1" } else { Write-Host "[GEMA-0] PYTHON_EXE -> $venvPy" } if (-not $SkipEnv) { $envPath = Join-Path $Gema0Root ".env" $keys = @( "GEMA0_NOTES_DIR", "GEMA0_GIT_ROOT", "GEMA0_PROJECTS_REGISTRY", "GEMA0_ORCHESTRATE_WRITE_NEXT_10", "GEMA0_ORCHESTRATE_MEGA_STEP", "PYTHON_EXE", "PORT", "GEMINI_MODEL", "LOG_LEVEL" ) if (-not (Test-Path $envPath)) { $ex = Join-Path $Gema0Root ".env.example" if (Test-Path $ex) { Write-Host "[GEMA-0] Tworzę .env z szablonu .env.example" if (-not $DryRun) { Copy-Item -LiteralPath $ex -Destination $envPath } } } $merged = @(Remove-EnvLines $envPath $keys) $regOut = Join-Path $Gema0Root "backend\config\projects_registry.json" $merged += "GEMA0_NOTES_DIR=$notesDir" $merged += "GEMA0_GIT_ROOT=$ProjectRoot" $merged += "GEMA0_PROJECTS_REGISTRY=$regOut" $merged += "GEMA0_ORCHESTRATE_WRITE_NEXT_10=true" $merged += "GEMA0_ORCHESTRATE_MEGA_STEP=false" $merged += "PYTHON_EXE=$venvPy" $merged += "PORT=$Port" $merged += "GEMINI_MODEL=gemini-3-flash-preview" $merged += "LOG_LEVEL=info" Write-Host "[GEMA-0] Aktualizuję .env (klucze projektu + PYTHON; GEMINI_API_KEY zostaje jak jest)." if (-not $DryRun) { Write-Utf8NoBom $envPath $merged } } else { Write-Host "[GEMA-0] SkipEnv - .env bez zmian." } if (-not $SkipRegistry) { $template = Join-Path $Gema0Root "backend\config\projects_registry.PROJEKT.template.json" $out = Join-Path $Gema0Root "backend\config\projects_registry.json" if (-not (Test-Path $template)) { throw "Brak szablonu: $template" } $raw = Get-Content -LiteralPath $template -Raw -Encoding UTF8 | ConvertFrom-Json $raw.panel_base_url = "http://127.0.0.1:$Port" $raw.projects[0].notes_dir = (To-JsonSlash $notesDir) $raw.projects[0].git_root = (To-JsonSlash $ProjectRoot) $json = $raw | ConvertTo-Json -Depth 10 Write-Host "[GEMA-0] Zapisuję $out" if (-not $DryRun) { Write-Utf8NoBom $out @($json) } } else { Write-Host "[GEMA-0] SkipRegistry - rejestr bez zmian." } Write-Host "" Write-Host "[GEMA-0] Gotowe." if (-not $DryRun) { $envCheck = Join-Path $Gema0Root ".env" $hasKey = $false if (Test-Path $envCheck) { $hasKey = Select-String -LiteralPath $envCheck -Pattern "^\s*GEMINI_API_KEY\s*=\s*\S+" -Quiet } if (-not $hasKey) { Write-Host (' (*) Uzupelnij GEMINI_API_KEY w: ' + $envCheck) } Write-Host (' (*) Panel: w cmd/powershell wpisz: cd /d "' + $Gema0Root + '" potem w tym samym oknie: npm start') Write-Host (' (*) Supervisor: drugi terminal, ten sam folder co wyzej, potem: npm run supervisor:loop') }