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
This commit is contained in:
oho 2026-02-13 18:30:44 +01:00
parent e6246286fb
commit c34f1edab2
3 changed files with 77 additions and 116 deletions

View file

@ -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 ""

View file

@ -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
<string>${VERSION}</string>
<key>CFBundleExecutable</key>
<string>KnowledgeRefinery</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>LSMinimumSystemVersion</key>
<string>26.0</string>
<string>15.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>LSApplicationCategoryType</key>
@ -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" "$@"

View file

@ -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 ""