From 42c159e42fc2f715647bcb8d464a59e0d1729d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Wed, 16 Sep 2026 15:06:53 +0800 Subject: [PATCH] version_0_1_0-alpha --- Makefile | 71 +++++++++++++++++++++++++--------------------- README.md | 9 +++++- web/vite.config.ts | 27 ++++++------------ 3 files changed, 54 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 9e1c3ae..702be62 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ # Local process control for LazyBoy. -# make start API :8787 + Vite :5173 +# make build cargo + production web UI (web/dist) +# make box Docker computer image (lazyboy-box:local) +# make start rebuild, then API :8787 + Vite :5173 +# make restart stop, build, start # make stop -# make restart .DEFAULT_GOAL := help @@ -10,6 +12,7 @@ RUNDIR := $(ROOT)/.run BIN := $(ROOT)/target/debug/lazyboy WEBDIR := $(ROOT)/web +HOST ?= 0.0.0.0 PORT_API ?= 8787 PORT_WEB ?= 5173 @@ -18,7 +21,7 @@ PID_WEB := $(RUNDIR)/web.pid LOG_SERVE := $(RUNDIR)/serve.log LOG_WEB := $(RUNDIR)/web.log -.PHONY: help start stop restart status logs prepare-ui start-serve start-web stop-serve stop-web +.PHONY: help build build-bin build-ui box start stop restart status logs prepare-ui start-serve start-web stop-serve stop-web # Shared POSIX helpers. Sourced by each recipe. define CTL @@ -153,17 +156,40 @@ endef export CTL help: - @echo "make start Start API (:$(PORT_API)) and frontend (:$(PORT_WEB))" + @echo "make build Compile API + production web UI (web/dist; phone uses :$(PORT_API))" + @echo "make box Build Docker computer image lazyboy-box:local (first time / after box/)" + @echo "make start Rebuild and start API (:$(PORT_API)) and frontend (:$(PORT_WEB))" @echo "make stop Stop both" - @echo "make restart Stop then start" + @echo "make restart Stop, rebuild, start" @echo "make status Show PIDs and ports" @echo "make logs Tail both logs (Ctrl-C to leave)" -start: prepare-ui start-serve start-web +build: build-bin build-ui + @echo "built $(BIN) and $(WEBDIR)/dist" + +build-bin: + @echo "building lazyboy…" + @cargo build -p lazyboy + +build-ui: + @if [ ! -d "$(WEBDIR)/node_modules" ]; then \ + echo "npm install…"; \ + (cd "$(WEBDIR)" && npm install) || exit 1; \ + fi + @echo "building web UI…" + @(cd "$(WEBDIR)" && npm run build) || exit 1 + +box: + @echo "building computer image lazyboy-box:local…" + @bash "$(ROOT)/box/build.sh" + +start: build + @$(MAKE) start-serve + @$(MAKE) start-web @echo @echo "API http://127.0.0.1:$(PORT_API)" @echo "UI http://127.0.0.1:$(PORT_WEB)" - @lan=$$(hostname -I 2>/dev/null | awk '{print $$1}'); \ + @lan=$$(awk '/手機同一個 Wi-Fi:/ {sub("http://", "", $$NF); sub(/:[0-9]+$$/, "", $$NF); print $$NF; exit}' "$(LOG_SERVE)"); \ if [ -n "$$lan" ]; then \ echo "Phone http://$$lan:$(PORT_API)"; \ fi @@ -186,32 +212,17 @@ logs: @echo "=== web $(LOG_WEB) ===" @tail -f "$(LOG_SERVE)" "$(LOG_WEB)" -prepare-ui: - @if [ ! -d "$(WEBDIR)/node_modules" ]; then \ - echo "npm install…"; \ - (cd "$(WEBDIR)" && npm install) || exit 1; \ - fi - @if [ ! -f "$(WEBDIR)/dist/index.html" ]; then \ - echo "building web UI (once, so :$(PORT_API) serves the app)…"; \ - (cd "$(WEBDIR)" && npm run build) || exit 1; \ - fi +prepare-ui: build-ui start-serve: @mkdir -p "$(RUNDIR)" @eval "$$CTL"; \ if alive "$(PID_SERVE)"; then \ - fmt=$$(cat "$$HOME/.lazyboy/certs/format" 2>/dev/null || true); \ - if [ "$$fmt" = "2" ]; then \ - echo "serve already running pid=$$(cat "$(PID_SERVE)")"; \ - exit 0; \ - fi; \ - echo "TLS certs need reissue; restarting serve"; \ + echo "restarting serve with rebuilt binary"; \ stop_one serve "$(PID_SERVE)" "$(PORT_API)"; \ fi; \ - echo "building lazyboy…"; \ - cargo build -p lazyboy || exit 1; \ load_env; \ - LAZYBOY_WEB_PORT="$(PORT_API)" nohup "$(BIN)" serve > "$(LOG_SERVE)" 2>&1 & echo $$! > "$(PID_SERVE)"; \ + LAZYBOY_WEB_HOST="$(HOST)" LAZYBOY_WEB_PORT="$(PORT_API)" nohup "$(BIN)" serve > "$(LOG_SERVE)" 2>&1 < /dev/null & echo $$! > "$(PID_SERVE)"; \ wait_alive "$(PID_SERVE)" serve "$(LOG_SERVE)" || exit 1; \ wait_listen "$(PID_SERVE)" "$(PORT_API)" serve "$(LOG_SERVE)" || exit 1; \ echo "started serve pid=$$(cat "$(PID_SERVE)") :$(PORT_API) log=$(LOG_SERVE)" @@ -220,19 +231,13 @@ start-web: @mkdir -p "$(RUNDIR)" @eval "$$CTL"; \ if alive "$(PID_WEB)"; then \ - if lsof -nP -iTCP:"$(PORT_WEB)" -sTCP:LISTEN 2>/dev/null | grep -q '127.0.0.1:$(PORT_WEB)'; then \ - echo "web is localhost-only; restarting so the phone can connect"; \ - stop_one web "$(PID_WEB)" "$(PORT_WEB)"; \ - else \ - echo "web already running pid=$$(cat "$(PID_WEB)")"; \ - exit 0; \ - fi; \ + stop_one web "$(PID_WEB)" "$(PORT_WEB)"; \ fi; \ if [ ! -d "$(WEBDIR)/node_modules" ]; then \ echo "npm install…"; \ (cd "$(WEBDIR)" && npm install) || exit 1; \ fi; \ - nohup npm --prefix "$(WEBDIR)" run dev -- --host 0.0.0.0 --port "$(PORT_WEB)" > "$(LOG_WEB)" 2>&1 & echo $$! > "$(PID_WEB)"; \ + LAZYBOY_WEB_PORT="$(PORT_API)" nohup npm --prefix "$(WEBDIR)" run dev -- --host "$(HOST)" --port "$(PORT_WEB)" > "$(LOG_WEB)" 2>&1 < /dev/null & echo $$! > "$(PID_WEB)"; \ wait_alive "$(PID_WEB)" web "$(LOG_WEB)" || exit 1; \ wait_listen "$(PID_WEB)" "$(PORT_WEB)" web "$(LOG_WEB)" || exit 1; \ echo "started web pid=$$(cat "$(PID_WEB)") :$(PORT_WEB) log=$(LOG_WEB)" diff --git a/README.md b/README.md index 818f5ed..2ca972c 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,18 @@ For action tasks the agent briefly explains its approach, then starts. Multi-sta ```bash # 可設項目與說明:複製 .env.example 成 .env 後填 LAZYBOY_API_KEY -# make start 會載入 .env +# make start / restart 會載入 .env +make build # API + 正式 UI(web/dist;手機走 :8787 需要這步) +make start # 每次重建 API + UI,再啟動;預設綁定 0.0.0.0 +make restart # 停止後重建並啟動 +make box # 第一次/改 box/ 之後:Docker 電腦映像 lazyboy-box:local +make stop export LAZYBOY_API_KEY=your_key # or XAI_API_KEY cargo run -p lazyboy -- agent # API daemon (named Agents) + HTTP on :8787 cargo run -p lazyboy -- serve +# 開發前端使用 HTTP,不會因本機殘留憑證自動切換 HTTPS。 +# 本機:http://127.0.0.1:5173;其他裝置:http://本機區網IP:5173(或 :8787)。 # Independent frontend: cd web && npm install && npm run dev # Production UI: npm run build then lazyboy serve hosts web/dist diff --git a/web/vite.config.ts b/web/vite.config.ts index b0eb549..6fc722e 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,39 +1,26 @@ -import { existsSync, readFileSync } from "node:fs"; -import { homedir } from "node:os"; -import { dirname, join, resolve } from "node:path"; +import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig, loadEnv, type ServerOptions } from "vite"; import react from "@vitejs/plugin-react"; const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), ".."); -function localCerts(): { cert: Buffer; key: Buffer } | undefined { - const home = homedir(); - for (const dir of [join(home, ".lazyboy", "certs"), join(home, ".grokboy", "certs")]) { - const cert = join(dir, "server.pem"); - const key = join(dir, "server.key"); - if (existsSync(cert) && existsSync(key)) { - return { cert: readFileSync(cert), key: readFileSync(key) }; - } - } - return undefined; -} - export default defineConfig(({ mode }) => { const env = loadEnv(mode, rootDir, ""); const version = (process.env.LAZYBOY_VERSION || env.LAZYBOY_VERSION || "0.1.0").trim() || "0.1.0"; - const https = localCerts(); - const backend = https ? "https://127.0.0.1:8787" : "http://127.0.0.1:8787"; + // The API accepts HTTP even when its optional TLS listener is enabled. + const backendPort = process.env.LAZYBOY_WEB_PORT || env.LAZYBOY_WEB_PORT || "8787"; + const backend = `http://127.0.0.1:${backendPort}`; const server: ServerOptions = { port: 5173, - host: true, + host: "0.0.0.0", + strictPort: true, proxy: { "/api": { target: backend, secure: false }, "/novnc": { target: backend, ws: true, secure: false }, "/lazyboy-ca.crt": { target: backend, secure: false }, }, }; - if (https) server.https = https; return { plugins: [react()], define: { @@ -42,6 +29,8 @@ export default defineConfig(({ mode }) => { server, preview: { port: 4173, + host: "0.0.0.0", + strictPort: true, }, }; });