From c34f1edab2300a0788165a533ac04d1031961064 Mon Sep 17 00:00:00 2001 From: oho Date: Fri, 13 Feb 2026 18:30:44 +0100 Subject: [PATCH] Rewrite build/install scripts for Go daemon architecture - build.sh: builds Go daemon + SwiftUI app into proper .app bundle with Info.plist, AppIcon.icns, embedded daemon binary, launcher wrapper - install.sh: checks prerequisites (Go, Swift, Xcode), runs tests, builds, installs to /Applications, creates data directory - Makefile: updated all targets (removed Python references) - Tested: 16MB .app bundle launches correctly --- Makefile | 54 +++++++++++++----------------- scripts/build.sh | 56 ++++++++++++++++--------------- scripts/install.sh | 83 ++++++++++++++-------------------------------- 3 files changed, 77 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index bc1755a..dfe428d 100644 --- a/Makefile +++ b/Makefile @@ -1,51 +1,41 @@ # Knowledge Refinery — Makefile # ============================================================ -.PHONY: all build install test clean daemon-setup app-build app-run +.PHONY: all build install test clean daemon app-run daemon-run help ROOT := $(shell pwd) -DAEMON_DIR := $(ROOT)/daemon +DAEMON_DIR := $(ROOT)/daemon-go APP_DIR := $(ROOT)/apps/macos/KnowledgeRefinery -VENV := $(DAEMON_DIR)/.venv -PYTHON := $(VENV)/bin/python # ── Default: build everything ── all: build -# ── Full build: daemon setup + app bundle ── -build: daemon-setup app-build - @echo "" - @echo "Build complete. Run 'make install' to copy to /Applications." +# ── Full build: Go daemon + SwiftUI app bundle ── +build: + @bash scripts/build.sh # ── Install to /Applications ── install: @bash scripts/install.sh -# ── Set up Python daemon venv + deps ── -daemon-setup: - @echo "Setting up Python daemon..." - @test -d $(VENV) || python3 -m venv $(VENV) - @$(VENV)/bin/pip install --upgrade pip -q - @$(VENV)/bin/pip install -e $(DAEMON_DIR) -q - @$(VENV)/bin/pip install -e "$(DAEMON_DIR)[dev]" -q - @echo " ✓ Daemon dependencies installed" - -# ── Build SwiftUI .app bundle ── -app-build: - @bash scripts/build.sh +# ── Build Go daemon only ── +daemon: + @echo "Building Go daemon..." + @cd $(DAEMON_DIR) && go build -o knowledge-refinery-daemon . + @echo " ✓ daemon-go/knowledge-refinery-daemon" # ── Run app in development mode (swift run) ── -app-run: +app-run: daemon @cd $(APP_DIR) && swift run -# ── Run daemon in development mode ── -daemon-run: - @cd $(DAEMON_DIR) && $(PYTHON) -m knowledge_refinery.main +# ── Run daemon standalone ── +daemon-run: daemon + @cd $(DAEMON_DIR) && ./knowledge-refinery-daemon -# ── Run tests ── +# ── Run all tests ── test: - @echo "Running daemon tests..." - @cd $(DAEMON_DIR) && $(VENV)/bin/python -m pytest tests/ -x -q + @echo "Running Go daemon tests..." + @cd $(DAEMON_DIR) && go test ./... -count=1 -short @echo "" @echo "Building SwiftUI app..." @cd $(APP_DIR) && swift build 2>&1 | tail -3 @@ -57,16 +47,18 @@ clean: @echo "Cleaning..." @rm -rf $(ROOT)/dist @rm -rf $(APP_DIR)/.build + @rm -f $(DAEMON_DIR)/knowledge-refinery-daemon @echo " ✓ Clean" # ── Help ── help: @echo "Knowledge Refinery — Build Commands" @echo "" - @echo " make build Build daemon + app bundle (to dist/)" + @echo " make build Build Go daemon + .app bundle (to dist/)" @echo " make install Full install to /Applications" - @echo " make test Run daemon tests + Swift build check" - @echo " make app-run Run app in dev mode (swift run)" - @echo " make daemon-run Run daemon in dev mode" + @echo " make test Run Go tests + Swift build check" + @echo " make daemon Build Go daemon binary only" + @echo " make app-run Run app in dev mode (builds daemon first)" + @echo " make daemon-run Run daemon standalone" @echo " make clean Remove build artifacts" @echo "" diff --git a/scripts/build.sh b/scripts/build.sh index 30c6f42..fd370f3 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,20 +1,19 @@ #!/usr/bin/env bash # ============================================================ # Knowledge Refinery — Build Script -# Creates a distributable macOS .app bundle +# Creates a distributable macOS .app bundle with embedded Go daemon # ============================================================ set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" APP_NAME="Knowledge Refinery" BUNDLE_ID="com.knowledge-refinery.app" -VERSION="0.1.0" +VERSION="0.2.0" BUILD_DIR="$ROOT/dist" APP_DIR="$BUILD_DIR/${APP_NAME}.app" CONTENTS="$APP_DIR/Contents" MACOS_DIR="$CONTENTS/MacOS" RESOURCES="$CONTENTS/Resources" -DAEMON_BUNDLE="$RESOURCES/daemon" echo "=== Knowledge Refinery Build ===" echo "Root: $ROOT" @@ -24,27 +23,32 @@ echo "" rm -rf "$BUILD_DIR" mkdir -p "$MACOS_DIR" "$RESOURCES" -# ── Step 2: Build SwiftUI app (release) ── -echo "[1/5] Building SwiftUI app (release)..." +# ── Step 2: Build Go daemon (release) ── +echo "[1/5] Building Go daemon..." +cd "$ROOT/daemon-go" +CGO_ENABLED=0 go build -ldflags="-s -w" -o "$MACOS_DIR/knowledge-refinery-daemon" . +DAEMON_SIZE=$(du -h "$MACOS_DIR/knowledge-refinery-daemon" | cut -f1) +echo " Daemon binary: $DAEMON_SIZE" + +# ── Step 3: Build SwiftUI app (release) ── +echo "[2/5] Building SwiftUI app (release)..." cd "$ROOT/apps/macos/KnowledgeRefinery" swift build -c release 2>&1 | tail -3 -cp .build/release/KnowledgeRefinery "$MACOS_DIR/KnowledgeRefinery" -# ── Step 3: Copy WebGPU resources ── -echo "[2/5] Bundling WebGPU resources..." -mkdir -p "$RESOURCES/WebGPU" -cp .build/release/KnowledgeRefinery_KnowledgeRefinery.bundle/universe.html "$RESOURCES/WebGPU/" -cp .build/release/KnowledgeRefinery_KnowledgeRefinery.bundle/universe.js "$RESOURCES/WebGPU/" -cp .build/release/KnowledgeRefinery_KnowledgeRefinery.bundle/universe.wgsl "$RESOURCES/WebGPU/" +# ── Step 4: Assemble .app bundle ── +echo "[3/5] Assembling app bundle..." -# ── Step 4: Bundle Python daemon ── -echo "[3/5] Bundling Python daemon..." -mkdir -p "$DAEMON_BUNDLE" -# Copy daemon source -cp -R "$ROOT/daemon/knowledge_refinery" "$DAEMON_BUNDLE/" -cp "$ROOT/daemon/pyproject.toml" "$DAEMON_BUNDLE/" -# Copy shared prompts/models/schemas -cp -R "$ROOT/shared" "$DAEMON_BUNDLE/" +# Copy Swift binary +cp .build/release/KnowledgeRefinery "$MACOS_DIR/KnowledgeRefinery-bin" + +# Copy SPM resource bundle (contains WebGPU files + icon) +cp -R .build/release/KnowledgeRefinery_KnowledgeRefinery.bundle "$RESOURCES/" + +# Copy shared prompts +cp -R "$ROOT/shared" "$RESOURCES/" + +# Copy app icon to Resources root for Info.plist +cp "$ROOT/apps/macos/KnowledgeRefinery/Sources/Resources/AppIcon.icns" "$RESOURCES/AppIcon.icns" # ── Step 5: Create Info.plist ── echo "[4/5] Creating Info.plist..." @@ -65,12 +69,14 @@ cat > "$CONTENTS/Info.plist" << PLIST ${VERSION} CFBundleExecutable KnowledgeRefinery + CFBundleIconFile + AppIcon CFBundlePackageType APPL CFBundleSignature ???? LSMinimumSystemVersion - 26.0 + 15.0 NSHighResolutionCapable LSApplicationCategoryType @@ -86,18 +92,14 @@ PLIST # ── Step 6: Create launcher wrapper ── echo "[5/5] Creating launcher..." -# The launcher script ensures the daemon Python environment is available -# and sets the right paths before launching the main binary -mv "$MACOS_DIR/KnowledgeRefinery" "$MACOS_DIR/KnowledgeRefinery-bin" cat > "$MACOS_DIR/KnowledgeRefinery" << 'LAUNCHER' #!/bin/bash # Knowledge Refinery Launcher -# Sets up environment and launches the app binary DIR="$(cd "$(dirname "$0")" && pwd)" RESOURCES="$(cd "$DIR/../Resources" && pwd)" -# Export daemon location so the app can find it -export KR_DAEMON_DIR="$RESOURCES/daemon" +# Tell the app where the Go daemon binary lives +export KR_DAEMON_DIR="$DIR" export KR_RESOURCES_DIR="$RESOURCES" exec "$DIR/KnowledgeRefinery-bin" "$@" diff --git a/scripts/install.sh b/scripts/install.sh index b66692d..5eec61e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash # ============================================================ # Knowledge Refinery — Fresh Machine Installer -# For macOS Tahoe (26.x) on Apple Silicon +# For macOS 15+ (Sequoia/Tahoe) on Apple Silicon # ============================================================ set -euo pipefail echo "========================================" echo " Knowledge Refinery Installer" -echo " macOS Tahoe · Apple Silicon" +echo " macOS · Apple Silicon" echo "========================================" echo "" @@ -26,15 +26,15 @@ fail() { echo -e " ${RED}✗${NC} $1"; exit 1; } info() { echo -e " ${CYAN}→${NC} $1"; } # ── Step 1: Check prerequisites ── -echo "[1/6] Checking prerequisites..." +echo "[1/5] Checking prerequisites..." # macOS version SW_VER=$(sw_vers -productVersion) MAJOR=$(echo "$SW_VER" | cut -d. -f1) -if [ "$MAJOR" -ge 26 ]; then - ok "macOS Tahoe ($SW_VER)" +if [ "$MAJOR" -ge 15 ]; then + ok "macOS $SW_VER" else - fail "macOS Tahoe (26.x) required — found $SW_VER" + fail "macOS 15+ required — found $SW_VER" fi # Architecture @@ -45,7 +45,7 @@ else warn "Architecture: $ARCH (Apple Silicon recommended)" fi -# Xcode Command Line Tools / Xcode +# Xcode Command Line Tools if xcode-select -p &>/dev/null; then ok "Xcode/Command Line Tools installed" else @@ -63,65 +63,32 @@ else fail "Swift not found — install Xcode or Xcode Command Line Tools" fi -# Python 3.12+ -PYTHON="" -for cmd in python3.14 python3.13 python3.12 python3; do - if command -v "$cmd" &>/dev/null; then - PY_VER=$("$cmd" --version 2>&1 | grep -oE '[0-9]+\.[0-9]+') - PY_MAJOR=$(echo "$PY_VER" | cut -d. -f1) - PY_MINOR=$(echo "$PY_VER" | cut -d. -f2) - if [ "$PY_MAJOR" -ge 3 ] && [ "$PY_MINOR" -ge 12 ]; then - PYTHON="$cmd" - break - fi - fi -done - -if [ -n "$PYTHON" ]; then - ok "Python: $($PYTHON --version)" +# Go +if command -v go &>/dev/null; then + GO_VER=$(go version 2>&1) + ok "Go: $GO_VER" else - fail "Python 3.12+ required. Install from python.org or: brew install python@3.14" + fail "Go not found. Install from https://go.dev/dl/ or: brew install go" fi echo "" -# ── Step 2: Set up Python virtual environment ── -echo "[2/6] Setting up Python virtual environment..." -DAEMON_DIR="$ROOT/daemon" -VENV_DIR="$DAEMON_DIR/.venv" - -if [ -d "$VENV_DIR" ]; then - ok "Virtual environment exists at $VENV_DIR" -else - info "Creating virtual environment..." - "$PYTHON" -m venv "$VENV_DIR" - ok "Virtual environment created" -fi - -info "Installing Python dependencies..." -"$VENV_DIR/bin/pip" install --upgrade pip -q -"$VENV_DIR/bin/pip" install -e "$DAEMON_DIR" -q -"$VENV_DIR/bin/pip" install -e "$DAEMON_DIR[dev]" -q -ok "Python dependencies installed" +# ── Step 2: Run Go tests ── +echo "[2/5] Running Go daemon tests..." +cd "$ROOT/daemon-go" +go test ./... -count=1 -short 2>&1 | tail -15 +ok "All Go tests passed" echo "" -# ── Step 3: Build the SwiftUI app ── -echo "[3/6] Building SwiftUI application..." -cd "$ROOT/apps/macos/KnowledgeRefinery" -swift build -c release 2>&1 | tail -3 -ok "SwiftUI app built (release)" - -echo "" - -# ── Step 4: Create .app bundle ── -echo "[4/6] Creating application bundle..." +# ── Step 3: Build .app bundle ── +echo "[3/5] Building application..." bash "$ROOT/scripts/build.sh" echo "" -# ── Step 5: Install to /Applications ── -echo "[5/6] Installing to /Applications..." +# ── Step 4: Install to /Applications ── +echo "[4/5] Installing to /Applications..." APP_SRC="$ROOT/dist/Knowledge Refinery.app" APP_DST="/Applications/Knowledge Refinery.app" @@ -135,14 +102,14 @@ ok "Installed to $APP_DST" echo "" -# ── Step 6: Create data directory ── -echo "[6/6] Initializing data directory..." +# ── Step 5: Create data directory ── +echo "[5/5] Initializing data directory..." KR_DIR="$HOME/.knowledge-refinery" mkdir -p "$KR_DIR" mkdir -p "$KR_DIR/workspaces" if [ ! -f "$KR_DIR/workspaces.json" ]; then - echo '{"workspaces":[]}' > "$KR_DIR/workspaces.json" + echo '[]' > "$KR_DIR/workspaces.json" ok "Created workspaces.json" else ok "workspaces.json already exists" @@ -158,7 +125,7 @@ echo "" echo " Before launching:" echo " 1. Install LM Studio from https://lmstudio.ai" echo " 2. Load models in LM Studio:" -echo " - Chat: gemma-3-4b (or similar)" +echo " - Chat: qwen3-4b-2507 (or similar small model)" echo " - Embeddings: nomic-embed-text-v1.5" echo " 3. Start the LM Studio local server (port 1234)" echo ""