Commit Graph

10 Commits

Author SHA1 Message Date
王性驊 1202de93ad Bots work like someone who knows the computer: they know each machine, reach what they see, plan, and hand the planned steps to a quick model
Measured on the bot's own box (8 tasks x 2, grok-4.7): 14/16 done, 120 steps, 1114 s before;
16/16, 102 steps, 574 s after (model time 1015 -> 471 s). A replayed skill: 49 s -> 15 s.

Knowing the machine
- facts.rs: 電腦現況 per computer (system, desktop, systemd, sudo, network, package manager,
  tools, apps, a fixed TZ), read once by a small read-only probe, kept 30 min, in the
  instructions at the start of a turn.
- The box's sudo is the bot's: only what follows sudo is checked against the always-denied
  list (it was refused outright, while the instructions said it could sudo), and commands with
  sudo run as the box's root (setuid does nothing under gVisor).
- Box image v8 drops ENV TZ=UTC (it overrode /etc/localtime). ANYBOT_BOX_IMAGE /
  ANYBOT_BOX_VOLUME give a throwaway box its own image and volume, never adopting the real one.
- Mac shell sandbox: App Store app CLIs (they carry their own app sandbox) and ps/top run
  outside it; plain `osascript -e` too, asked the first time even in direct mode, refusing do
  shell script, terminals, keystrokes, file reads, ObjC and the secret folders. A command the
  sandbox broke says so, instead of looking like a broken program.

Reaching what it sees
- The Mac menu bar's status icons are numbered (each app's AXExtrasMenuBar, named from inside
  for the system's own), computer_use_zoom looks closer at full sharpness.
- Numbers stay with their controls from look to look (they were reassigned every look, so a
  step's second click landed elsewhere); the box's front window is listed first; a control can
  be named instead of numbered (name "4").
- Web page numbering walks open shadow DOM (Chromium settings, web components).
- A box on a Docker host elsewhere retries the next port when the usual one is taken (a retry
  without it came up with no network).

Working like a person
- Instructions: pick the route, know what done looks like, one route, check once, say what's
  stuck instead of faking it with a substitute, ask before cutting the connection.
- StepPlan: the bot's model takes the first step, the step after trouble (failed, refused,
  repeated, nothing changed on screen, the quick model switching routes), one in four, and the
  final check; a quick model (Bot.step_model, auto: grok-4.20-0309-non-reasoning on xAI) does
  the planned steps in between, falling back to the bot's model if it can't be used.
- Skills keep the steps that worked (with what each acted on, not numbers); replay_skill does
  them again with no model in between, finding each control again, handing back on a mismatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha5F5gJt93t3yEx3XcS
2026-11-09 09:01:03 +08:00
王性驊 00f6723588 HTTPS on the local network's own IP, with a certificate the server signs itself
setup.sh offers 「區網 IP」 (alone, or next to Tailscale): Caddy serves https://<LAN IP> with its
own small certificate authority (tls internal, default_sni for clients that send no name) and
hands out the root at http://<LAN IP>/anybot-ca.crt for each device to trust once.
docker-compose.lan.yml binds Caddy to that address only, so it sits beside tailscale serve.

The app now accepts, for the account server, the certificates this computer trusts as well as
the built-in public ones (HTTP and the WebSocket alike), so it connects once the root is
trusted; before that it says what to install instead of "the certificate is wrong".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 21:27:07 +08:00
王性驊 81e87545cd Each job works on its own tabs; a Lima VM the box lives in is started when it's down
- Bots share a browser (the box's Chromium has one profile). Every step acted on the tab in
  front, so two jobs at once read and clicked on each other's pages and one finishing closed
  the other's. A job (named, and the name rides along to another computer's browser) owns the
  tabs it opens or lands on, popups it clicks open included; its steps use its latest one, and
  another job's tabs are never used, listed or closed. When it ends it closes only its own.
  Real run on the box: two jobs at once each read their own page with the other's in front,
  both tabs survived both endings; a popup was read by the job that opened it.
- A Docker host that is a Lima VM's socket and doesn't answer (the Mac restarted): AnyBot
  starts the VM (limactl start, at most once in 5 minutes), and a step that needs the box
  waits for it. No login item needed. Real run: the VM stopped, AnyBot had it back in 10 s;
  the box then woke on use, still gVisor with Chromium's sandbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 00:50:29 +08:00
王性驊 4605b317d8 Bot 的電腦 can run under gVisor: its own kernel, Chromium's sandbox back on
容器隔離 in 設定 › 電腦: standard (runc, the container is the only wall, Chromium runs
--no-sandbox) or hardened (runsc: a virtualized kernel, all capabilities dropped but the few
the desktop needs, ANYBOT_BOX_SANDBOX=1 turns Chromium's own sandbox back on). Box image v7.
deploy/mac/gvisor-vm.sh makes a Lima VM with Docker + gVisor for a Mac (started at login),
gvisor-migrate.sh moves the box's files and logins there.

Checked and finished before committing:
- the hardened choice is offered only on a Docker host that has runsc; a box set to it on a
  host without it opens the standard way and says so (it used to not start at all)
- the settings row shows what the box really runs on, and when 更新 is needed
- no swap only under gVisor (a standard box keeps Docker's default)
- the migrate script sees the running Mac app ("AnyBot", not "anybot")
- the VM script starts an existing VM by name, checks runsc and the kernel from the Mac
- the version test says 7

Real run in the Lima VM: desktop, VNC, numbered controls, xdotool and screenshots work; no
Chromium process has --no-sandbox, renderers run with seccomp and their own namespaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 00:03:25 +08:00
王性驊 ece88bf2fe Plan: smoother computer use and box logins that survive a rebuild
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 22:06:49 +08:00
王性驊 2867c8e822 Remove what nothing uses and keep one copy of what was written several times
Unused (found by taking away the dead-code allowances; nothing else used them, tests aside):
computer::specs, quiet_button, the never-made Poke::Spin, ten icons and their SVGs, the
theme's chrome/bubble_agent colours, ImportRow.line, voice's multipart/transcribe/speak
wrappers, and the old keychain writers vault::save/remove/index_add with their live test
(the vault store replaced them; reading old keychain entries for the import stays).

One copy each: percent-encoding (httpd::url_encode, was four), tool arguments (tools::args_of,
was three), the WebSocket handshake (httpd::accept_websocket, was three), the read pacing
(wire::Pace, was two: relay and app), docker with input and a time limit (dk_with_input, was
two). Docs: FEATURES §看畫面 (VNC), protocol (v* frames, /screen, tickets), architecture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:21:47 +08:00
王性驊 26fa2a8ee9 Commands on another computer run in the bot's work folder and finish before the relay gives up; read_terminal goes to the same computer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:28:32 +08:00
王性驊 c0dfef0995 Docs: 頁面, Tailscale servers, no-questions install, hands' virtual screen and updates
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-05 08:35:47 +08:00
王性驊 472a004f87 One-step install: install.sh, fixed Linux and server builds, clearer README
- install.sh (curl | sh): app, hands, server and deps modes; installs system packages
  (right names per release, e.g. libasound2t64 on Ubuntu 24.04), Rust via rustup (1.95+),
  Docker for the server; limits parallel compiles on small machines
- Server Docker image: add the ALSA build/runtime packages (the build failed), cache the
  cargo registry and target between rebuilds, JOBS build arg
- 加一台電腦 now gives a line that installs AnyBot on a blank computer before joining it
- Makefile: make deps installs Rust too, make doctor, clear message when Rust is missing/old
- README rewritten: one line per use, getting started, update/remove, troubleshooting,
  deployment options; docs/install.md and multi-device.md follow it
- Tested on fresh ubuntu:24.04 (app) and debian:12 (curl | sh hands) containers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-05 00:52:10 +08:00
王性驊 867732bd73 make, README and docs: build and install from source
- Makefile: make / run / install / uninstall / deps / test / serve / setup /
  hands / relay-run / server / dist / clean (macOS and Linux).
- README.md and docs/: install (all platforms, data locations, troubleshooting),
  multi-device (brain, hands, screens, pairing, what the offline messages mean),
  architecture (layers, data, security, sync, keys, hands, picture helper),
  protocol (relay and AnyBot endpoints, WebSocket frames, sync ops), release
  (packaging, Gitea Actions, Linux and Mac runners).
- install.sh --deps-only, bundle.sh KEEP_APP=1 (used by make deps / install).
- FEATURES.md: the multi-device part is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 22:16:45 +08:00