Go to file
王性驊 8e8174e8bf version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
box fix bot flow 2026-09-15 17:07:16 +08:00
crates version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
docs have main issue 2026-09-16 06:40:00 +00:00
node_modules version_0_1_0-alpha 2026-09-16 14:47:32 +08:00
prompts docs+P6: scenario playbook template + example + request_user_confirm 2026-09-13 16:37:51 +08:00
tests version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
tools/playwright version_0_1_0-alpha 2026-09-16 14:47:32 +08:00
web version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
.env.example have main issue 2026-09-16 06:40:00 +00:00
.gitignore fix bot flow 2026-09-15 13:20:44 +08:00
Cargo.lock fix bot flow 2026-09-15 17:07:16 +08:00
Cargo.toml fix bot flow 2026-09-15 13:20:44 +08:00
LICENSE P0: GrokBoy streaming chat CLI 2026-09-13 15:25:02 +08:00
Makefile version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
README.md version_0_1_0-alpha 2026-09-16 16:17:38 +08:00
package-lock.json base flow 2026-09-15 11:20:42 +08:00
package.json base flow 2026-09-15 11:20:42 +08:00

README.md

LazyBoy

A local, general-purpose GrokBot-like CLI agent. It observes the environment, chooses tools, adapts to results, and verifies its work. Uses your existing xAI/OpenAI-compatible model configuration; no separate search API key.

For action tasks the agent briefly explains its approach, then starts. Multi-stage tasks get a short live plan. You can add instructions while it works, answer a question, or interrupt and resume. Simple questions remain simple answers.

Remote computer controls

右側電腦採用 Grok 風格的螢幕卡片按「放大」可開啟全頁操作。桌面版不顯示手機控制列直接使用滑鼠鍵盤Ctrl+Alt+ 可縮放Ctrl+Alt+0 重設Ctrl+Alt+B 開啟文字剪貼簿面板。

手機沿用 LazyBoy 的獨立觸控板滑動移動游標、輕點左鍵、雙指捲動輕點右鍵也可按左右鍵、捲動與「拖曳」再按一次放開。可切換直接點選模式。直向控制區在下方橫向在左側鍵盤、常用按鍵、14 倍縮放、移動畫面與雙向文字剪貼簿都在手機控制區。若區網 HTTP 或瀏覽器限制剪貼簿權限,可在面板長按貼上/複製。

Start

# 可設項目與說明:複製 .env.example 成 .env 後填 LAZYBOY_API_KEY
# make start / restart 會載入 .env
make build     # API + 正式 UIweb/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
# Phone: same Wi-Fi, open the printed LAN URL, Add to Home Screen
# One-shot:
cargo run -p lazyboy -- run "整理目前目錄的資料,產生報告並讀回驗證"
# Resume:
cargo run -p lazyboy -- agent --session <id>
cargo run -p lazyboy -- run --session <id> "繼續"

While running, enter additional instructions to steer the next step. Ctrl-C or /stop stops the turn and saves its state. In the REPL, /plan shows the current plan, /session shows its ID, and /exit or /quit exits when idle. During work /exit and /quit stop the current turn first. At an explicit question, new text answers that question. Already queued idle inputs remain separate tasks.

Progress, plans and questions go to stderr; final answers go to stdout. lazyboy chat remains streaming chat without tools. lazyboy web serves the Grok Bot-shaped conversation UI (sidebar, bubbles, composer, 我的電腦 overlay) as a phone-installable PWA. lazyboy help lists commands and settings.

Persistent agents and background work

Run lazyboy serve in one terminal, then create identities with lazyboy agents create <name> and open separate chats with lazyboy agent --name <name>. Agents learn private memories and public expertise from their conversations. They can delegate to an existing agent or create a temporary worker while you keep chatting.

In named-agent mode, ordinary text is new chat. Use /tasks and /task <id> say|stop|resume to manage background work. Closing a chat leaves the service and its tasks running. Agent identity and task ownership are separate: one agent can help another without losing its own conversation.

See team setup and behavior for commands, budgets, privacy boundaries and recovery. LAZYBOY_DATA_DIR defaults to ~/.lazyboy/team; existing single-session commands keep their original behavior.

Tools

Capability Tools
Voice send_message (only user-visible channel; widget asks a question)
Progress and planning report_progress (alias of send_message text), update_plan
Human interaction request_user_input, request_user_confirm, browser_handoff
Completion No-tool response ends the turn. report_done is optional. report_blocked when stuck.
Explicit local commands external_exec_command (backgrounds after block_until_ms, default 30s), external_await_command, external_write_stdin, external_shell
Explicit local files external_list_dir, external_read_file, external_edit_file, external_write_file, external_grep (regex), external_glob, external_search_files (literal)
Web web_fetch (direct anonymous HTTP GET, HTML → text, short cache), web_search (remote search service); no browser login; Docker browser for login-gated pages
Background spawn_subagent (returns immediately; kind=computerUse for desktop GUI), check_subagent, message_subagent, stop_subagent. Subagents and external command completion revive the turn; observe detached box commands with await_shell.
Desktop GUI Parent: screenshot (read-only). Clicks: spawn_subagent kind=computerUse, which gets computer (screenshot/click/move/drag/type/key/scroll/wait via xdotool on DISPLAY=:1). One computerUse per agent computer. Passwords still request_box_help.
MCP get_mcp_tools, call_mcp_tool, get_mcp_server_status, add_mcp_server, remove_mcp_server. Config: ~/.lazyboy/mcp.json (or LAZYBOY_MCP_CONFIG). Prefer a connector over the browser for that service.
My computer (box) Docker Linux desktop (XFCE + Chromium + 終端機 + xdotool). Named agents each get their own container; opening an agent starts it and the UI confirms ready/error. Session CLI keeps lazyboy-box. Default tools: shell, read, await_shell, screenshot. Profile: /home/box/chrome-profile on that seat. Viewerlazyboy computer or the agent overlay.
Browser observation browser_navigate, browser_snapshot, browser_read_page, browser_tabs
Browser actions browser_click, browser_type, browser_press, browser_select, browser_scroll, browser_wait
Browser file exchange browser_upload, browser_download
Browser fallback browser_eval

Long commands return a session ID and incremental output; external_write_stdin polls, sends input, closes stdin or terminates the command. One foreground command at a time, piped I/O, default ten-minute deadline. The explicit local external_shell retains its 30-second limit. Default shell runs on the box and continues in the background when its foreground wait expires; use await_shell to observe it. Full command output is saved under .lazyboy-output/; large tool results are also stored there with a readable preview and path.

external_read_file accepts a zero-based line offset and line limit; external_search_files searches names or literal content; external_edit_file requires one unique exact match. File tools and browser file exchange check workspace paths and symlinks. Only external_* tools operate on the local machine; shell and read use the box.

Browser surfaces

Docker mode includes Node, Playwright and Chromium in the image. The following setup is only for the explicit legacy local browser:

export LAZYBOY_BROWSER_SURFACE=local
cd tools/playwright
npm install
npx playwright install chromium
cd ../..
export LAZYBOY_BROWSER_HEADED=1  # visible browser, convenient for login handoff
cargo run -p lazyboy -- agent

Browser tools now default to Docker Chromium, attached to the desktop browser at /home/box/chrome-profile. Automation and human login share this profile; browser uploads/downloads use /workspace paths and explicit copy_to_box/copy_from_box transfer files. browser_release disconnects automation without closing the desktop. The old local browser is available only with LAZYBOY_BROWSER_SURFACE=local; its owner profiles are preserved and are not merged into Docker. See surface comparison for differences and configuration.

web_fetch is a direct anonymous HTTP GET from the host: browser-like headers, no cookies, public hosts only (redirects are re-checked), body capped at 2 MiB, HTML reduced to readable text with link footnotes, non-UTF-8 charsets decoded, and results cached for ten minutes per URL. Only when a site refuses plain HTTP (401/403/429/503, or an empty JavaScript shell) and the model configuration is official xAI does it fall back to xAI native browsing; that result is marked content_kind=model_rendered_web_content and carries fallback_reason. web_search uses a remote search service with no browser cookies: official xAI configuration reuses the existing model API key for native web search; for the reconstructed AiService contract, set LAZYBOY_WEB_BACKEND_URL and, when required, LAZYBOY_WEB_TOKEN. That gateway must provide the reconstructed RunWebSearch JSON contract; a normal OpenAI-compatible chat endpoint alone does not provide it. Missing search configuration produces an explicit error, never a hidden browser fallback.

For login, OTP or captcha, browser_handoff shows the Docker viewer URL and parks the turn until you reply. For irreversible public actions, the agent follows the existing explicit-approval rule; plans themselves do not require approval.

Settings

Environment variable Default / meaning
LAZYBOY_API_KEY Falls back to XAI_API_KEY, then OPENAI_API_KEY
LAZYBOY_BASE_URL https://api.x.ai/v1; fallback OPENAI_BASE_URL
LAZYBOY_MODEL grok-4.6
LAZYBOY_MAX_ROUNDS_TOTAL 5000 model steps per user turn (Grok Bot Sand-style). A step with no tool calls ends the turn.
LAZYBOY_MAX_ROUNDS 12; local progress interval, no extra model calls
LAZYBOY_CONTEXT_CHARS 100000 approximate UTF-8 bytes; legacy name
LAZYBOY_SESSIONS_DIR ~/.lazyboy/sessions
LAZYBOY_PROGRESS 0 silences progress, but not questions
LAZYBOY_BROWSER_HEADED 1 launches visible Chromium
LAZYBOY_CONFIRM_AUTO Test-only approval/denial override; falls back to LAZYBOY_HANDOFF_AUTO
LAZYBOY_HANDOFF_AUTO Test-only handoff override: 1 resume, abort deny

Session stop reasons: answer (no tool calls — the Grok Bot end condition), done (optional report_done), blocked, budget_exhausted, failed, cancelled. One-shot exits 0 for answer/done, 1 for blocked/budget/failed, 130 for cancellation. The REPL remains usable after any turn outcome. Delivery is send_message; a no-tool response is not independent proof of arbitrary task correctness.

Latency diagnostics

Set LAZYBOY_TIMING=1 when starting the process to print elapsed milliseconds to stderr for request preparation, model-slot queues, model rounds (including queue wait), tool execution, and whole agent turns. These nested measurements must not be added together. They contain no prompts, tool arguments, or credentials; concurrent turns can interleave. Compare the same task and session length, and count model rounds as well as wall time. This does not enable extra model calls.

Memory extraction starts only when no foreground chat is active and both background slots are free; it acquires capacity without queuing. Deferred memory remains durable and is retried by the scheduler. Already-running extraction is allowed to finish, and continuous activity can delay memory updates. Work and completion rules are unchanged: acknowledgement is not completion, required results must still be observed, and sending a message alone does not end a turn.

Validation

cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo build -p lazyboy
python3 tests/cli_flow.py
python3 tests/runtime_flow.py       # includes a real 31-second command + local Chromium
python3 tests/browser_flow.py       # headless Chromium, local fixture only
python3 tests/team_flow.py          # daemon, two CLI clients, mock API + Chromium
cargo run -p lazyboy -- smoke
# Opt-in: uses your existing paid model configuration, max 12 requests:
python3 tests/live_cli.py
python3 tests/live_team.py          # opt-in team workflow, root task ceiling 16

Design and Codex references: CLI flow. Product scope: PRODUCT. Acceptance scenarios: ACCEPTANCE. Older scenario playbooks remain optional examples, not hardcoded workflows: scenarios.

Memory and long-running UI

make start rebuilds both services and reapplies computer limits to existing containers. Each computer is limited to 1536 MiB RAM (no additional swap), 2 CPUs and 512 processes; new containers use 256 MiB shared memory. The default maximum is three running computers, including computers recovered from previous server runs. Idle computers are stopped when a slot is needed; their workspace and browser profile volumes are retained. Busy computers are not evicted. LAZYBOY_COMPUTER_MAX overrides the running count.

Chat history scrolls continuously and only mounts nearby messages. Desktop chrome is hidden by CSS without a DOM mutation feedback loop. Regression checks: node tests/novnc_memory_ui.mjs and node tests/history_memory_ui.mjs (with the frontend running).