Repository navigation
Expand file tree
/
Copy pathsetup.ps1
More file actions
803 lines (724 loc) · 39.6 KB
/
Copy pathsetup.ps1
File metadata and controls
803 lines (724 loc) · 39.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
# setup.ps1 - Automated installation and setup script for the Wizard-AI environment.
# Supported Platform: Windows 10/11 (x86_64) - native PowerShell port of setup.sh
#
# Usage: powershell -ExecutionPolicy Bypass -File setup.ps1
#
# After installation, the WIZARD_AI_DIR user environment variable is available
# and points to the directory where you cloned this repository.
#
# Requirements: git on PATH. Everything else (uv, Python venv, tools) is
# installed automatically.
param (
[switch]$VerboseMode
)
# -------------------------------------------------------------
# Detailed Logging System (Human & LLM / JSON)
# -------------------------------------------------------------
$GlobalLogFile = Join-Path $HOME '.wizard-ai\setup.log'
$GlobalJsonLog = Join-Path $HOME '.wizard-ai\setup.json'
function Write-Log {
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]
[string]$Message,
[ConsoleColor]$ForegroundColor = 'Gray',
[switch]$NoNewline
)
$Timestamp = (Get-Date).ToString('o')
$CleanMessage = $Message -replace '\e\[[0-9;]*m', '' # Remove ANSI
# JSON Log
$LogEntry = @{
timestamp = $Timestamp
level = 'INFO'
message = $CleanMessage
}
$JsonString = $LogEntry | ConvertTo-Json -Compress
Add-Content -Path $GlobalJsonLog -Value $JsonString
# Text Log
Add-Content -Path $GlobalLogFile -Value "[$Timestamp] $CleanMessage"
# Console Output
if ($NoNewline) {
Write-Host $Message -ForegroundColor $ForegroundColor -NoNewline
} else {
Write-Host $Message -ForegroundColor $ForegroundColor
}
}
# -------------------------------------------------------------
# PowerShell security hardening: Enforce TLS 1.2 and TLS 1.3 explicitly
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
$QuietOpt = '--quiet'
if ($VerboseMode) {
$QuietOpt = ''
$VerbosePreference = 'Continue'
$DebugPreference = 'Continue'
}
Write-Log '============================================================' -ForegroundColor Cyan
Write-Log ' Wizard-AI Environment Setup Wizard (Windows)' -ForegroundColor Cyan
Write-Log '============================================================' -ForegroundColor Cyan
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Log '[X] git not found on PATH. Install Git for Windows first: https://git-scm.com/download/win' -ForegroundColor Red
exit 1
}
# Resolve the absolute path of this script (= repo root)
$ScriptDir = $PSScriptRoot
$LocalBin = Join-Path $HOME '.local\bin'
$AiSkills = Join-Path $HOME '.wizard-ai'
# 0. Save WIZARD_AI_DIR so skills and wrappers can reference the repo portably
Write-Log '[7.8/8] Configuring Compression Tools and MCP...' -ForegroundColor Blue
try { python (Join-Path $ScriptDir 'scripts\install-compression-mcp.py') } catch {}
Write-Log ' '
Write-Log '[0/8] Registering Wizard-AI installation path...' -ForegroundColor Blue
$ConfigDir = Join-Path $HOME '.config\wizard-ai'
$null = New-Item -ItemType Directory -Force -Path $ConfigDir
$EnvFile = Join-Path $ConfigDir 'env.ps1'
$Stamp = Get-Date -Format 'yyyy-MM-dd'
@"
# Wizard-AI environment - auto-generated by setup.ps1 on $Stamp
# Do not edit manually; re-run setup.ps1 to update.
`$env:WIZARD_AI_DIR = '$ScriptDir'
if (`$env:Path -notlike "*$LocalBin*") { `$env:Path = "$LocalBin;`$(`$env:Path)" }
"@ | Set-Content -Path $EnvFile -Encoding utf8
# Persist as user environment variables (the Windows equivalent of ~/.bashrc)
[Environment]::SetEnvironmentVariable('WIZARD_AI_DIR', $ScriptDir, 'User')
$UserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
if (-not $UserPath) { $UserPath = '' }
if ($UserPath -notlike "*$LocalBin*") {
[Environment]::SetEnvironmentVariable('Path', "$LocalBin;$UserPath", 'User')
Write-Log " [ok] Added $LocalBin to your user PATH" -ForegroundColor Green
}
# Export for the current session
$env:WIZARD_AI_DIR = $ScriptDir
if ($env:Path -notlike "*$LocalBin*") { $env:Path = "$LocalBin;$($env:Path)" }
Write-Log "[ok] WIZARD_AI_DIR=`"$ScriptDir`"" -ForegroundColor Green
# 1. Check/Install UV
Write-Log ' '
Write-Log '[1/8] Checking for modern Python & Package Manager (uv)...' -ForegroundColor Blue
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
Write-Log 'uv not found. Installing uv via official script...' -ForegroundColor Yellow
# SECURITY: Executing scripts directly from the internet via pipe is a security risk.
# Ideally, download the script, verify its hash/signature, and then execute it.
Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
Write-Log '[X] uv installation failed. Install manually: https://docs.astral.sh/uv/' -ForegroundColor Red
exit 1
}
}
else {
Write-Log "[ok] uv is already installed: $(uv --version)" -ForegroundColor Green
}
# Ensure local directories exist
$null = New-Item -ItemType Directory -Force -Path $LocalBin
$null = New-Item -ItemType Directory -Force -Path $AiSkills
# Optional: Install native Unix tools for Windows (ls, cp, grep, etc.)
Write-Log 'Checking for Microsoft.Coreutils...' -ForegroundColor Yellow
if (-not (Get-Command ls -ErrorAction SilentlyContinue | Where-Object { $_.Source -match "coreutils" })) {
Write-Log ' > Command: winget install Microsoft.Coreutils --accept-package-agreements --accept-source-agreements --verbose-logs' -ForegroundColor DarkGray
Write-Log ' > Note: If this hangs, check for hidden UAC prompts in your taskbar, or press Enter.' -ForegroundColor DarkGray
winget install Microsoft.Coreutils --accept-package-agreements --accept-source-agreements --verbose-logs
Write-Log ' > winget command finished.' -ForegroundColor DarkGray
}
else {
Write-Log '[ok] Microsoft.Coreutils is already installed.' -ForegroundColor Green
}
# Ensure MSVC C++ Build Tools are installed for headroom-ai compilation
Write-Log 'Checking for MSVC C++ Build Tools...' -ForegroundColor Yellow
$VsWherePath = 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
$HasMsvc = $false
if (Test-Path $VsWherePath) {
$MsvcCheck = & $VsWherePath -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if ($MsvcCheck) { $HasMsvc = $true }
}
if (-not $HasMsvc) {
Write-Log 'MSVC C++ Build Tools not found. Installing via winget (this may take a few minutes)...' -ForegroundColor Yellow
Write-Log ' > Note: A UAC prompt may appear in the background for Visual Studio Installer. Please accept it.' -ForegroundColor Yellow
$VsOverride = '--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended'
Write-Log " > Command: winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --force --accept-package-agreements --accept-source-agreements --override `"$VsOverride`" --verbose-logs" -ForegroundColor DarkGray
winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --force --accept-package-agreements --accept-source-agreements --override $VsOverride --verbose-logs
Write-Log ' > winget command finished.' -ForegroundColor DarkGray
Write-Log '[ok] MSVC C++ Build Tools installed.' -ForegroundColor Green
} else {
Write-Log '[ok] MSVC C++ Build Tools are already installed.' -ForegroundColor Green
}
# 2. Recreate Python Virtual Environment for wrappers
Write-Log ' '
Write-Log '[2/8] Preparing Python Virtual Environment for LLMLingua & FlashRank...' -ForegroundColor Blue
$VenvDir = Join-Path $AiSkills 'venv'
if ($QuietOpt) { uv venv $VenvDir --python 3.12 --seed --quiet } else { uv venv $VenvDir --python 3.12 --seed }
$VenvPython = Join-Path $VenvDir 'Scripts\python.exe'
Write-Log 'Installing llmlingua, flashrank, turbovec and zvec inside the venv (this can take a while)...' -ForegroundColor Yellow
if ($QuietOpt) { uv pip install --quiet --python $VenvPython llmlingua flashrank aisuite turbovec zvec litellm numpy qwenpaw repodocs } else { uv pip install --python $VenvPython llmlingua flashrank aisuite turbovec zvec litellm numpy qwenpaw repodocs }
Write-Log "[ok] Virtual environment ready at $VenvDir" -ForegroundColor Green
# 3. Setting up external git skill & framework repositories (Interactive Selector)
# -------------------------------------------------------------------------------
# Reads from scripts/repo-registry.json - single source of truth for all repos.
# Inspired by caveman installer UX: numbered categories, selectable items.
# -------------------------------------------------------------------------------
Write-Log ' '
Write-Log '[3/8] Setting up external git skill & framework repositories...' -ForegroundColor Blue
$RegistryFile = Join-Path $ScriptDir 'scripts\repo-registry.json'
if (-not (Test-Path $RegistryFile)) {
Write-Log "[ERROR] Missing repo-registry.json at $RegistryFile" -ForegroundColor Red
exit 1
}
$Registry = Get-Content $RegistryFile -Raw | ConvertFrom-Json
# Build flat list and category summary
$AllItems = @()
$CategoryList = @()
foreach ($catKey in $Registry.categories.PSObject.Properties.Name) {
$cat = $Registry.categories.$catKey
$CategoryList += [PSCustomObject]@{
Key = $catKey
Name = $cat.name
Badge = $cat.badge
Description = $cat.description
Count = $cat.repos.Count
}
foreach ($repo in $cat.repos) {
$AllItems += [PSCustomObject]@{
CatKey = $catKey
CatName = $cat.name
Badge = $cat.badge
Name = $repo.name
Url = $repo.url
Desc = $repo.desc
}
}
}
$TotalRepos = $AllItems.Count
# Install counters
$script:SkillRepoIndex = 0
$script:SkillRepoTotal = 0
$script:InstallOK = 0
$script:InstallSkip = 0
$script:InstallFail = 0
$script:FailedRepos = @()
function Clone-SkillRepo {
param([string]$Url, [string]$DestName, [string]$Badge = '')
$script:SkillRepoIndex++
$DestDir = Join-Path $AiSkills $DestName
$badgeStr = if ($Badge) { " $Badge" } else { '' }
Write-Log "[3/8] [$($script:SkillRepoIndex)/$($script:SkillRepoTotal)] $DestName$badgeStr" -ForegroundColor White
if (-not (Test-Path $DestDir)) {
Write-Log " > Cloning $DestName from $Url..." -ForegroundColor Yellow
if ($VerboseMode) {
git clone --recurse-submodules --shallow-submodules --depth 1 --single-branch --no-tags $Url $DestDir
} else {
git clone --recurse-submodules --shallow-submodules --depth 1 --single-branch --no-tags --quiet $Url $DestDir *>&1 | Out-Null
}
if ($LASTEXITCODE -ne 0) {
$script:InstallFail++
$script:FailedRepos += $DestName
Write-Log " [X] Clone failed for $DestName" -ForegroundColor Red
return
}
Write-Log " [ok] $DestName cloned." -ForegroundColor Green
$script:InstallOK++
} else {
Write-Log " [ok] $DestName is already present." -ForegroundColor Green
$script:InstallSkip++
}
# Auto-install framework / skill dependencies
if (Test-Path $DestDir) {
$InstallPs1 = Join-Path $DestDir 'install.ps1'
$SetupPs1 = Join-Path $DestDir 'setup.ps1'
$InstallJs = Join-Path $DestDir 'bin\install.js'
$PyProj = Join-Path $DestDir 'pyproject.toml'
$SetupPy = Join-Path $DestDir 'setup.py'
$PkgJson = Join-Path $DestDir 'package.json'
if (Test-Path $InstallPs1) {
Write-Log " > Running install.ps1 for $DestName..." -ForegroundColor Cyan
try { & $InstallPs1 } catch {}
} elseif ((Test-Path $SetupPs1) -and ($SetupPs1 -ne (Join-Path $ScriptDir 'setup.ps1'))) {
Write-Log " > Running setup.ps1 for $DestName..." -ForegroundColor Cyan
try { & $SetupPs1 } catch {}
} elseif (Test-Path $InstallJs) {
Write-Log " > Running bin\install.js for $DestName..." -ForegroundColor Cyan
try { $env:GITHUB_TOKEN=''; node $InstallJs --all --non-interactive } catch {}
} elseif ((Test-Path $PyProj) -or (Test-Path $SetupPy)) {
Write-Log " > Building Python package for $DestName..." -ForegroundColor Cyan
if ($VerboseMode) {
try { uv pip install --python $VenvPython -e $DestDir } catch {}
} else {
try { $null = uv pip install --python $VenvPython -e $DestDir 2>&1 } catch {}
}
} elseif (Test-Path $PkgJson) {
Write-Log " > Installing npm packages for $DestName..." -ForegroundColor Cyan
if ($VerboseMode) {
try { npm install --prefix $DestDir --no-audit --no-fund } catch {}
} else {
try { $null = npm install --prefix $DestDir --no-audit --no-fund 2>&1 } catch {}
}
}
}
}
# -- Determine if interactive --
$IsNonInteractive = $false
foreach ($a in $args) { if ($a -match '(?i)^(-y|--yes|--all)$') { $IsNonInteractive = $true } }
if (-not [Environment]::UserInteractive) { $IsNonInteractive = $true }
$SelectedItems = @()
if ($IsNonInteractive) {
Write-Log "Installing all $TotalRepos repositories (non-interactive mode)..." -ForegroundColor Yellow
$SelectedItems = $AllItems
} else {
# -- Interactive menu via Node.js (@clack/prompts) --
if (Get-Command npm -ErrorAction SilentlyContinue) {
if ($VerboseMode) {
npm install --prefix "$ScriptDir" --no-audit --no-fund
} else {
npm install --prefix "$ScriptDir" --no-audit --no-fund --quiet *>&1 | Out-Null
}
}
$TmpSel = [System.IO.Path]::GetTempFileName()
node "$ScriptDir\scripts\interactive-selector.js" $TmpSel
$SelectedReposText = Get-Content $TmpSel -Raw -ErrorAction SilentlyContinue
Remove-Item $TmpSel -Force -ErrorAction SilentlyContinue
$SelectedItems = @()
if ($SelectedReposText -and $SelectedReposText.Trim() -ne '') {
$lines = $SelectedReposText -split "`n"
foreach ($line in $lines) {
$line = $line.Trim()
if ($line -eq '') { continue }
$parts = $line -split '\|'
if ($parts.Count -ge 6) {
$SelectedItems += [PSCustomObject]@{
CatKey = $parts[0]
CatName = $parts[1]
Badge = $parts[2]
Name = $parts[3]
Url = $parts[4]
Desc = $parts[5]
}
}
}
}
}
# -- Execute installation for selected repos ---------------------------------
$script:SkillRepoTotal = $SelectedItems.Count
if ($SelectedItems.Count -gt 0) {
Write-Log ' ' -ForegroundColor White
Write-Log "Installing $($SelectedItems.Count) selected repositories..." -ForegroundColor Green
Write-Log ' ' -ForegroundColor White
foreach ($item in $SelectedItems) {
Clone-SkillRepo -Url $item.Url -DestName $item.Name -Badge $item.Badge
}
# Special wslens handler (Windows-specific)
if ($SelectedItems | Where-Object { $_.Name -eq 'wslens' }) {
$WslensInstall = Join-Path $AiSkills 'wslens\install.ps1'
if (Test-Path $WslensInstall) {
Write-Log 'Installing wslens backend...' -ForegroundColor Yellow
$OldDir = Get-Location
Set-Location (Join-Path $AiSkills 'wslens')
& .\install.ps1
Set-Location $OldDir
$WslensWrapper = Join-Path $LocalBin 'wz-ai-wslens.ps1'
"<#`n.SYNOPSIS`nWrapper for wslens`n#>`nif (`$args.Count -eq 0) { wslens } else { wslens @args }" | Set-Content -Path $WslensWrapper -Encoding utf8
}
}
} else {
Write-Log 'No repositories selected for installation.' -ForegroundColor Yellow
}
# -- Post-install: optional NPM global packages -----------------------------
$selectedNames = $SelectedItems | ForEach-Object { $_.Name }
if (($selectedNames -contains 'ECC') -or ($selectedNames -contains 'caveman') -or ($selectedNames -contains 'design.md')) {
if (Get-Command npm -ErrorAction SilentlyContinue) {
Write-Log 'Running post-install hooks for special packages...' -ForegroundColor Blue
if ($selectedNames -contains 'ECC') {
try { npm install -g ecc-universal 2>$null } catch { Write-Log 'Note: ecc-universal npm install skipped.' -ForegroundColor DarkGray }
}
if ($selectedNames -contains 'caveman') {
$cavemanJs = Join-Path $AiSkills 'caveman\bin\install.js'
if (Test-Path $cavemanJs) {
# Patch invalid tool names for Gemini
Get-ChildItem -Path "$DestDir\agents" -Filter "cavecrew-*.md" -File -ErrorAction SilentlyContinue | ForEach-Object { $c = Get-Content $_.FullName -Raw; $c = $c -replace "(?m)^tools:(.*)", { "tools:" + $args[0].Groups[1].Value.ToLower().Replace("-", "_") }; Set-Content -Path $_.FullName -Value $c -NoNewline }
Write-Log ' > Running caveman installer...' -ForegroundColor Cyan
try { $env:GITHUB_TOKEN=''; node $cavemanJs --all --non-interactive } catch {}
}
}
if ($selectedNames -contains 'design.md') {
try { npm install -g @google/design.md 2>$null } catch { Write-Log 'Note: @google/design.md npm install skipped.' -ForegroundColor DarkGray }
}
}
}
# lean-ctx (always install if skipped from registry)
Clone-SkillRepo -Url 'https://github.com/yvgude/lean-ctx.git' -DestName 'lean-ctx' -Badge '[CLI TOOL]'
# -- Installation Summary ----------------------------------------------------
if ($SelectedItems.Count -gt 0) {
Write-Host ''
Write-Host ' --------------------------------------------------------' -ForegroundColor Cyan
Write-Log " Repository Installation Summary:" -ForegroundColor White
Write-Host ' --------------------------------------------------------' -ForegroundColor Cyan
Write-Log " [ok] Installed: $($script:InstallOK) new" -ForegroundColor Green
Write-Log " [>>] Skipped: $($script:InstallSkip) (already present)" -ForegroundColor Blue
if ($script:InstallFail -gt 0) {
Write-Log " [X] Failed: $($script:InstallFail) ($($script:FailedRepos -join ', '))" -ForegroundColor Red
}
Write-Host ' --------------------------------------------------------' -ForegroundColor Cyan
}
# 4. Install UV Global Tools
Write-Log ' '
Write-Log '[4/8] Installing global CLI Tools via uv tool...' -ForegroundColor Blue
function Install-UvTool($Tool, $Pkg) {
if (-not $Pkg) { $Pkg = $Tool }
Write-Log "Installing/Updating $Tool..." -ForegroundColor Yellow
# Run uv tool install and capture stderr
$err = $(uv tool install --force $Pkg 2>&1)
if ($LASTEXITCODE -eq 0) {
Write-Log " [ok] $Tool installed." -ForegroundColor Green
} else {
if ($Tool -eq 'headroom') {
Write-Log " [!] Failed to install $Tool (MSVC C++ Build Tools required). Skipping headroom setup, proceeding with the rest..." -ForegroundColor Yellow
} else {
Write-Log " [!] Failed to install $Tool (exit code $LASTEXITCODE). You may need to install MSVC C++ Build Tools." -ForegroundColor Red
Write-Log " Details: $err" -ForegroundColor DarkGray
}
}
}
Install-UvTool 'graphify' 'graphifyy[all]'
Install-UvTool 'litellm' 'litellm[proxy]'
Install-UvTool 'markitdown'
Install-UvTool 'sqz'
Install-UvTool 'headroom' 'headroom-ai'
# Install serena (semantic code intelligence - available via uvx)
Write-Log 'Checking serena (semantic code search)...' -ForegroundColor Yellow
if (-not (Get-Command serena -ErrorAction SilentlyContinue)) {
uv tool install --force serena-agent | Out-Null
Write-Log ' [ok] serena installed.' -ForegroundColor Green
}
else {
Write-Log '[ok] serena already installed.' -ForegroundColor Green
}
# Install lightpanda (headless browser for agents) - no native Windows binary, requires WSL2
Write-Log 'Checking lightpanda (headless browser for agents)...' -ForegroundColor Yellow
if (Get-Command wsl -ErrorAction SilentlyContinue) {
Write-Log ' [i] lightpanda has no native Windows binary. Install inside WSL2 (run once):' -ForegroundColor Yellow
Write-Log ' wsl -e bash -lc "curl -fL -o ~/.local/bin/lightpanda https://github.com/lightpanda-io/browser/releases/download/nightly/lightpanda-x86_64-linux && chmod a+x ~/.local/bin/lightpanda"' -ForegroundColor Yellow
}
else {
Write-Log ' [!] lightpanda requires WSL2 on Windows (no native binary). Install WSL2 first: wsl --install' -ForegroundColor Yellow
}
# Install Open Code Review (ocr) - deterministic pipeline + LLM agent hybrid code review CLI
Write-Log 'Checking Open Code Review (ocr)...' -ForegroundColor Yellow
if (Get-Command ocr -ErrorAction SilentlyContinue) {
Write-Log ' [ok] ocr already installed.' -ForegroundColor Green
}
elseif (Get-Command npm -ErrorAction SilentlyContinue) {
try {
npm install -g '@alibaba-group/open-code-review' 2>$null
Write-Log ' [ok] ocr installed (@alibaba-group/open-code-review).' -ForegroundColor Green
}
catch {
Write-Log ' [!] failed to install ocr. Run manually: npm install -g @alibaba-group/open-code-review' -ForegroundColor Yellow
}
}
else {
Write-Log ' [!] ocr requires Node.js (npm). Skipped.' -ForegroundColor Yellow
}
if (Get-Command git -ErrorAction SilentlyContinue) {
try {
$OcrGitVer = [version](((git --version) -split ' ')[2] -replace '\.windows.*$', '')
if ($OcrGitVer -lt [version]'2.41.0') {
Write-Log " [!] ocr requires Git >= 2.41 (found $OcrGitVer). Upgrade Git or reviews will fail." -ForegroundColor Yellow
}
}
catch { Write-Log ' [i] Could not parse Git version - ocr requires Git >= 2.41.' -ForegroundColor DarkGray }
}
# Install blume (zero-config, AI-ready documentation site generator - drives a hidden Astro project)
Write-Log 'Checking blume (docs site generator)...' -ForegroundColor Yellow
if (Get-Command blume -ErrorAction SilentlyContinue) {
Write-Log ' [ok] blume already installed.' -ForegroundColor Green
}
elseif (Get-Command npm -ErrorAction SilentlyContinue) {
try {
npm install -g blume 2>$null
Write-Log ' [ok] blume installed.' -ForegroundColor Green
}
catch {
Write-Log ' [!] failed to install blume. Run manually: npm install -g blume' -ForegroundColor Yellow
}
}
else {
Write-Log ' [!] blume requires Node.js >= 22.12 (npm). Skipped.' -ForegroundColor Yellow
}
# 5. Fix sqz binary (pre-compiled native binary for token compression)
Write-Log ' '
Write-Log '[5/8] Placing pre-compiled sqz binary...' -ForegroundColor Blue
$SqzVer = ((Invoke-RestMethod -Uri 'https://api.github.com/repos/ojuschugh1/sqz/releases/latest' -UseBasicParsing -ErrorAction SilentlyContinue).tag_name)
if (-not $SqzVer) { $SqzVer = 'v1.3.0' }
$Arch = $env:PROCESSOR_ARCHITECTURE
if ($Arch -eq 'AMD64') {
$SqzUrl = "https://github.com/ojuschugh1/sqz/releases/download/$SqzVer/sqz-$SqzVer-x86_64-pc-windows-msvc.zip"
Write-Log "Fetching compiled sqz $SqzVer binary for x86_64..." -ForegroundColor Yellow
$TmpDir = Join-Path $env:TEMP ([guid]::NewGuid().ToString())
$null = New-Item -ItemType Directory -Force -Path $TmpDir
try {
# Security Hardening: UseBasicParsing prevents IE DOM parsing vulnerabilities
Invoke-WebRequest -Uri $SqzUrl -OutFile "$TmpDir\sqz.zip" -UseBasicParsing
Expand-Archive -Path (Join-Path $TmpDir 'sqz.zip') -DestinationPath $TmpDir -Force
$SqzExe = Get-ChildItem -Path $TmpDir -Recurse -Filter 'sqz.exe' | Select-Object -First 1
if ($SqzExe) {
# Verify executable runs before overwriting working installation
$IsWorking = $false
try {
& $SqzExe.FullName --help 2>&1 | Out-Null
$IsWorking = $true
} catch { $IsWorking = $false }
if (-not $IsWorking) {
Write-Log "[!] Downloaded sqz $SqzVer binary failed execution check. Keeping previous working installation." -ForegroundColor Yellow
} else {
# Try to place in uv tool site-packages first, fallback to ~\.local\bin
$PlacedInSitePackages = $false
$UvToolDir = (uv tool dir 2>$null).Trim()
if ($UvToolDir -and (Test-Path $UvToolDir)) {
$SqzToolDir = Join-Path $UvToolDir 'sqz'
if (Test-Path $SqzToolDir) {
$SitePackages = Get-ChildItem -Path $SqzToolDir -Recurse -Directory -Filter 'site-packages' -ErrorAction SilentlyContinue | Select-Object -First 1
if ($SitePackages) {
$BinDir = Join-Path $SitePackages.FullName 'sqz\_bin'
$null = New-Item -ItemType Directory -Force -Path $BinDir
Copy-Item -Path $SqzExe.FullName -Destination (Join-Path $BinDir 'sqz.exe') -Force
Copy-Item -Path $SqzExe.FullName -Destination (Join-Path $BinDir 'sqz') -Force
Write-Log "[ok] sqz $SqzVer binary placed safely in Python site-packages (x86_64)." -ForegroundColor Green
$PlacedInSitePackages = $true
}
}
}
if (-not $PlacedInSitePackages) {
Copy-Item -Path $SqzExe.FullName -Destination (Join-Path $LocalBin 'sqz.exe') -Force
Write-Log "[!] sqz $SqzVer binary placed safely in $LocalBin\sqz.exe (fallback)." -ForegroundColor Yellow
}
}
}
else {
Write-Log '[!] sqz.exe not found inside the release archive - keeping previous working version.' -ForegroundColor Yellow
}
}
catch {
Write-Log "[!] Could not download/extract sqz $SqzVer binary: $($_.Exception.Message). Keeping previous working version." -ForegroundColor Yellow
}
finally {
Remove-Item -Path $TmpDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
else {
Write-Log "[X] No pre-compiled sqz Windows binary for architecture '$Arch'. Compile sqz manually." -ForegroundColor Red
}
# 6. Copy and configure CLI Wrappers
Write-Log ' '
Write-Log "[6/8] Deploying custom AI CLI wrappers to $LocalBin..." -ForegroundColor Blue
$WrappersSrc = Join-Path $ScriptDir 'bin\windows'
# Security: Ensure paths are strictly within the project directory to prevent path traversal
$ResolvedSrc = Resolve-Path $WrappersSrc -ErrorAction SilentlyContinue
if (-not $ResolvedSrc -or -not $ResolvedSrc.Path.StartsWith($ScriptDir)) {
Write-Log "[X] Invalid wrappers source path. Potential path traversal detected." -ForegroundColor Red
exit 1
}
Copy-Item -Path (Join-Path $WrappersSrc '*.ps1') -Destination $LocalBin -Force
$null = New-Item -ItemType Directory -Force -Path (Join-Path $LocalBin 'lib')
Copy-Item -Path (Join-Path $WrappersSrc 'lib\*') -Destination (Join-Path $LocalBin 'lib') -Recurse -Force
# Generate .cmd shims so wrappers can be invoked as plain commands
# (e.g. "wz-ai") from cmd.exe, PowerShell, and other AI agents.
function New-CmdShim($CommandName, $Ps1Name) {
$ShimPath = Join-Path $LocalBin "$CommandName.cmd"
$Content = "@echo off`r`npowershell -NoProfile -ExecutionPolicy Bypass -File `"%~dp0$Ps1Name`" %*"
Set-Content -Path $ShimPath -Value $Content -Encoding Ascii
}
# Only create the main dispatcher shim to prevent PATH pollution
New-CmdShim 'wz-ai' 'wz-ai.ps1'
Write-Log "[ok] Main dispatcher wz-ai.cmd installed to $LocalBin (subcommands are encapsulated)" -ForegroundColor Green
# 7. Install Skills for all agents (hierarchical ? flat)
Write-Log ' '
Write-Log '[7/8] Installing AI agent skills...' -ForegroundColor Blue
$SkillsDst = Join-Path $HOME '.gemini\config\skills'
$null = New-Item -ItemType Directory -Force -Path $SkillsDst
$SkillCount = 0
# Find every SKILL.md inside categorized directories and copy its parent folder flatly
Get-ChildItem -Path (Join-Path $ScriptDir 'skills') -Filter 'SKILL.md' -Recurse -File | ForEach-Object {
$SkillDir = $_.DirectoryName
$SkillName = Split-Path $SkillDir -Leaf
$DestDir = Join-Path $SkillsDst $SkillName
$null = New-Item -ItemType Directory -Force -Path $DestDir
Copy-Item -Path (Join-Path $SkillDir '*') -Destination $DestDir -Recurse -Force -ErrorAction SilentlyContinue
$SkillCount++
}
# Also copy skills.json for reference
Copy-Item -Path (Join-Path $ScriptDir 'skills\skills.json') -Destination $SkillsDst -Force -ErrorAction SilentlyContinue
Write-Log "[ok] $SkillCount skills installed to $SkillsDst" -ForegroundColor Green
Write-Log 'Syncing skills to Claude Code, Amp, and other agents...' -ForegroundColor Yellow
& (Join-Path $LocalBin 'wz-ai-sync-skills.ps1')
# 7.5. Interactive Skill Setup and Configuration
Write-Log ' '
Write-Log '[7.5/8] Interactive Skill Setup and Configuration...' -ForegroundColor Blue
Get-ChildItem -Path $SkillsDst -Directory | ForEach-Object {
$SkillDir = $_.FullName
$SkillName = $_.Name
$SetupPs1 = Join-Path $SkillDir 'scripts\setup.ps1'
$InstallPs1 = Join-Path $SkillDir 'scripts\install.ps1'
$SetupSh = Join-Path $SkillDir 'scripts\setup.sh'
$InstallSh = Join-Path $SkillDir 'scripts\install.sh'
$SetupJs = Join-Path $SkillDir 'scripts\setup.js'
$ScriptToRun = $null
if (Test-Path $SetupPs1) { $ScriptToRun = $SetupPs1 }
elseif (Test-Path $InstallPs1) { $ScriptToRun = $InstallPs1 }
elseif (Test-Path $SetupJs) { $ScriptToRun = "node $SetupJs" }
elseif (Test-Path $SetupSh) { $ScriptToRun = "bash $SetupSh" }
elseif (Test-Path $InstallSh) { $ScriptToRun = "bash $InstallSh" }
if ($ScriptToRun) {
Write-Log " ╭────────────────────────────────────────────────────────╮" -ForegroundColor Magenta
Write-Log " │ 🛠 Configuration: $($SkillName)" -ForegroundColor Cyan
Write-Log " ├────────────────────────────────────────────────────────┤" -ForegroundColor Magenta
Write-Log " │ Found automated setup script for $($SkillName): $ScriptToRun" -ForegroundColor Cyan
Write-Log " │ Auto-running setup script (forced)..." -ForegroundColor Green
try {
if ($ScriptToRun.EndsWith('.ps1')) {
& $ScriptToRun
} else {
Invoke-Expression $ScriptToRun
}
Write-Log " │ [ok] Setup completed for $SkillName." -ForegroundColor Green
} catch {
Write-Log " │ [!] Setup for $SkillName returned warning: $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Log " ╰────────────────────────────────────────────────────────╯" -ForegroundColor Magenta
}
}
Write-Log ' '
Write-Log '[7.6/8] Auto-configuring Pi Agent Models...' -ForegroundColor Blue
if (Get-Command node -ErrorAction SilentlyContinue) {
Write-Log 'Syncing benchmarks and mapping best Cockpit models to Pi roles...' -ForegroundColor Yellow
try {
node (Join-Path $ScriptDir 'scripts\wz-ai-benchmark-sync.js')
node (Join-Path $ScriptDir 'scripts\wz-ai-pi-configurator.js')
Write-Log ' [ok] Pi auto-configuration completed.' -ForegroundColor Green
} catch {
Write-Log " [!] Failed to configure Pi: $($_.Exception.Message)" -ForegroundColor Red
}
} else {
Write-Log " [!] Node.js not found. Skipping Pi auto-configuration." -ForegroundColor Yellow
}
# 7.7. Pi Integration and Cockpit Proxy Setup (Antigravity Rotator)
Write-Log ' '
Write-Log '[7.7/8] Pi Integration and Cockpit Proxy Setup...' -ForegroundColor Blue
if (Get-Command npm -ErrorAction SilentlyContinue) {
$RunCockpitProxy = 'Y'
# Auto-detect Cockpit Tools installation
$CockpitDetected = $false
$CockpitPaths = @(
"$env:USERPROFILE\.antigravity_cockpit",
"$env:LOCALAPPDATA\cockpit-tools",
"$env:APPDATA\cockpit-tools",
"$env:USERPROFILE\.wizard-ai\cockpit-tools"
)
foreach ($cPath in $CockpitPaths) {
if ((Test-Path (Join-Path $cPath 'accounts.json')) -or (Test-Path (Join-Path $cPath 'account-token.key'))) {
$CockpitDetected = $true
Write-Log " [ok] Auto-detected Cockpit Tools installation at: $cPath" -ForegroundColor Green
break
}
}
$RunCockpitProxy = 'Y'
Write-Log 'Do you want to install and enable the background Cockpit Proxy Rotator for Pi? [Y/n]' -ForegroundColor Yellow
Write-Log ' (auto-accepted - forced configuration)' -ForegroundColor Green
if ($RunCockpitProxy -notmatch '^[Nn]$') {
Write-Log ' Installing and enabling background Proxy Rotator...' -ForegroundColor Cyan
Write-Log ' The proxy will be installed and enabled as a background service to avoid quota (429) issues.' -ForegroundColor Yellow
npm install -g pi-antigravity-rotator 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Log ' [ok] pi-antigravity-rotator installed.' -ForegroundColor Green
} else {
Write-Log " [!] Failed to install pi-antigravity-rotator (exit code $LASTEXITCODE)." -ForegroundColor Red
}
$WzAiProxyJs = Join-Path $PSScriptRoot 'scripts\wz-ai-proxy.js'
if (Test-Path $WzAiProxyJs) {
try {
Write-Log ' Executing Automated Cockpit Tools & Rotator Proxy Setup (Boot)...' -ForegroundColor Cyan
node $WzAiProxyJs boot
} catch {
Write-Log " [!] wz-ai-proxy boot warning: $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Log ' '
Write-Log '========================================================================' -ForegroundColor Green
Write-Log ' ✨ COCKPIT TOOLS & PI ROTATOR PROXY FULLY INTEGRATED ✨' -ForegroundColor Green
Write-Log '========================================================================' -ForegroundColor Green
if ($CockpitDetected) {
Write-Log ' [ok] Cockpit Tools multi-account OAuth tokens auto-imported!' -ForegroundColor Green
} else {
Write-Log ' [i] Cockpit Tools not found. Add Google accounts via: wz-ai-proxy login' -ForegroundColor Yellow
}
Write-Log ' [ok] Pi CLI configured to route requests via local rotator (port 51200)' -ForegroundColor Cyan
Write-Log ' [ok] Rotator proxy service enabled in Startup folder (auto-starts on boot)' -ForegroundColor Cyan
Write-Log ' '
Write-Log ' Useful Proxy Commands:' -ForegroundColor Yellow
Write-Log ' wz-ai-proxy accounts # List all rotator accounts and quotas' -ForegroundColor Cyan
Write-Log ' wz-ai-proxy status # Check proxy rotation status' -ForegroundColor Cyan
Write-Log ' wz-ai-proxy login # Add a new Google account via OAuth' -ForegroundColor Cyan
Write-Log '========================================================================' -ForegroundColor Green
Write-Log ' '
} else {
Write-Log " [!] $WzAiProxyJs not found. Skipping proxy configuration." -ForegroundColor Yellow
}
}
} else {
Write-Log '[!] npm not found. Cockpit Proxy setup skipped.' -ForegroundColor Yellow
}
Write-Log ' '
Write-Log '[8/8] Auto-Update Configuration...' -ForegroundColor Blue
Write-Log 'Do you want to enable automatic background updates at system logon? [Y/n] (Auto-yes in 10s) ' -ForegroundColor Yellow -NoNewline
$EnableUpdate = 'Y'
Write-Log ' (auto-accepted - forced configuration)' -ForegroundColor Green
$StartupFolder = [Environment]::GetFolderPath('Startup')
$StartupShortcut = Join-Path $StartupFolder "WizardAI-AutoUpdate.lnk"
if ($EnableUpdate -eq 'Y') {
Write-Log " [ok] Enabling automatic background updates at logon..." -ForegroundColor Green
$UpdateScriptPath = Join-Path $LocalBin 'wz-ai-update.ps1'
# Security: Ensure the file exists before creating the shortcut
if (Test-Path $UpdateScriptPath) {
try {
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut($StartupShortcut)
$Shortcut.TargetPath = "powershell.exe"
$Shortcut.Arguments = "-WindowStyle Hidden -NoProfile -ExecutionPolicy Bypass -File `"$UpdateScriptPath`" -Quiet"
$Shortcut.Save()
Write-Log " [ok] Startup shortcut installed for user." -ForegroundColor Green
}
catch {
Write-Log " [!] Could not create startup shortcut: $($_.Exception.Message)" -ForegroundColor Yellow
}
} else {
Write-Log " [!] Update script not found at $UpdateScriptPath. Skipping auto-update setup." -ForegroundColor Red
}
}
else {
Write-Log " Auto-updates disabled. Update manually using 'wz-ai update'." -ForegroundColor Yellow
if (Test-Path $StartupShortcut) {
Remove-Item $StartupShortcut -Force
}
}
# 9. Final summary
Write-Log ' '
Write-Log '============================================================' -ForegroundColor Green
Write-Log ' Wizard-AI Environment Installed Successfully!' -ForegroundColor Green
Write-Log '============================================================' -ForegroundColor Green
Write-Log ' '
Write-Log '╭────────────────────────────────────────────────────────────╮' -ForegroundColor Green
Write-Log '│ 🚀 QUICK START GUIDE │' -ForegroundColor Green
Write-Log '├────────────────────────────────────────────────────────────┤' -ForegroundColor Green
Write-Log '│ 1. AI Agents & Cockpit Tools │' -ForegroundColor Green
Write-Log '│ wz-ai proxy login (Add Google Account) │' -ForegroundColor Green
Write-Log '│ wz-ai proxy setup (Sync models to Pi) │' -ForegroundColor Green
Write-Log '│ wizard-ai pi-configurator (Auto-select AI models) │' -ForegroundColor Green
Write-Log '│ │' -ForegroundColor Green
Write-Log '│ 2. Scaffolding & Frameworks │' -ForegroundColor Green
Write-Log '│ pi ''scaffold a new Qwik app'' │' -ForegroundColor Green
Write-Log '│ pi ''setup a Nuxt 4 project in ./dashboard'' │' -ForegroundColor Green
Write-Log '│ pi ''bootstrap an Astro 5 landing page'' │' -ForegroundColor Green
Write-Log '│ │' -ForegroundColor Green
Write-Log '│ 3. Master Initialization │' -ForegroundColor Green
Write-Log '│ pi ''run master-project-bootstrap here'' │' -ForegroundColor Green
Write-Log '╰────────────────────────────────────────────────────────────╯' -ForegroundColor Green
Write-Log ' '
Write-Log 'Important: open a NEW terminal to load the updated PATH.' -ForegroundColor Yellow
Write-Log ' '
Write-Log 'Your Wizard-AI directory: ' -ForegroundColor Yellow -NoNewline; Write-Log $ScriptDir -ForegroundColor Magenta
Write-Log 'Skills: ' -ForegroundColor Yellow -NoNewline; Write-Log $SkillsDst -ForegroundColor Magenta
Write-Log 'CLIs: ' -ForegroundColor Yellow -NoNewline; Write-Log $LocalBin -ForegroundColor Magenta
Write-Log ' '
Write-Log "Run 'wz-ai help' to see all available tools and their usage." -ForegroundColor Cyan