Repository navigation
Expand file tree
/
Copy pathinstall.ps1
More file actions
490 lines (442 loc) · 19 KB
/
Copy pathinstall.ps1
File metadata and controls
490 lines (442 loc) · 19 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
#!/usr/bin/env pwsh
# ───────────────────────────────────────────────────────────────────────
# DreamCode Windows Installer (PowerShell)
#
# Downloads the pre-built binary from GitHub Releases, places it in
# $env:LOCALAPPDATA\dreamcode\bin\, and adds it to the user PATH.
#
# Usage:
# irm https://raw.githubusercontent.com/weebcoder101/dreamcode/stable-release/install.ps1 | iex
# .\install.ps1
#
# Or clone + build from source:
# git clone https://github.com/weebcoder101/dreamcode; cd dreamcode
# .\install.ps1 -BuildFromSource
# ───────────────────────────────────────────────────────────────────────
param(
[switch]$BuildFromSource
)
$ErrorActionPreference = "Stop"
# Force TLS 1.2 (GitHub requires it; older Windows defaults to TLS 1.0)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$APP = "dreamcode"
$OWNER = "weebcoder101"
$REPO = "dreamcode"
$INSTALL_DIR = if ($env:DREAMCODE_DIR) { $env:DREAMCODE_DIR } else { "$env:USERPROFILE\.dreamcode" }
$BIN_DIR = "$env:LOCALAPPDATA\$APP\bin"
$tempDir = "$env:TEMP\dreamcode-install"
# ─── Colors (approximate) ─────────────────────────────────────────────
$GREEN = "Green"
$CYAN = "Cyan"
$RED = "Red"
$ORANGE = "Yellow"
$MUTED = "DarkGray"
$BOLD = "White"
function Write-Color($text, $color, $bold = $false) {
if ($bold) { Write-Host $text -ForegroundColor $color }
else { Write-Host $text -ForegroundColor $color }
}
# ─── Helper: download with progress ───────────────────────────────────
function Download-File($url, $dest) {
Write-Color "Downloading $url ..." $CYAN
Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing
}
# ─── Phase 1: Download pre-built binary (default) ─────────────────────
if (-not $BuildFromSource) {
Write-Color "DreamCode Windows Installer" $BOLD $true
Write-Color "Downloading latest release..." $CYAN
# Get latest release from GitHub
$apiUrl = "https://api.github.com/repos/$OWNER/$REPO/releases/latest"
try {
$release = Invoke-RestMethod -Uri $apiUrl -Headers @{ "User-Agent" = "dreamcode-installer" }
$tag = $release.tag_name
Write-Color "Latest release: $tag" $MUTED
# Find the windows-x64 asset — try .tar.gz first (v1.4.0+), then .zip (v1.3.x and earlier)
$winAsset = $release.assets | Where-Object { $_.name -match "windows-x64(?!.*baseline)" } | Sort-Object -Property name | Select-Object -First 1
if (-not $winAsset) {
Write-Color "ERROR: No windows-x64 asset found in release $tag" $RED
Write-Color "Falling back to source build (requires git + bun)..." $ORANGE
$BuildFromSource = $true
} else {
$assetName = $winAsset.name
$downloadUrl = $winAsset.browser_download_url
$tempArchive = "$tempDir\$assetName"
$extractDir = "$tempDir\extracted"
Write-Color "Found asset: $assetName" $MUTED
New-Item -ItemType Directory -Force -Path $tempDir, $extractDir | Out-Null
try {
Download-File $downloadUrl $tempArchive
} catch {
Write-Color "ERROR: Failed to download $downloadUrl" $RED
Write-Color "Falling back to source build (requires git + bun)..." $ORANGE
$BuildFromSource = $true
}
}
} catch {
Write-Color "ERROR: Failed to fetch latest release from GitHub API." $RED
Write-Color "Falling back to source build (requires git + bun)..." $ORANGE
$BuildFromSource = $true
}
}
# ─── Phase 1b: Extract pre-built binary ───────────────────────────────
if (-not $BuildFromSource -and (Test-Path $tempArchive)) {
Write-Color "Extracting $assetName..." $CYAN
# Handle both .tar.gz (v1.4.0+) and .zip (v1.3.x and earlier)
try {
if ($assetName -match "\.tar\.gz$|\.tgz$") {
# tar.gz: use built-in tar (Windows 10+ includes tar.exe)
if (Get-Command tar -ErrorAction SilentlyContinue) {
& tar -xzf $tempArchive -C $extractDir
} else {
Write-Color "WARN: tar not found — trying 7z..." $ORANGE
if (Get-Command 7z -ErrorAction SilentlyContinue) {
& 7z x $tempArchive -o"$extractDir" -y
} else {
throw "Neither tar nor 7z found. Install 7-Zip or use Windows 10+ (includes tar)."
}
}
} else {
# .zip: use native PowerShell Expand-Archive
Expand-Archive -Path $tempArchive -DestinationPath $extractDir -Force
}
} catch {
Write-Color "WARN: Extraction failed — falling back to source build: $_" $ORANGE
$BuildFromSource = $true
}
if (-not $BuildFromSource) {
$binaryPath = Get-ChildItem -Recurse -Filter "dreamcode.exe" -Path $extractDir | Select-Object -First 1
if (-not $binaryPath) {
Write-Color "ERROR: Binary not found in extracted archive" $RED
$BuildFromSource = $true
} else {
# Install binary to bin dir
New-Item -ItemType Directory -Force -Path $BIN_DIR | Out-Null
Copy-Item $binaryPath.FullName "$BIN_DIR\$APP.exe" -Force
Write-Color "Installed $APP.exe to $BIN_DIR" $GREEN
}
}
}
# ─── Phase 1c: Build from source (fallback or explicit) ───────────────
if ($BuildFromSource) {
Write-Color "Building from source..." $CYAN
# Check for git before attempting source build
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Color "ERROR: git is required for source build but was not found." $RED
Write-Color "Install git from https://git-scm.com/download/win and re-run." $ORANGE
exit 1
}
# Clone or update repo
if (Test-Path "$INSTALL_DIR\.git") {
Write-Color "Updating existing DreamCode install..." $CYAN
$currentBranch = git -C $INSTALL_DIR rev-parse --abbrev-ref HEAD 2>&1
if ($currentBranch -ne "stable-release") {
Write-Color "Switching to stable-release branch..." $CYAN
git -C $INSTALL_DIR fetch origin stable-release 2>&1 | Out-Null
git -C $INSTALL_DIR checkout stable-release 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
git -C $INSTALL_DIR checkout -b stable-release origin/stable-release 2>&1 | Out-Null
}
}
git -C $INSTALL_DIR pull origin stable-release 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Color "WARN: git pull failed (detached HEAD or network issue). Using working tree as-is." $ORANGE
git -C $INSTALL_DIR checkout .
}
} else {
if (Test-Path $INSTALL_DIR) {
Write-Color "ERROR: $INSTALL_DIR exists but is not a git repo." $RED
Write-Color "Remove it or set `$env:DREAMCODE_DIR to a different path." $ORANGE
exit 1
}
Write-Color "Cloning DreamCode (stable-release branch)..." $CYAN
try {
git clone -b stable-release "https://github.com/$OWNER/$REPO.git" $INSTALL_DIR
} catch {
Write-Color "ERROR: git clone failed: $_" $RED
exit 1
}
}
# Check for bun
if (-not (Get-Command bun -ErrorAction SilentlyContinue)) {
Write-Color "Installing bun..." $CYAN
# Use bun's official PowerShell installer (scope ErrorActionPreference to avoid breaking it)
$bunInstallScript = Invoke-RestMethod -Uri "https://bun.sh/install.ps1"
$prevEAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
Invoke-Expression ($bunInstallScript)
} finally {
$ErrorActionPreference = $prevEAP
}
$env:Path = "$env:USERPROFILE\.bun\bin;$env:Path"
}
# Read version from package.json
$pkg = Get-Content "$INSTALL_DIR\packages\opencode\package.json" | ConvertFrom-Json
$VERSION = $pkg.version
$env:OPENCODE_VERSION = $VERSION
Write-Color "Building version: $VERSION" $MUTED
Set-Location $INSTALL_DIR
# Windows requires --linker hoisted for symlink compatibility (bun#12385)
$bunInstallArgs = @("install")
if ($env:OS -eq "Windows_NT") { $bunInstallArgs += "--linker", "hoisted" }
$sourceBuildOk = $true
try {
& "bun" @bunInstallArgs
} catch {
Write-Color "WARN: bun install failed (likely native dep compilation on Windows): $_" $ORANGE
Write-Color "Continuing — the pre-built download path is the primary install method for Windows." $ORANGE
$sourceBuildOk = $false
}
if ($sourceBuildOk) {
Set-Location packages\opencode
$buildOk = $true
try {
bun run build --single --skip-embed-web-ui --skip-install
} catch {
Write-Color "WARN: bun build failed (likely bun 1.3.x Schema AST bug on Windows): $_" $ORANGE
$buildOk = $false
}
if ($buildOk) {
# Verify binary
$NATIVE_BIN = "dist\dreamcode-windows-x64\bin\dreamcode.exe"
if (Test-Path $NATIVE_BIN) {
# Copy binary
New-Item -ItemType Directory -Force -Path $BIN_DIR | Out-Null
Copy-Item $NATIVE_BIN "$BIN_DIR\$APP.exe" -Force
Write-Color "Installed $APP.exe to $BIN_DIR" $GREEN
} else {
Write-Color "WARN: Build did not produce expected binary at $NATIVE_BIN" $ORANGE
}
}
}
if (-not (Test-Path "$BIN_DIR\$APP.exe")) {
Write-Color "WARN: Binary was not installed via source build. The pre-built download path is recommended for Windows." $ORANGE
Write-Color "Install with: .\install.ps1 (without -BuildFromSource) to download a pre-built binary." $CYAN
}
}
# ─── Phase 1d: Install skills and plugins to config directory ────────
# The Python scripts (sensor_gate.py, neuro_harness.py, etc.) and plugins
# (sensor-gate-enforcer.ts, etc.) are needed for skill/chain/sensor-gate
# functionality. The resolver checks ~/.config/dreamcode/skills at runtime.
$CONFIG_SKILLS = "$env:USERPROFILE\.config\dreamcode\skills"
$CONFIG_PLUGINS = "$env:USERPROFILE\.config\dreamcode\plugins"
# Skills/plugins source candidates:
# 1. Bundled alongside the binary in the extracted archive (pre-built)
# Layout varies: flat zip → $extractDir/skills
# tar.gz → $extractDir/<name>/bin/skills
# Solution: find skills relative to the exe we already located.
# 2. Source repo path (BuildFromSource)
$bundledSkills = $null
$bundledPlugins = $null
$repoSkills = "$INSTALL_DIR\packages\opencode\src\skill\dreamcode\skills"
$skillsSource = $null
# Locate skills/plugins relative to the installed exe (archive-layout-agnostic)
$exeCandidate = Get-ChildItem -Path $extractDir -Recurse -Filter "$APP.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $BuildFromSource -and $exeCandidate) {
$exeDir = Split-Path $exeCandidate.FullName -Parent
$bundledSkills = Join-Path $exeDir "skills"
$bundledPlugins = Join-Path $exeDir "plugins"
Write-Color "Probing skills at: $bundledSkills" $MUTED
}
if (-not $BuildFromSource -and $bundledSkills -and (Test-Path $bundledSkills)) {
$skillsSource = $bundledSkills
Write-Color "Found bundled skills in release archive." $MUTED
} elseif ($BuildFromSource -and (Test-Path $repoSkills)) {
$skillsSource = $repoSkills
Write-Color "Found skills in source repo." $MUTED
}
if ($skillsSource) {
Write-Color "Installing skills to $CONFIG_SKILLS ..." $CYAN
try {
New-Item -ItemType Directory -Force -Path $CONFIG_SKILLS | Out-Null
Copy-Item -Path "$skillsSource\*" -Destination $CONFIG_SKILLS -Recurse -Force
$skillCount = (Get-ChildItem -Path $CONFIG_SKILLS -Directory).Count
Write-Color "Installed $skillCount skills to $CONFIG_SKILLS" $GREEN
} catch {
Write-Color "WARN: Failed to install skills: $_" $ORANGE
Write-Color "Skill chains may not work without skills." $ORANGE
}
} else {
Write-Color "WARN: No skills source found." $ORANGE
Write-Color "Skill chains will be disabled without skills." $ORANGE
}
# Plugins source candidates (same logic as skills above)
$repoPlugins = "$INSTALL_DIR\.opencode\plugins"
$pluginsSource = $null
if (-not $BuildFromSource -and $bundledPlugins -and (Test-Path $bundledPlugins)) {
$pluginsSource = $bundledPlugins
Write-Color "Found bundled plugins in release archive." $MUTED
} elseif ($BuildFromSource -and (Test-Path $repoPlugins)) {
$pluginsSource = $repoPlugins
Write-Color "Found plugins in source repo." $MUTED
}
if ($pluginsSource) {
Write-Color "Installing plugins to $CONFIG_PLUGINS ..." $CYAN
try {
New-Item -ItemType Directory -Force -Path $CONFIG_PLUGINS | Out-Null
Copy-Item -Path "$pluginsSource\*" -Destination $CONFIG_PLUGINS -Recurse -Force
$pluginCount = (Get-ChildItem -Path $CONFIG_PLUGINS -Filter "*.ts" -Recurse).Count
Write-Color "Installed $pluginCount plugins to $CONFIG_PLUGINS" $GREEN
} catch {
Write-Color "WARN: Failed to install plugins: $_" $ORANGE
}
} else {
Write-Color "WARN: No plugins source found." $ORANGE
}
# ─── Copy skills/plugins alongside binary (binary-bundled fallback) ──
# The resolver checks dirname(process.execPath)/skills first. Copying here
# ensures skills/plugins work even if XDG config is cleared.
if (Test-Path "$BIN_DIR\$APP.exe") {
if (Test-Path $CONFIG_SKILLS) {
$binSkills = "$BIN_DIR\skills"
try {
New-Item -ItemType Directory -Force -Path $binSkills | Out-Null
Copy-Item -Path "$CONFIG_SKILLS\*" -Destination $binSkills -Recurse -Force
Write-Color "Copied skills alongside binary: $binSkills" $GREEN
} catch {
Write-Color "WARN: Failed to copy skills alongside binary: $_" $ORANGE
}
}
if (Test-Path $CONFIG_PLUGINS) {
$binPlugins = "$BIN_DIR\plugins"
try {
New-Item -ItemType Directory -Force -Path $binPlugins | Out-Null
Copy-Item -Path "$CONFIG_PLUGINS\*" -Destination $binPlugins -Recurse -Force
Write-Color "Copied plugins alongside binary: $binPlugins" $GREEN
} catch {
Write-Color "WARN: Failed to copy plugins alongside binary: $_" $ORANGE
}
}
}
# ─── Phase 1e: Verify Python availability ─────────────────────────────
# Check if Python is available on the system
$pythonAvailable = $false
$pythonCmd = $null
# Try py -3 (Python Launcher for Windows)
if (Get-Command py -ErrorAction SilentlyContinue) {
try {
$pyVersion = & py -3 --version 2>&1 | Out-String
if ($pyVersion -match "Python 3") {
$pythonAvailable = $true
$pythonCmd = "py -3"
Write-Color "Python 3 found via Python Launcher: $pythonCmd" $GREEN
}
} catch {}
}
# Try python
if (-not $pythonAvailable -and (Get-Command python -ErrorAction SilentlyContinue)) {
try {
$pyVersion = & python --version 2>&1 | Out-String
if ($pyVersion -match "Python 3") {
$pythonAvailable = $true
$pythonCmd = "python"
Write-Color "Python 3 found: $pythonCmd" $GREEN
}
} catch {}
}
# Try python3
if (-not $pythonAvailable -and (Get-Command python3 -ErrorAction SilentlyContinue)) {
try {
$pyVersion = & python3 --version 2>&1 | Out-String
if ($pyVersion -match "Python 3") {
$pythonAvailable = $true
$pythonCmd = "python3"
Write-Color "Python 3 found: $pythonCmd" $GREEN
}
} catch {}
}
if (-not $pythonAvailable) {
Write-Color "" $ORANGE
Write-Color "WARNING: Python 3 not found on your system!" $RED
Write-Color "The persona/skill/chain features require Python 3." $ORANGE
Write-Color "" $ORANGE
Write-Color "To install Python 3 on Windows:" $CYAN
Write-Color " 1. Download from https://www.python.org/downloads/" $CYAN
Write-Color " 2. Run the installer" $CYAN
Write-Color " 3. CHECK THE BOX: 'Add Python to PATH'" $CYAN
Write-Color " 4. Restart your terminal" $CYAN
Write-Color "" $ORANGE
Write-Color "Or install via winget:" $CYAN
Write-Color " winget install Python.Python.3.12" $CYAN
Write-Color "" $ORANGE
Write-Color "Without Python, you can still use DreamCode for basic tasks." $MUTED
Write-Color "Personas and skill chains will be disabled." $MUTED
} else {
Write-Color "" $MUTED
Write-Color "Python 3 verified: $pythonCmd" $GREEN
}
# ─── Phase 2: Add to user PATH (only if binary was installed) ──────────
$installSucceeded = Test-Path "$BIN_DIR\$APP.exe"
if ($installSucceeded) {
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$BIN_DIR*") {
[Environment]::SetEnvironmentVariable("Path", "$BIN_DIR;$userPath", "User")
# Also update current session
$env:Path = "$BIN_DIR;$env:Path"
Write-Color "Added $BIN_DIR to user PATH" $GREEN
# Support CI (GitHub Actions): propagate PATH to subsequent steps
if ($env:GITHUB_PATH) {
Add-Content -Path $env:GITHUB_PATH -Value $BIN_DIR
}
} else {
Write-Color "$BIN_DIR already in PATH" $MUTED
}
} else {
Write-Color "Installation did not complete — PATH not modified." $ORANGE
}
# ─── Cleanup: remove temp directory ──────────────────────────────────
if (Test-Path $tempDir) {
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
}
# ─── Phase 3: Verify ─────────────────────────────────────────────────
Write-Color "" $MUTED
Write-Color ("=" * 50) $GREEN
Write-Color " DreamCode Install Complete" $BOLD $true
Write-Color ("=" * 50) $GREEN
Write-Color "" $MUTED
$fullPath = "$BIN_DIR\$APP.exe"
if (Test-Path $fullPath) {
try {
$version = & $fullPath --version 2>&1 | Out-String
Write-Color " Binary: $fullPath" $GREEN
Write-Color " Version: $($version.Trim())" $GREEN
} catch {
Write-Color " Binary: $fullPath (version check failed)" $ORANGE
}
} else {
Write-Color " ERROR: $fullPath not found!" $RED
}
# Verify skills installation
$skillsInstalled = Test-Path "$CONFIG_SKILLS\chain-orchestrator\scripts\sensor_gate.py"
if ($skillsInstalled) {
Write-Color " Skills: $CONFIG_SKILLS (installed)" $GREEN
} else {
Write-Color " Skills: $CONFIG_SKILLS (not found)" $ORANGE
}
# Verify plugins installation
$pluginsInstalled = Test-Path "$CONFIG_PLUGINS\sensor-gate-enforcer.ts"
if ($pluginsInstalled) {
Write-Color " Plugins: $CONFIG_PLUGINS (installed)" $GREEN
} else {
Write-Color " Plugins: $CONFIG_PLUGINS (not found)" $ORANGE
}
# Verify Python
if ($pythonAvailable) {
Write-Color " Python: $pythonCmd (available)" $GREEN
} else {
Write-Color " Python: NOT FOUND (personas disabled)" $RED
}
Write-Color "" $CYAN
Write-Color "Quick start:" $CYAN
Write-Color " Open a NEW PowerShell window (for PATH to take effect)" $CYAN
Write-Color " cd <your-project>" $CYAN
Write-Color " $APP" $CYAN
Write-Color "" $CYAN
Write-Color "Configuration:" $CYAN
Write-Color " ~\.config\dreamcode\config.yaml (create if missing)" $CYAN
Write-Color "" $CYAN
Write-Color "NEURO API (Highly Recommended):" $CYAN
Write-Color " Get your free key at https://neurometric.ai" $CYAN
Write-Color " Then: `$env:NEURO_API_KEY = 'your-key'" $CYAN
Write-Color "" $MUTED
Write-Color "Docs: https://github.com/weebcoder101/dreamcode" $MUTED