mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
refactor(justfile): rename, relay auto-start, bootstrap, DRY cleanup (#1117)
This commit is contained in:
@@ -55,8 +55,11 @@ pinning. Activate it once per shell session:
|
||||
. ./bin/activate-hermit
|
||||
```
|
||||
|
||||
Hermit pins Rust, `just`, and other tools to the versions in `bin/`. If you
|
||||
don't use Hermit, make sure your Rust toolchain meets the minimum version.
|
||||
Hermit pins Rust, `just`, Node, pnpm, and other tools to the versions in
|
||||
`bin/`. Each tool is downloaded on first use. You can also run `just bootstrap`
|
||||
(which `just setup` calls automatically) to pre-download all required tools
|
||||
upfront. If you don't use Hermit, ensure your toolchain meets the minimum
|
||||
versions in the table above.
|
||||
|
||||
### First-Time Setup
|
||||
|
||||
@@ -68,30 +71,40 @@ cd sprout
|
||||
# 2. Activate Hermit (optional but recommended)
|
||||
. ./bin/activate-hermit
|
||||
|
||||
# 3. Copy environment config
|
||||
cp .env.example .env
|
||||
|
||||
# 4. Start infrastructure + run migrations
|
||||
# 3. Bootstrap tools + infrastructure
|
||||
just setup
|
||||
|
||||
# 5. Install Git hooks (optional, recommended)
|
||||
lefthook install
|
||||
# 4. Install Git hooks (optional, recommended)
|
||||
just hooks
|
||||
```
|
||||
|
||||
`just setup` starts Docker services (Postgres on `:5432`, Redis on `:6379`,
|
||||
`just setup` runs `just bootstrap` first — it copies `.env.example` to `.env`
|
||||
if it doesn't already exist, and invokes `cargo`, `node`, and `pnpm` to trigger
|
||||
Hermit's lazy tool download (each tool is fetched once on first invocation and
|
||||
cached thereafter). You can also run `just bootstrap` independently at any time;
|
||||
it is safe to re-run.
|
||||
|
||||
`just setup` then starts Docker services (Postgres on `:5432`, Redis on `:6379`,
|
||||
Typesense on `:8108`, Adminer on `:8082`, Keycloak on `:8180` for local
|
||||
OAuth/OIDC testing, MinIO on `:9000` for media storage, and Prometheus on
|
||||
`:9090` for metrics) and runs all pending database migrations.
|
||||
|
||||
### Running the Relay
|
||||
### Running the Relay and Desktop App
|
||||
|
||||
```bash
|
||||
just relay
|
||||
# or: cargo run -p buzz-relay
|
||||
just dev # starts the relay + desktop app in one command
|
||||
```
|
||||
|
||||
The relay listens on `ws://localhost:3000` by default. You should see log
|
||||
output confirming the WebSocket server is up and migrations have run.
|
||||
`just dev` builds all agent tools, starts the relay (`ws://localhost:3000`) in
|
||||
the background, and launches the Tauri desktop app. The relay process is
|
||||
automatically killed when you quit the app or press Ctrl+C.
|
||||
|
||||
For a split-terminal workflow (relay logs visible separately from Vite output):
|
||||
|
||||
```bash
|
||||
just relay # terminal 1 — relay on ws://localhost:3000
|
||||
just desktop-dev # terminal 2 — Vite dev server only (no Tauri shell)
|
||||
```
|
||||
|
||||
### Stopping / Resetting
|
||||
|
||||
|
||||
@@ -12,8 +12,30 @@ default:
|
||||
|
||||
# ─── Dev Environment ─────────────────────────────────────────────────────────
|
||||
|
||||
# Install required dev tools via Hermit and create .env (safe to re-run)
|
||||
bootstrap:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
# Hermit's bin/ symlinks auto-download pinned tool versions on first use.
|
||||
# Running each tool once triggers the download if not already cached.
|
||||
echo "Ensuring toolchain via Hermit..."
|
||||
cargo --version &
|
||||
node --version &
|
||||
pnpm --version &
|
||||
wait
|
||||
if ! command -v docker &>/dev/null; then
|
||||
echo "Error: Docker is required but not installed."
|
||||
echo "Install it from https://docs.docker.com/get-docker/"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f .env ]]; then
|
||||
cp .env.example .env
|
||||
echo "Created .env from .env.example — review it before running just dev."
|
||||
fi
|
||||
|
||||
# Start Docker services, run migrations, install desktop deps
|
||||
setup:
|
||||
setup: bootstrap
|
||||
./scripts/dev-setup.sh
|
||||
|
||||
# Install git hooks via lefthook
|
||||
@@ -48,13 +70,6 @@ build:
|
||||
build-release:
|
||||
cargo build --workspace --release
|
||||
|
||||
# Rebuild Typesense docs for all kind:0 (user profile) events.
|
||||
# Required once after deploying the indexer change that flattens kind:0 content
|
||||
# for searchability; new/updated profiles are indexed correctly automatically.
|
||||
# Safe to run repeatedly — Typesense upserts.
|
||||
reindex-kind0:
|
||||
cargo run --release -p buzz-relay --bin buzz-reindex-kind0
|
||||
|
||||
# Run repo lint and formatting checks
|
||||
check: fmt-check clippy desktop-check desktop-tauri-fmt-check desktop-tauri-clippy web-check mobile-check
|
||||
|
||||
@@ -113,6 +128,7 @@ fmt-all: fmt desktop-tauri-fmt mobile-fmt
|
||||
fix-all: fmt desktop-tauri-fmt desktop-fix web-fix mobile-fix
|
||||
|
||||
# Ensure sidecar placeholder binaries exist (Tauri validates externalBin at compile time)
|
||||
# Sidecar binary list must stay in sync with desktop-release-build below.
|
||||
_ensure-sidecar-stubs:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
@@ -165,6 +181,8 @@ desktop-tauri-test: _ensure-sidecar-stubs
|
||||
cd desktop/src-tauri && cargo test
|
||||
|
||||
# Build the full desktop Tauri app locally (unsigned, for testing)
|
||||
# Sidecar binary list must stay in sync with _ensure-sidecar-stubs above.
|
||||
# pnpm install is unconditional here: release builds must start from a clean dep tree.
|
||||
desktop-release-build target="aarch64-apple-darwin":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
@@ -193,31 +211,6 @@ desktop-e2e-smoke:
|
||||
desktop-e2e-integration: _ensure-migrations
|
||||
cd {{desktop_dir}} && pnpm test:e2e:integration
|
||||
|
||||
# Take desktop screenshots using the mock bridge
|
||||
desktop-screenshot *ARGS:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
just desktop-build
|
||||
cd {{desktop_dir}}
|
||||
if ! curl -sf http://127.0.0.1:4173/ >/dev/null 2>&1; then
|
||||
python3 -m http.server 4173 -d dist >/dev/null 2>&1 &
|
||||
trap "kill $! 2>/dev/null || true" EXIT
|
||||
for i in $(seq 1 20); do curl -sf http://127.0.0.1:4173/ >/dev/null && break; sleep 0.5; done
|
||||
fi
|
||||
node tests/helpers/screenshot.mjs {{ARGS}}
|
||||
|
||||
# Mesh-compute e2e: the CI-safe layers (relay mesh signaling invariants + Playwright UI)
|
||||
mesh-e2e:
|
||||
cargo test -p buzz-relay mesh_signaling
|
||||
cd {{desktop_dir}} && pnpm test:e2e:integration -- mesh-compute.spec.ts
|
||||
|
||||
# Mesh-compute Layer 1: REAL serve->client->inference on this machine (not CI)
|
||||
mesh-e2e-hardware:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export MESH_LLM_NATIVE_RUNTIME_CACHE_DIR="$(./scripts/ensure-mesh-native-runtime.sh)"
|
||||
cargo run -p buzz-relay --example mesh_serve_client_smoke
|
||||
|
||||
# Run all checks suitable for CI / pre-push (no infra needed)
|
||||
ci: check test-unit desktop-test desktop-build desktop-tauri-check desktop-tauri-test web-build mobile-test
|
||||
|
||||
@@ -240,16 +233,45 @@ test-unit:
|
||||
test-integration:
|
||||
./scripts/run-tests.sh integration
|
||||
|
||||
# Mesh-compute e2e: the CI-safe layers (relay mesh signaling invariants + Playwright UI)
|
||||
mesh-e2e:
|
||||
cargo test -p buzz-relay mesh_signaling
|
||||
cd {{desktop_dir}} && pnpm test:e2e:integration -- mesh-compute.spec.ts
|
||||
|
||||
# Mesh-compute Layer 1: REAL serve->client->inference on this machine (not CI)
|
||||
mesh-e2e-hardware:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export MESH_LLM_NATIVE_RUNTIME_CACHE_DIR="$(./scripts/ensure-mesh-native-runtime.sh)"
|
||||
cargo run -p buzz-relay --example mesh_serve_client_smoke
|
||||
|
||||
# Take desktop screenshots using the mock bridge
|
||||
desktop-screenshot *ARGS:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
just desktop-build
|
||||
cd {{desktop_dir}}
|
||||
if ! curl -sf http://127.0.0.1:4173/ >/dev/null 2>&1; then
|
||||
python3 -m http.server 4173 -d dist >/dev/null 2>&1 &
|
||||
trap "kill $! 2>/dev/null || true" EXIT
|
||||
for i in $(seq 1 20); do curl -sf http://127.0.0.1:4173/ >/dev/null && break; sleep 0.5; done
|
||||
fi
|
||||
node tests/helpers/screenshot.mjs {{ARGS}}
|
||||
|
||||
# ─── Run ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
# Start the relay server (auto-starts Docker services if needed)
|
||||
relay: _ensure-migrations
|
||||
relay: bootstrap _ensure-migrations
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
cargo run -p buzz-relay
|
||||
|
||||
# Start the relay with the built web UI served from it
|
||||
relay-web: _ensure-migrations
|
||||
relay-web: bootstrap _ensure-migrations
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
[[ -d node_modules ]] || pnpm install
|
||||
pnpm -C web build
|
||||
BUZZ_WEB_DIR=./web/dist cargo run -p buzz-relay
|
||||
@@ -266,26 +288,32 @@ proxy:
|
||||
proxy-release:
|
||||
cargo run -p buzz-proxy --release
|
||||
|
||||
# Run the desktop Tauri app in dev mode (ports and identity derived from worktree)
|
||||
dev *ARGS: _ensure-sidecar-stubs
|
||||
# Run the desktop Tauri app in dev mode with a local relay (ports and identity derived from worktree)
|
||||
dev *ARGS: bootstrap _ensure-sidecar-stubs _ensure-migrations
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cargo build -p buzz-acp -p buzz-agent -p buzz-dev-mcp -p buzz-cli -p git-credential-nostr
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
cargo build -p buzz-acp -p buzz-agent -p buzz-dev-mcp -p buzz-cli -p git-credential-nostr -p buzz-relay
|
||||
./target/debug/buzz-relay &
|
||||
RELAY_PID=$!
|
||||
cleanup() {
|
||||
[[ -n "${INSTANCE_ID:-}" ]] && ../scripts/cleanup-instance-agents.sh "$INSTANCE_ID" || true
|
||||
kill "$RELAY_PID" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
cd {{desktop_dir}}
|
||||
[[ -d node_modules ]] || pnpm install
|
||||
source ../scripts/instance-env.sh
|
||||
# Ctrl+C kills the Tauri app before its in-process sweep finishes, leaking
|
||||
# agent workers. Reap this instance's agents on exit as a backstop.
|
||||
INSTANCE_ID=$(node -e "console.log(JSON.parse(process.env.BUZZ_TAURI_CONFIG).identifier)")
|
||||
trap '../scripts/cleanup-instance-agents.sh "$INSTANCE_ID"' EXIT
|
||||
echo "Starting on Vite port ${BUZZ_VITE_PORT}, relay ${BUZZ_RELAY_URL}"
|
||||
pnpm exec tauri dev --features mesh-llm --config "$BUZZ_TAURI_CONFIG" {{ARGS}}
|
||||
|
||||
# Run the desktop app against the internal staging relay (installs deps + builds agent tools automatically)
|
||||
staging *ARGS: _ensure-sidecar-stubs
|
||||
staging *ARGS: bootstrap _ensure-sidecar-stubs
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
pnpm install
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
pnpm install # unconditional: staging must always start with a clean dep tree
|
||||
cargo build --release -p buzz-acp -p buzz-agent -p buzz-dev-mcp -p buzz-cli -p git-credential-nostr
|
||||
export MESH_LLM_NATIVE_RUNTIME_CACHE_DIR="$(./scripts/ensure-mesh-native-runtime.sh)"
|
||||
# Replace the 0-byte sidecar stub with the real CLI binary so tauri dev picks it up.
|
||||
@@ -293,12 +321,12 @@ staging *ARGS: _ensure-sidecar-stubs
|
||||
cp target/release/buzz "desktop/src-tauri/binaries/buzz-${TARGET}"
|
||||
chmod +x "desktop/src-tauri/binaries/buzz-${TARGET}"
|
||||
cd {{desktop_dir}}
|
||||
source ../scripts/instance-env.sh
|
||||
export BUZZ_RELAY_URL="wss://sprout-oss.stage.blox.sqprod.co"
|
||||
source ../scripts/instance-env.sh
|
||||
# Ctrl+C kills the Tauri app before its in-process sweep finishes, leaking
|
||||
# agent workers. Reap this instance's agents on exit as a backstop.
|
||||
INSTANCE_ID=$(node -e "console.log(JSON.parse(process.env.BUZZ_TAURI_CONFIG).identifier)")
|
||||
trap '../scripts/cleanup-instance-agents.sh "$INSTANCE_ID"' EXIT
|
||||
trap '../scripts/cleanup-instance-agents.sh "$INSTANCE_ID" || true' EXIT
|
||||
echo "Starting staging on Vite port ${BUZZ_VITE_PORT}, relay ${BUZZ_RELAY_URL}"
|
||||
pnpm exec tauri dev --features mesh-llm --config "$BUZZ_TAURI_CONFIG" {{ARGS}}
|
||||
|
||||
@@ -385,11 +413,17 @@ mobile-dev:
|
||||
# ─── Database ─────────────────────────────────────────────────────────────────
|
||||
|
||||
# Apply database migrations
|
||||
migrate: _ensure-services
|
||||
cargo run -p buzz-admin -- migrate
|
||||
migrate: _ensure-migrations
|
||||
|
||||
# ─── Utilities ────────────────────────────────────────────────────────────────
|
||||
|
||||
# Rebuild Typesense docs for all kind:0 (user profile) events.
|
||||
# Required once after deploying the indexer change that flattens kind:0 content
|
||||
# for searchability; new/updated profiles are indexed correctly automatically.
|
||||
# Safe to run repeatedly — Typesense upserts.
|
||||
reindex-kind0:
|
||||
cargo run --release -p buzz-relay --bin buzz-reindex-kind0
|
||||
|
||||
# Remove build artifacts
|
||||
clean:
|
||||
cargo clean
|
||||
@@ -584,37 +618,15 @@ release *ARGS:
|
||||
goose relay="ws://localhost:3000" agents="1" heartbeat="0" prompt="" key="$BUZZ_PRIVATE_KEY":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cargo build --release -p buzz-acp -p buzz-cli
|
||||
env_args=(
|
||||
BUZZ_RELAY_URL="{{relay}}"
|
||||
BUZZ_PRIVATE_KEY="{{key}}"
|
||||
BUZZ_ACP_AGENT_COMMAND=goose
|
||||
BUZZ_ACP_AGENT_ARGS=acp
|
||||
BUZZ_ACP_AGENTS="{{agents}}"
|
||||
GOOSE_MODE=auto
|
||||
)
|
||||
[[ -n "{{prompt}}" ]] && env_args+=(BUZZ_ACP_SYSTEM_PROMPT="{{prompt}}")
|
||||
if [[ "{{heartbeat}}" != "0" ]]; then
|
||||
env_args+=(BUZZ_ACP_HEARTBEAT_INTERVAL={{heartbeat}})
|
||||
fi
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
source ./scripts/_goose-env.sh "{{relay}}" "{{key}}" "{{agents}}" "{{heartbeat}}" "{{prompt}}"
|
||||
exec env "${env_args[@]}" ./target/release/buzz-acp
|
||||
|
||||
# Run a goose agent in the background (screen session named 'goose-agent-N')
|
||||
goose-bg relay="ws://localhost:3000" agents="1" heartbeat="0" prompt="" key="$BUZZ_PRIVATE_KEY":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cargo build --release -p buzz-acp -p buzz-cli
|
||||
env_args=(
|
||||
BUZZ_RELAY_URL="{{relay}}"
|
||||
BUZZ_PRIVATE_KEY="{{key}}"
|
||||
BUZZ_ACP_AGENT_COMMAND=goose
|
||||
BUZZ_ACP_AGENT_ARGS=acp
|
||||
BUZZ_ACP_AGENTS="{{agents}}"
|
||||
GOOSE_MODE=auto
|
||||
)
|
||||
[[ -n "{{prompt}}" ]] && env_args+=(BUZZ_ACP_SYSTEM_PROMPT="{{prompt}}")
|
||||
if [[ "{{heartbeat}}" != "0" ]]; then
|
||||
env_args+=(BUZZ_ACP_HEARTBEAT_INTERVAL={{heartbeat}})
|
||||
fi
|
||||
export PATH="{{justfile_directory()}}/bin:$PATH"
|
||||
source ./scripts/_goose-env.sh "{{relay}}" "{{key}}" "{{agents}}" "{{heartbeat}}" "{{prompt}}"
|
||||
screen -dmS goose-agent-{{agents}} bash -c "$(printf '%q ' env "${env_args[@]}") ./target/release/buzz-acp"
|
||||
echo "Agent running in screen session 'goose-agent-{{agents}}'. Attach with: screen -r goose-agent-{{agents}}"
|
||||
11
README.md
11
README.md
@@ -84,18 +84,21 @@ You'll need [Docker](https://docs.docker.com/get-docker/) and [Hermit](https://c
|
||||
**Once:**
|
||||
```bash
|
||||
git clone https://github.com/block/sprout.git && cd sprout
|
||||
. ./bin/activate-hermit # pinned toolchain
|
||||
cp .env.example .env && just setup && just build
|
||||
. ./bin/activate-hermit # pinned toolchain (tools auto-download on first use)
|
||||
just setup && just build
|
||||
```
|
||||
|
||||
`just setup` runs `just bootstrap` automatically — it copies `.env.example` to `.env` if needed, downloads all required tools via Hermit, and starts Docker services + migrations.
|
||||
|
||||
**Every day:**
|
||||
```bash
|
||||
just relay # terminal 1
|
||||
just dev # terminal 2 — desktop app opens automatically
|
||||
just dev # starts the relay + desktop app together
|
||||
```
|
||||
|
||||
Relay on `ws://localhost:3000`. Desktop app pops up. You're in.
|
||||
|
||||
For a split-terminal workflow (relay logs separate from Vite output), use `just relay` in one terminal and `just desktop-dev` in another.
|
||||
|
||||
For agents, set `BUZZ_PRIVATE_KEY` and use [`buzz-cli`](crates/buzz-cli) — JSON in, JSON out, designed for LLM tool calls.
|
||||
|
||||
---
|
||||
|
||||
26
scripts/_goose-env.sh
Executable file
26
scripts/_goose-env.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sourced by the goose and goose-bg just recipes to build shared agent env_args.
|
||||
# Usage: source scripts/_goose-env.sh <relay> <key> <agents> <heartbeat> <prompt>
|
||||
# Sets: env_args (bash array), ready for: exec env "${env_args[@]}" <binary>
|
||||
set -euo pipefail
|
||||
|
||||
_relay="$1"
|
||||
_key="$2"
|
||||
_agents="$3"
|
||||
_heartbeat="$4"
|
||||
_prompt="${5:-}"
|
||||
|
||||
cargo build --release -p buzz-acp -p buzz-cli
|
||||
|
||||
env_args=(
|
||||
BUZZ_RELAY_URL="$_relay"
|
||||
BUZZ_PRIVATE_KEY="$_key"
|
||||
BUZZ_ACP_AGENT_COMMAND=goose
|
||||
BUZZ_ACP_AGENT_ARGS=acp
|
||||
BUZZ_ACP_AGENTS="$_agents"
|
||||
GOOSE_MODE=auto
|
||||
)
|
||||
[[ -n "$_prompt" ]] && env_args+=(BUZZ_ACP_SYSTEM_PROMPT="$_prompt")
|
||||
if [[ "$_heartbeat" != "0" ]]; then
|
||||
env_args+=(BUZZ_ACP_HEARTBEAT_INTERVAL="$_heartbeat")
|
||||
fi
|
||||
Reference in New Issue
Block a user