build_vscode.bat 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. @echo off
  2. REM Opencode VSCode Extension Build Script for Windows
  3. REM Handles the complete build process for the Opencode VSCode extension.
  4. REM Supports building two variants:
  5. REM - Standard: bundles opencode binaries (default)
  6. REM - GUI-only: no binaries, uses system opencode, embeds webgui-dist
  7. REM
  8. REM By default both variants are built. Use --gui-only or --standard-only to
  9. REM build a single variant.
  10. setlocal enabledelayedexpansion
  11. REM Resolve key directories
  12. set "SCRIPT_DIR=%~dp0"
  13. set "ROOT_DIR=%SCRIPT_DIR%..\.."
  14. for %%I in ("%ROOT_DIR%") do set "ROOT_DIR=%%~fI"
  15. set "PLUGIN_DIR=%ROOT_DIR%\hosts\vscode-plugin"
  16. set "WEBGUI_DIR=%ROOT_DIR%\packages\opencode\webgui"
  17. set "WEBGUI_DIST=%ROOT_DIR%\packages\opencode\webgui-dist"
  18. if not exist "%PLUGIN_DIR%\package.json" (
  19. echo [ERROR] package.json not found. Please run this script from the repository root.
  20. exit /b 1
  21. )
  22. echo Opencode VSCode Extension Build Script
  23. echo Plugin directory: %PLUGIN_DIR%
  24. echo Root directory: %ROOT_DIR%
  25. set "BUILD_TYPE=development"
  26. set "SKIP_BINARIES=false"
  27. set "SKIP_TESTS=false"
  28. set "PACKAGE_ONLY=false"
  29. set "BUILD_STANDARD=true"
  30. set "BUILD_GUI_ONLY=true"
  31. :parse_args
  32. if "%~1"=="" goto args_done
  33. if "%~1"=="--production" (
  34. set "BUILD_TYPE=production"
  35. shift
  36. goto parse_args
  37. )
  38. if "%~1"=="--skip-binaries" (
  39. set "SKIP_BINARIES=true"
  40. shift
  41. goto parse_args
  42. )
  43. if "%~1"=="--skip-tests" (
  44. set "SKIP_TESTS=true"
  45. shift
  46. goto parse_args
  47. )
  48. if "%~1"=="--package-only" (
  49. set "PACKAGE_ONLY=true"
  50. shift
  51. goto parse_args
  52. )
  53. if "%~1"=="--gui-only" (
  54. set "BUILD_STANDARD=false"
  55. set "BUILD_GUI_ONLY=true"
  56. shift
  57. goto parse_args
  58. )
  59. if "%~1"=="--standard-only" (
  60. set "BUILD_STANDARD=true"
  61. set "BUILD_GUI_ONLY=false"
  62. shift
  63. goto parse_args
  64. )
  65. if "%~1"=="--help" (
  66. echo Usage: %0 [OPTIONS]
  67. echo --production Build for production (default: development)
  68. echo --skip-binaries Skip building backend binaries
  69. echo --skip-tests Skip running tests
  70. echo --package-only Only create the .vsix package (skip compilation)
  71. echo --gui-only Build only the gui-only variant (no binaries)
  72. echo --standard-only Build only the standard variant (with binaries)
  73. echo --help Show this help message
  74. exit /b 0
  75. )
  76. echo [ERROR] Unknown option: %~1
  77. exit /b 1
  78. :args_done
  79. echo [INFO] Building VSCode extension in %BUILD_TYPE% mode
  80. if "%BUILD_STANDARD%"=="true" echo [INFO] Variant: standard (with binaries)
  81. if "%BUILD_GUI_ONLY%"=="true" echo [INFO] Variant: gui-only (system opencode)
  82. cd /d "%PLUGIN_DIR%"
  83. REM --- Shared preparation (compile once, package per-variant) ---
  84. if "%PACKAGE_ONLY%"=="false" (
  85. echo [INFO] Cleaning previous build artifacts...
  86. if not exist "node_modules" (
  87. echo [WARN] Dependencies not installed; skipping script clean and removing artifacts manually.
  88. if exist "out" rmdir /s /q "out"
  89. del /f /q *.vsix 2>nul
  90. ) else (
  91. call pnpm run clean 2>nul
  92. if errorlevel 1 (
  93. echo [WARN] Clean command failed, applying fallback removal...
  94. if exist "out" rmdir /s /q "out"
  95. del /f /q *.vsix 2>nul
  96. )
  97. )
  98. )
  99. if "%PACKAGE_ONLY%"=="false" (
  100. echo [INFO] Installing dependencies...
  101. where pnpm >nul 2>&1
  102. if not errorlevel 1 (
  103. call pnpm install
  104. ) else (
  105. where npm >nul 2>&1
  106. if errorlevel 1 (
  107. echo [ERROR] Neither pnpm nor npm found. Please install a package manager.
  108. exit /b 1
  109. )
  110. call npm install
  111. )
  112. )
  113. if "%SKIP_BINARIES%"=="false" (
  114. if "%PACKAGE_ONLY%"=="false" (
  115. if "%BUILD_STANDARD%"=="true" (
  116. echo [INFO] Building backend binaries...
  117. cd /d "%ROOT_DIR%"
  118. if exist "hosts\scripts\build_opencode.bat" (
  119. call hosts\scripts\build_opencode.bat
  120. ) else (
  121. echo [ERROR] Backend build script not found at hosts\scripts\build_opencode.bat
  122. exit /b 1
  123. )
  124. cd /d "%PLUGIN_DIR%"
  125. )
  126. )
  127. )
  128. if "%PACKAGE_ONLY%"=="false" (
  129. echo [INFO] Compiling TypeScript...
  130. if "%BUILD_TYPE%"=="production" (
  131. call pnpm run compile:production
  132. ) else (
  133. call pnpm run compile
  134. )
  135. )
  136. if "%PACKAGE_ONLY%"=="false" (
  137. echo [INFO] Running linter...
  138. call pnpm run lint
  139. if errorlevel 1 echo [WARN] Linting failed, continuing with build...
  140. )
  141. if "%SKIP_TESTS%"=="false" (
  142. if "%PACKAGE_ONLY%"=="false" (
  143. echo [INFO] Running tests...
  144. call pnpm run test
  145. if errorlevel 1 echo [WARN] Tests failed, continuing with build...
  146. )
  147. )
  148. REM --- Resolve vsce command ---
  149. set "VSCE_CMD=vsce"
  150. where vsce >nul 2>&1
  151. if errorlevel 1 (
  152. where npx >nul 2>&1
  153. if not errorlevel 1 (
  154. set "VSCE_CMD=npx -y @vscode/vsce"
  155. ) else (
  156. echo [WARN] vsce not found and npx unavailable; attempting global install via npm
  157. call npm install -g @vscode/vsce
  158. )
  159. )
  160. REM Generate timestamp
  161. for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (
  162. for /f "tokens=1-2 delims=/" %%c in ("%%a") do (
  163. set "MONTH=%%c"
  164. set "DAY=%%d"
  165. )
  166. set "YEAR=%%b"
  167. )
  168. for /f "tokens=1-2 delims=: " %%a in ('time /t') do (
  169. set "HOUR=%%a"
  170. set "MINUTE=%%b"
  171. )
  172. set "TIMESTAMP=%YEAR%%MONTH%%DAY%-%HOUR%%MINUTE%"
  173. REM --- Build helper: package a single variant ---
  174. if "%BUILD_STANDARD%"=="true" (
  175. call :build_variant_standard
  176. if errorlevel 1 exit /b 1
  177. )
  178. if "%BUILD_GUI_ONLY%"=="true" (
  179. call :build_variant_gui_only
  180. if errorlevel 1 exit /b 1
  181. )
  182. echo [INFO] Build completed successfully!
  183. echo [INFO] Extension packages created in: %PLUGIN_DIR%
  184. echo Packages created:
  185. for %%F in ("%PLUGIN_DIR%\*.vsix") do echo %%~nxF
  186. endlocal
  187. exit /b 0
  188. REM --- Build variant: standard ---
  189. :build_variant_standard
  190. echo [INFO] === Packaging STANDARD variant ===
  191. cd /d "%PLUGIN_DIR%"
  192. REM Check for required binaries
  193. echo [INFO] Checking for required binaries...
  194. set "MISSING_BINARIES=false"
  195. if not exist "resources\bin\windows\amd64\opencode.exe" (
  196. echo [WARN] Missing binary: resources\bin\windows\amd64\opencode.exe
  197. set "MISSING_BINARIES=true"
  198. )
  199. if not exist "resources\bin\macos\amd64\opencode" (
  200. echo [WARN] Missing binary: resources\bin\macos\amd64\opencode
  201. set "MISSING_BINARIES=true"
  202. )
  203. if not exist "resources\bin\macos\arm64\opencode" (
  204. echo [WARN] Missing binary: resources\bin\macos\arm64\opencode
  205. set "MISSING_BINARIES=true"
  206. )
  207. if not exist "resources\bin\linux\amd64\opencode" (
  208. echo [WARN] Missing binary: resources\bin\linux\amd64\opencode
  209. set "MISSING_BINARIES=true"
  210. )
  211. if not exist "resources\bin\linux\arm64\opencode" (
  212. echo [WARN] Missing binary: resources\bin\linux\arm64\opencode
  213. set "MISSING_BINARIES=true"
  214. )
  215. if "%MISSING_BINARIES%"=="true" (
  216. echo [WARN] Some binaries are missing. The extension may not work on all platforms.
  217. echo [WARN] Run 'hosts\scripts\build_opencode.bat' from the repository root to build all binaries.
  218. )
  219. REM Package with original package.json and .vscodeignore
  220. if "%BUILD_TYPE%"=="production" (
  221. call %VSCE_CMD% package --no-dependencies --out "opencode-vscode-%TIMESTAMP%.vsix"
  222. ) else (
  223. call %VSCE_CMD% package --pre-release --no-dependencies --out "opencode-vscode-dev-%TIMESTAMP%.vsix"
  224. )
  225. if errorlevel 1 exit /b 1
  226. echo [INFO] Standard variant packaged successfully
  227. exit /b 0
  228. REM --- Build variant: gui-only ---
  229. :build_variant_gui_only
  230. echo [INFO] === Packaging GUI-ONLY variant ===
  231. cd /d "%PLUGIN_DIR%"
  232. REM Always rebuild webgui to pick up source changes
  233. REM The monorepo uses bun workspaces a deps are already installed at root level
  234. echo [INFO] Building webgui...
  235. cd /d "%WEBGUI_DIR%"
  236. where bun >nul 2>&1
  237. if not errorlevel 1 (
  238. call bun run build
  239. ) else (
  240. call npm run build
  241. )
  242. cd /d "%PLUGIN_DIR%"
  243. if not exist "%WEBGUI_DIST%" (
  244. echo [ERROR] webgui-dist not found at %WEBGUI_DIST% after build
  245. exit /b 1
  246. )
  247. REM Copy webgui-dist into plugin resources for embedding
  248. echo [INFO] Embedding webgui-dist into plugin resources...
  249. if exist "resources\webgui-app" rmdir /s /q "resources\webgui-app"
  250. xcopy /s /e /i "%WEBGUI_DIST%" "resources\webgui-app\" >nul
  251. REM Move binaries completely outside the plugin tree so vsce cannot bundle them
  252. set "BIN_STASH=%TEMP%\opencode_bin_stash_%RANDOM%"
  253. if exist "resources\bin" (
  254. mkdir "%BIN_STASH%"
  255. move "resources\bin" "%BIN_STASH%\bin" >nul
  256. )
  257. REM Temporarily swap package.json with gui-only overrides and .vscodeignore
  258. copy "%PLUGIN_DIR%\package.json" "%PLUGIN_DIR%\package.json.bak" >nul
  259. copy "%PLUGIN_DIR%\.vscodeignore" "%PLUGIN_DIR%\.vscodeignore.bak" >nul
  260. REM Deep-merge gui-only overrides into package.json using PowerShell's built-in JSON support
  261. powershell -NoProfile -Command "$b=Get-Content 'package.json'|ConvertFrom-Json;$o=Get-Content 'package.gui-only.json'|ConvertFrom-Json;function m($t,$s){foreach($p in $s.PSObject.Properties){$v=$p.Value;if($v-is[array]-and$t.($p.Name)-is[array]){$a=$t.($p.Name);for($i=0;$i-lt$v.Count;$i++){if($i-lt$a.Count-and$v[$i]-is[pscustomobject]){m $a[$i] $v[$i]}else{$a[$i]=$v[$i]}}}elseif($v-is[pscustomobject]-and$t.($p.Name)-is[pscustomobject]){m $t.($p.Name) $v}else{$t|Add-Member -MemberType NoteProperty -Name $p.Name -Value $v -Force}}};m $b $o;$b|ConvertTo-Json -Depth 100|Set-Content 'package.json'"
  262. if errorlevel 1 (
  263. echo [ERROR] Failed to merge gui-only package.json overrides
  264. call :gui_only_cleanup
  265. exit /b 1
  266. )
  267. REM Swap .vscodeignore
  268. copy "%PLUGIN_DIR%\.vscodeignore.gui-only" "%PLUGIN_DIR%\.vscodeignore" >nul
  269. REM Package gui-only variant
  270. if "%BUILD_TYPE%"=="production" (
  271. call %VSCE_CMD% package --no-dependencies --out "opencode-vscode-gui-only-%TIMESTAMP%.vsix"
  272. ) else (
  273. call %VSCE_CMD% package --pre-release --no-dependencies --out "opencode-vscode-gui-only-dev-%TIMESTAMP%.vsix"
  274. )
  275. set "PACKAGE_RESULT=%ERRORLEVEL%"
  276. REM Restore originals
  277. call :gui_only_cleanup
  278. if "%PACKAGE_RESULT%"=="1" exit /b 1
  279. echo [INFO] GUI-only variant packaged successfully
  280. exit /b 0
  281. REM --- Cleanup helper for gui-only ---
  282. :gui_only_cleanup
  283. cd /d "%PLUGIN_DIR%"
  284. if exist "package.json.bak" (
  285. move /y "package.json.bak" "package.json" >nul
  286. )
  287. if exist ".vscodeignore.bak" (
  288. move /y ".vscodeignore.bak" ".vscodeignore" >nul
  289. )
  290. if exist "%BIN_STASH%\bin" (
  291. if exist "resources\bin" rmdir /s /q "resources\bin"
  292. move "%BIN_STASH%\bin" "resources\bin" >nul
  293. )
  294. if exist "%BIN_STASH%" rmdir /s /q "%BIN_STASH%"
  295. if exist "resources\webgui-app" rmdir /s /q "resources\webgui-app"
  296. exit /b 0