|
|
@@ -1,7 +1,13 @@
|
|
|
#!/bin/bash
|
|
|
|
|
|
# Opencode VSCode Extension Build Script
|
|
|
-# This script handles the complete build process for the Opencode VSCode extension
|
|
|
+# This script handles the complete build process for the Opencode VSCode extension.
|
|
|
+# Supports building two variants:
|
|
|
+# - Standard: bundles opencode binaries (default)
|
|
|
+# - GUI-only: no binaries, uses system opencode, embeds webgui-dist
|
|
|
+#
|
|
|
+# By default both variants are built. Use --gui-only or --standard-only to
|
|
|
+# build a single variant.
|
|
|
|
|
|
set -e
|
|
|
|
|
|
@@ -16,6 +22,8 @@ NC='\033[0m' # No Color
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
PLUGIN_DIR="$ROOT_DIR/hosts/vscode-plugin"
|
|
|
+WEBGUI_DIR="$ROOT_DIR/packages/opencode/webgui"
|
|
|
+WEBGUI_DIST="$ROOT_DIR/packages/opencode/webgui-dist"
|
|
|
|
|
|
echo -e "${BLUE}Opencode VSCode Extension Build Script${NC}"
|
|
|
echo "Plugin directory: $PLUGIN_DIR"
|
|
|
@@ -23,13 +31,9 @@ echo "Root directory: $ROOT_DIR"
|
|
|
|
|
|
# --- Package manager helpers ---
|
|
|
PNPM_AVAILABLE=false
|
|
|
-RUN_PM="npm run"
|
|
|
-INSTALL_PM="npm ci || npm install"
|
|
|
|
|
|
if command -v pnpm >/dev/null 2>&1; then
|
|
|
PNPM_AVAILABLE=true
|
|
|
- RUN_PM="pnpm run"
|
|
|
- INSTALL_PM="pnpm install --frozen-lockfile"
|
|
|
fi
|
|
|
|
|
|
run_install() {
|
|
|
@@ -70,6 +74,8 @@ BUILD_TYPE="development"
|
|
|
SKIP_BINARIES=false
|
|
|
SKIP_TESTS=false
|
|
|
PACKAGE_ONLY=false
|
|
|
+BUILD_STANDARD=true
|
|
|
+BUILD_GUI_ONLY=true
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
case $1 in
|
|
|
@@ -89,6 +95,16 @@ while [[ $# -gt 0 ]]; do
|
|
|
PACKAGE_ONLY=true
|
|
|
shift
|
|
|
;;
|
|
|
+ --gui-only)
|
|
|
+ BUILD_STANDARD=false
|
|
|
+ BUILD_GUI_ONLY=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --standard-only)
|
|
|
+ BUILD_STANDARD=true
|
|
|
+ BUILD_GUI_ONLY=false
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
--help)
|
|
|
echo "Usage: $0 [OPTIONS]"
|
|
|
echo "Options:"
|
|
|
@@ -96,6 +112,8 @@ while [[ $# -gt 0 ]]; do
|
|
|
echo " --skip-binaries Skip building backend binaries"
|
|
|
echo " --skip-tests Skip running tests"
|
|
|
echo " --package-only Only create the .vsix package (skip compilation)"
|
|
|
+ echo " --gui-only Build only the gui-only variant (no binaries)"
|
|
|
+ echo " --standard-only Build only the standard variant (with binaries)"
|
|
|
echo " --help Show this help message"
|
|
|
exit 0
|
|
|
;;
|
|
|
@@ -107,9 +125,13 @@ while [[ $# -gt 0 ]]; do
|
|
|
done
|
|
|
|
|
|
print_status "Building VSCode extension in $BUILD_TYPE mode"
|
|
|
+[ "$BUILD_STANDARD" = true ] && print_status " Variant: standard (with binaries)"
|
|
|
+[ "$BUILD_GUI_ONLY" = true ] && print_status " Variant: gui-only (system opencode)"
|
|
|
|
|
|
cd "$PLUGIN_DIR"
|
|
|
|
|
|
+# ─── Shared preparation (compile once, package per-variant) ───────────────
|
|
|
+
|
|
|
if [ "$PACKAGE_ONLY" = false ]; then
|
|
|
print_status "Cleaning previous build artifacts..."
|
|
|
set +e
|
|
|
@@ -139,7 +161,7 @@ if [ "$PACKAGE_ONLY" = false ]; then
|
|
|
run_install
|
|
|
fi
|
|
|
|
|
|
-if [ "$SKIP_BINARIES" = false ] && [ "$PACKAGE_ONLY" = false ]; then
|
|
|
+if [ "$SKIP_BINARIES" = false ] && [ "$PACKAGE_ONLY" = false ] && [ "$BUILD_STANDARD" = true ]; then
|
|
|
print_status "Building backend binaries..."
|
|
|
"$SCRIPT_DIR/build_opencode.sh"
|
|
|
fi
|
|
|
@@ -173,29 +195,8 @@ if [ "$SKIP_TESTS" = false ] && [ "$PACKAGE_ONLY" = false ]; then
|
|
|
set -e
|
|
|
fi
|
|
|
|
|
|
-print_status "Checking for required binaries..."
|
|
|
-BINARY_PATHS=(
|
|
|
- "resources/bin/windows/amd64/opencode.exe"
|
|
|
- "resources/bin/macos/amd64/opencode"
|
|
|
- "resources/bin/macos/arm64/opencode"
|
|
|
- "resources/bin/linux/amd64/opencode"
|
|
|
- "resources/bin/linux/arm64/opencode"
|
|
|
-)
|
|
|
-
|
|
|
-MISSING_BINARIES=false
|
|
|
-for binary_path in "${BINARY_PATHS[@]}"; do
|
|
|
- if [ ! -f "$binary_path" ]; then
|
|
|
- print_warning "Missing binary: $binary_path"
|
|
|
- MISSING_BINARIES=true
|
|
|
- fi
|
|
|
-done
|
|
|
-
|
|
|
-if [ "$MISSING_BINARIES" = true ]; then
|
|
|
- print_warning "Some binaries are missing. The extension may not work on all platforms."
|
|
|
- print_warning "Run '$SCRIPT_DIR/build_opencode.sh' from the root directory to build all binaries."
|
|
|
-fi
|
|
|
+# ─── Resolve vsce command ────────────────────────────────────────────────
|
|
|
|
|
|
-print_status "Creating VSCode extension package..."
|
|
|
VSCE_CMD="vsce"
|
|
|
if ! command -v vsce >/dev/null 2>&1; then
|
|
|
if command -v npx >/dev/null 2>&1; then
|
|
|
@@ -206,21 +207,160 @@ if ! command -v vsce >/dev/null 2>&1; then
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
-if [ "$BUILD_TYPE" = "production" ]; then
|
|
|
- eval "$VSCE_CMD package --no-dependencies --out 'opencode-vscode-$(date +%Y%m%d-%H%M%S).vsix'"
|
|
|
-else
|
|
|
- eval "$VSCE_CMD package --pre-release --no-dependencies --out 'opencode-vscode-dev-$(date +%Y%m%d-%H%M%S).vsix'"
|
|
|
+TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
|
|
|
+
|
|
|
+# ─── Build helper: package a single variant ──────────────────────────────
|
|
|
+
|
|
|
+build_variant() {
|
|
|
+ local variant="$1" # "standard" or "gui-only"
|
|
|
+
|
|
|
+ cd "$PLUGIN_DIR"
|
|
|
+
|
|
|
+ if [ "$variant" = "standard" ]; then
|
|
|
+ print_status "=== Packaging STANDARD variant ==="
|
|
|
+
|
|
|
+ # Check for required binaries
|
|
|
+ BINARY_PATHS=(
|
|
|
+ "resources/bin/windows/amd64/opencode.exe"
|
|
|
+ "resources/bin/macos/amd64/opencode"
|
|
|
+ "resources/bin/macos/arm64/opencode"
|
|
|
+ "resources/bin/linux/amd64/opencode"
|
|
|
+ "resources/bin/linux/arm64/opencode"
|
|
|
+ )
|
|
|
+
|
|
|
+ MISSING_BINARIES=false
|
|
|
+ for binary_path in "${BINARY_PATHS[@]}"; do
|
|
|
+ if [ ! -f "$binary_path" ]; then
|
|
|
+ print_warning "Missing binary: $binary_path"
|
|
|
+ MISSING_BINARIES=true
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [ "$MISSING_BINARIES" = true ]; then
|
|
|
+ print_warning "Some binaries are missing. The extension may not work on all platforms."
|
|
|
+ print_warning "Run '$SCRIPT_DIR/build_opencode.sh' from the root directory to build all binaries."
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Package with original package.json and .vscodeignore
|
|
|
+ if [ "$BUILD_TYPE" = "production" ]; then
|
|
|
+ eval "$VSCE_CMD package --no-dependencies --out 'opencode-vscode-${TIMESTAMP}.vsix'"
|
|
|
+ else
|
|
|
+ eval "$VSCE_CMD package --pre-release --no-dependencies --out 'opencode-vscode-dev-${TIMESTAMP}.vsix'"
|
|
|
+ fi
|
|
|
+
|
|
|
+ elif [ "$variant" = "gui-only" ]; then
|
|
|
+ print_status "=== Packaging GUI-ONLY variant ==="
|
|
|
+
|
|
|
+ # Build webgui if webgui-dist doesn't exist yet
|
|
|
+ if [ ! -d "$WEBGUI_DIST" ] || [ -z "$(ls -A "$WEBGUI_DIST" 2>/dev/null)" ]; then
|
|
|
+ print_status "Building webgui..."
|
|
|
+ (
|
|
|
+ cd "$WEBGUI_DIR"
|
|
|
+ run_install
|
|
|
+ if $PNPM_AVAILABLE; then
|
|
|
+ pnpm run build
|
|
|
+ else
|
|
|
+ npm run build
|
|
|
+ fi
|
|
|
+ )
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ ! -d "$WEBGUI_DIST" ]; then
|
|
|
+ print_error "webgui-dist not found at $WEBGUI_DIST after build"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Copy webgui-dist into plugin resources for embedding
|
|
|
+ print_status "Embedding webgui-dist into plugin resources..."
|
|
|
+ rm -rf "$PLUGIN_DIR/resources/webgui-app"
|
|
|
+ cp -r "$WEBGUI_DIST" "$PLUGIN_DIR/resources/webgui-app"
|
|
|
+
|
|
|
+ # Move binaries completely outside the plugin tree so vsce cannot bundle them
|
|
|
+ BIN_STASH="$(mktemp -d)"
|
|
|
+ if [ -d "$PLUGIN_DIR/resources/bin" ]; then
|
|
|
+ mv "$PLUGIN_DIR/resources/bin" "$BIN_STASH/bin"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Temporarily swap package.json with gui-only overrides and .vscodeignore
|
|
|
+ cp "$PLUGIN_DIR/package.json" "$PLUGIN_DIR/package.json.bak"
|
|
|
+ cp "$PLUGIN_DIR/.vscodeignore" "$PLUGIN_DIR/.vscodeignore.bak"
|
|
|
+
|
|
|
+ # Ensure originals are restored even on failure
|
|
|
+ gui_only_cleanup() {
|
|
|
+ cd "$PLUGIN_DIR"
|
|
|
+ [ -f package.json.bak ] && mv package.json.bak package.json
|
|
|
+ [ -f .vscodeignore.bak ] && mv .vscodeignore.bak .vscodeignore
|
|
|
+ [ -d "$BIN_STASH/bin" ] && mv "$BIN_STASH/bin" resources/bin
|
|
|
+ rm -rf "$BIN_STASH"
|
|
|
+ rm -rf resources/webgui-app
|
|
|
+ }
|
|
|
+ trap gui_only_cleanup EXIT
|
|
|
+
|
|
|
+ # Deep-merge gui-only overrides into package.json
|
|
|
+ node -e "
|
|
|
+ const fs = require('fs');
|
|
|
+ function deep(target, src) {
|
|
|
+ for (const key of Object.keys(src)) {
|
|
|
+ const s = src[key];
|
|
|
+ const t = target[key];
|
|
|
+ if (Array.isArray(s) && Array.isArray(t)) {
|
|
|
+ for (let i = 0; i < s.length; i++) {
|
|
|
+ if (i < t.length && typeof s[i] === 'object' && typeof t[i] === 'object') {
|
|
|
+ deep(t[i], s[i]);
|
|
|
+ } else {
|
|
|
+ t[i] = s[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (s && typeof s === 'object' && !Array.isArray(s) && t && typeof t === 'object' && !Array.isArray(t)) {
|
|
|
+ deep(t, s);
|
|
|
+ } else {
|
|
|
+ target[key] = s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return target;
|
|
|
+ }
|
|
|
+ const base = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
|
+ const overrides = JSON.parse(fs.readFileSync('package.gui-only.json', 'utf8'));
|
|
|
+ fs.writeFileSync('package.json', JSON.stringify(deep(base, overrides), null, 2) + '\n');
|
|
|
+ "
|
|
|
+
|
|
|
+ # Swap .vscodeignore
|
|
|
+ cp "$PLUGIN_DIR/.vscodeignore.gui-only" "$PLUGIN_DIR/.vscodeignore"
|
|
|
+
|
|
|
+ # Package gui-only variant
|
|
|
+ if [ "$BUILD_TYPE" = "production" ]; then
|
|
|
+ eval "$VSCE_CMD package --no-dependencies --out 'opencode-vscode-gui-only-${TIMESTAMP}.vsix'"
|
|
|
+ else
|
|
|
+ eval "$VSCE_CMD package --pre-release --no-dependencies --out 'opencode-vscode-gui-only-dev-${TIMESTAMP}.vsix'"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Restore originals (also handled by trap on failure)
|
|
|
+ gui_only_cleanup
|
|
|
+ trap - EXIT
|
|
|
+
|
|
|
+ print_status "GUI-only variant packaged successfully"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# ─── Build requested variants ────────────────────────────────────────────
|
|
|
+
|
|
|
+if [ "$BUILD_STANDARD" = true ]; then
|
|
|
+ build_variant "standard"
|
|
|
+fi
|
|
|
+
|
|
|
+if [ "$BUILD_GUI_ONLY" = true ]; then
|
|
|
+ build_variant "gui-only"
|
|
|
fi
|
|
|
|
|
|
print_status "Build completed successfully!"
|
|
|
-print_status "Extension package created in: $PLUGIN_DIR"
|
|
|
+print_status "Extension packages created in: $PLUGIN_DIR"
|
|
|
|
|
|
shopt -s nullglob
|
|
|
-VSIX_FILES=( *.vsix )
|
|
|
+VSIX_FILES=( "$PLUGIN_DIR"/*.vsix )
|
|
|
shopt -u nullglob
|
|
|
if ((${#VSIX_FILES[@]} > 0)); then
|
|
|
echo "Packages created:"
|
|
|
for vsix in "${VSIX_FILES[@]}"; do
|
|
|
- echo " $vsix"
|
|
|
+ echo " $(basename "$vsix")"
|
|
|
done
|
|
|
fi
|