Commit Graph

34 Commits

Author SHA1 Message Date
AnyBot Dev 1bc2fdcec9 Rewrite decompilation comments as behaviour specs; move reverse-engineering docs out of the repo; drop third-party marks from UI strings (i18n tables synced) 2026-11-09 16:37:33 +08:00
王性驊 ec3fddf3ab A computer showing another brain lets its own box and Lima VM sleep
The Mac mini shows the cloud brain, whose bots work on the brain's own
computer and borrow only this Mac's screen, browser and apps. Its local
box still ran, and the Lima VM under it had grown to its whole 6 GB: the
Mac never gets back memory a VM once used.

- On a screen the box stops after 2 idle minutes, and the Lima VM too when
  nothing else runs in it. probe() no longer starts the VM there, and the
  volume holder and scheduled updates run on brains only. Becoming a brain
  again starts both (probe/ensure_running already wake the VM).
- Screen mode is decided from the settings before the box loop's first
  look, which used to start the VM at launch.
- gvisor-vm.sh: 4 GB instead of 6 (box capped at 2 GB), and the VM's
  ModemManager, udisks2 and multipathd are turned off.

Verified on this Mac: box and VM stopped by themselves 2 minutes after the
app started; the VM process (4.4 GB plus compressed pages) is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha5F5gJt93t3yEx3XcS
2026-11-09 15:24:28 +08:00
王性驊 2f603c2362 A turn cut off by a crash leaves a 「繼續」 card, and nothing it may have done runs twice
Each bot keeps a work log (oplog/bot-<id>.jsonl, after pi's durable-harness design, cut down):
before something happens a line says it is about to — the turn, each model call, each step once
its checks passed (with the arguments it runs with and whether it may run again), each message
typed mid-turn — synced to disk first. When the turn ends the file shrinks to the messages still
waiting, usually nothing.

On the next start after AnyBot was killed mid-turn, the log puts the chat right before anything
runs: the message the turn answered comes back if the chat lost it; a step that was running and
reaches outside (a text, a click, a file, a published site) shows as 「可能已經執行了」, both to the
person and in the result the bot reads — no longer as "not allowed"; a step that only looked shows
as cut off; messages typed mid-turn that never reached the bot go back into the chat. The chat is
saved, then the log closes the turn. A turn the person didn't stop ends with a 「繼續」 card (what
it was doing, what may have run, the messages put back); it goes on only when they press it — in
the window, on a screen of the brain, or on the phone — from where its steps stand, never running
a step that may have run again. Pressing stop is on disk at once, and a stopped turn stays
stopped.

Also in the turn loop:
- 自動審核 that doesn't answer (or answers something that isn't a verdict) asks the person; in
  直接操作 mode it used to let the step through unchecked.
- "Too long for this model" folds older messages into a summary and asks the same step again,
  once per thing the person said, instead of ending the turn.
- Folding keeps the person's chat whole: the summary goes in at the fold and the model reads from
  the newest summary on (it used to delete what it folded).
- A step moved to the chosen computer runs there, but the chat keeps the call as the model wrote
  it; the result says where it ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha5F5gJt93t3yEx3XcS
2026-11-09 00:49:12 +08:00
王性驊 4506cc149b Clippy is clean on macOS and Linux, for the app and the relay
Every warning `cargo clippy --all-targets` gave (50 on macOS, 8 more only on
Linux, 1 in the relay), fixed without changing what anything does:
- long types get a name (Peer, Members, Imported, Joining, Mention, Stream…);
- the two big enum variants are boxed (the vault's login plan, joining an
  account);
- a test now waits for the copy it relaunched (it left a zombie behind);
- a hint's format had a dead `if` whose two branches were both "";
- the rest is what clippy suggests: sort_by_key, as_chunks, is_none_or,
  is_multiple_of, while let, from_ref, next_back, struct init, no casts to
  the same type.

Checked: cargo test (177 macOS, 181 Linux), relay tests (11), remote_e2e
28/28, and the live Linux test (X11; Wayland clicks, keys, Chinese typing,
scroll and screenshots).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 10:10:28 +08:00
王性驊 f3ccd129d6 The phone page does what the desktop does, laid out like it
A new mobile/index.html in the desktop's (and Grok Bot's) shape: the sidebar
with its sections and folders, the chat with steps, thinking, reactions, quotes
and the approval card, 對話詳細資訊, Bot 設定, routines, pages, computers and
設定. Each action goes to the desktop's own code on the app's thread
(api/act/<what> -> App::phone_act): appctl, set_pinned, restart_bot,
toggle_reaction, box_task, channels_restart and the rest. No new rules.

Keys, channel tokens and the vault never reach the phone; a model key can only
be written. Admins keep what the phone always let them do; making, changing or
deleting bots, routines, memories, pages, folders and settings stays the
owner's. The state the phone polls now carries the sidebar's section order.

Checked by using it on a preview brain: routines, memories, templates, folders,
keys, signing another phone out, approvals and a chat with a fake model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 03:05:12 +08:00
王性驊 9a23411e51 Checked by using it: tests stay off the real box, gVisor scripts run clean, times are the person's
- box_numbers_only_on_what_is_seen is ignored again (a test inserted before it in cbada6b took
  its mark: every cargo test drove the real box), and the path test runs
- gvisor-vm.sh restarts the VM's Docker only when runsc was just registered (a restart stopped
  Bot 的電腦), and `${var}` before full-width text (bash read 「)」's first byte as part of
  the name and stopped)
- a scheduled box update and a PDF's name use the person's time zone (a server keeps UTC)
- 容器隔離 lists 標準 before 強隔離
- screenshots of real data can open 設定 › 電腦 (ANYBOT_SHOT_VIEW=computers) and scroll
  (ANYBOT_SHOT_SCROLL)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-07 00:19:56 +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
王性驊 cbada6bdb1 Bots learn from what they did; the box's browser works with the box's own disk
- A job of five or more real steps is looked back on after the answer: the short way that
  worked becomes a skill (or improves the one it followed); the reply says so. The prompt has
  the bot check its skills before starting.
- Upload, download and PDF on Bot 的電腦's browser look for and save files in the box, not on
  the brain (a picture in a Threads post took 24 steps).
- The bot's browser keeps the six tabs used last (19 Threads tabs had filled the box's 2 GB).
- Words name the control, not the box around it: a form's 「Customer name:」, 「Large」 and
  「Submit order」 used to land on the <p> holding them and do nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 23:12:53 +08:00
王性驊 ce566b97f0 Times are the person's: a brain on a server takes the phone's time zone instead of its own UTC
Both cloud brains had 「Etc/UTC」 as the time zone (the server's, set when they were made), so pages
said 「今天 01:03」 for 09:03 and a routine for 9 in the morning would run at 5 in the afternoon. The
phone now says where the person is; a brain still on a server's zone takes it (a zone the person
chose stays). Page times use the person's zone, not the computer's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 20:33:06 +08:00
王性驊 39cd7e85d7 Phone: a home with the computers, pages and routines; each bot's settings a tap away; long jobs fold up
The phone page was bare: one row per bot, a chat listing every step, a menu with four lines.
- Home: the main bot large at the top with its model and last words, the other bots with times,
  then its computers (own box and the account's, online or not, 看畫面), the newest pages and the
  routines with their next run.
- Chat: the bot's name opens its settings — model (chat models only), computer, past conversations
  (restore), regenerate, new chat. A turn's steps fold into 「已完成 N 個步驟」 when done (the newest
  three stay while it works); copy and regenerate under replies; four ready starts in a new chat;
  a jump back to the newest message.
- Menu: 外觀 (follow the phone, light, dark).
- API: api/state carries pages and models; each bot its model, computers, routines, past
  conversations; POST api/bots/{id}/set | regenerate | restore. The home's last line skips errors.

Checked on a local copy of the brain's data (cut off from the account and Docker) at iPhone size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 20:28:08 +08:00
王性驊 b9fc134c99 Phone: a step's name stays on one line; every step says what it does
From looking at the real phone page after the fixes: a long command squeezed its step's name into
one character per line (執/行/指/令), and sending a file showed as 「工具」. The name keeps its width,
the detail is cut with an ellipsis, and send_file, react and view_demo_step have names; the window
says 「正在傳檔案給你」 instead of 「正在記下來」 while a file is sent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 19:55:40 +08:00
王性驊 cbf43ce2d4 Bots do a planned sequence in one step; the box's screen settles by what it shows; no login is ever the only copy
- computer_use_batch: up to 8 planned actions run in one docker exec (steps chained with && and a
  done-marker each), the first failure stops the rest, one picture comes back at the end. Typed
  text rides inside the script quoted (one stdin for the chain). The prompt tells the model when
  to use it (a form whose fields are all visible) and when not to (step 2 needs step 1's screen).
- The box waits for the screen to stop changing, not the clock: two matching small probes (~60 ms
  each) mean settled — ~160 ms on a still screen where every step paid a fixed 500 ms, and a page
  mid-load is waited for (up to ~0.9 s) instead of captured mid-change. The picture is JPEG, and
  the a11y read runs in parallel with the capture (look ~307 ms; two steps with pictures 1102 ms).
  (SETTLE_SH is a group command: dash needs ';' after it — found by box_screen_is_exact.)
- The home volume (every bot's logins) is never one command from loss: snapshots keep generations
  (last 7 days, then one per week; the old single snapshot migrates by file date), Reset and
  Restore save the running box first and refuse to wipe if saving fails, a box built on an empty
  volume re-fills itself from the newest snapshot, and a sleeping holder container keeps the
  volume attached so `docker volume prune` can't take it. make doctor shows volume and snapshot
  state; the 電腦 card shows the box's average step times and says resets save first.
- box_batch_in_one_round_trip (ignored): three typed steps, ASCII and Chinese, land in one trip.
  On the real box after upgrading v3→v5: box_update_keeps_files (files survive, snapshot 2 代),
  box_numbers_are_exact, box_screen_is_exact, box_end_to_end, box_traffic_via_mac pass; 155 unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:47:37 +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
王性驊 02bca39b98 People watch and help on the bots' computer through VNC (noVNC), carried by the account server
The core: the bot works the computer; a person watches it like a colleague, and takes over
when it needs them. VNC is made for that (only what changed, every mouse move and key, touch on
phones), so the pictures sent one by one go, and with them their own input path.

- vnc.rs: a VNC proxy to the box's x11vnc through one docker exec (a Python bridge that ends
  with either side). It signs in to the box with the box's own password (its VNC_PASSWORD) and
  offers the viewer no password, so the password never leaves the brain. The person's clicks
  and keys make the bot's steps wait until 8 s after they stop; text typed in the viewer's box
  (any language) is pasted in the box.
- Account server: /screen (the viewer page) and /novnc.js (noVNC 1.6.0, MPL-2.0, bundled);
  /relay/vnc/<host> takes the browser's WebSocket (account session, or a 10-minute ticket the
  app asks for with POST /relay/screen-ticket; owners and admins) and carries it over that
  AnyBot's lasting connection (vopen / vdata / vtext / vclose). Both ends of that connection
  wait 2 ms instead of 40 ms to read while things move: a request and its answer took up to
  160 ms more than needed.
- Phone page: 看 Bot 的電腦 and 接管 open the viewer page (also on the local network: /api/vnc on
  the AnyBot's own phone server). This Mac's own screen moved to the ⋯ menu.
- Mac app: 看畫面 opens the viewer in the browser (a screen of a brain: the brain's computer by
  ticket; else this computer's box, noVNC straight from it). The in-app picture viewer, the
  live JPEG stream, the person's click/move/scroll/key endpoints and the input shell are gone.
- Opening a Mac app uses LaunchServices (`open -a`): agent-desktop's launch waited on the window
  through accessibility and failed without 輔助使用 now and then.

Measured on this Mac (made-up account, local relay + headless brain + the real box): viewer
signed in in 0.4–0.7 s, a request and its answer through relay + brain + box 25–58 ms median;
headless Chrome shows the desktop live in /screen. remote_e2e 28/28 ×2, 149 unit tests, relay 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:05:44 +08:00
王性驊 6c0c4d7ecd Watching and using the bots' computer from afar: pictures as the screen changes, input through a lasting shell
- One lasting docker exec takes the desktop as a JPEG inside the box and sends a picture only
  when it changed (quicker while it changes, slower while still). Viewers ask for the picture
  after the one they have and get it at once. It was one exec per picture (a 1 MB PNG decoded
  and encoded again on the brain) and a fixed 0.7 s / 1 s pause: about one picture a second.
  Measured on the Mac's box: first picture 45 ms, ~90 KB (was ~1.1 MB), 9–19 pictures a second
  while it changes; viewers take at most ~8 a second over the network.
- The loop in the box ends the one before it, ends itself when a write fails ("0" lines while
  still) and is ended when nobody watched for 10 s (ending docker exec on this side left it
  running in the box).
- The person's clicks and keys go through one lasting shell in the box (text as base64), not a
  docker exec each.
- Answers over the lasting connection keep their headers (the relay dropped them): a picture's
  number reaches the app. JPEG/PNG/PDF/zip bodies are no longer deflated again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 22:34:36 +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
王性驊 06801f549d Remote brain: a computer that just came on is known at once; an offline computer is said, not swapped; snapshots survive an open browser; end-to-end test
- The brain looked the account's computers up once a minute: for up to a minute after the Mac
  came on, 「我的電腦」 was unknown and steps went elsewhere. Now every 15 s, and at once when a
  message comes from a computer it doesn't know yet.
- A step naming a computer that is off says so in words instead of running on the chosen one
  with a note that the person hadn't asked.
- Snapshots: tar's 'file changed' (the open browser) is not a failure; browser caches are left
  out; ten minutes for a large home folder.
- box_end_to_end clicks the terminal where it opened; restore only with ANYBOT_TEST_RESTORE=1.
- deploy/test/remote_e2e.py: account server + headless brain + hands + scripted model, 27 checks
  (computers, redirect, agent-desktop on the hands, hand-off 3 ways, phone view, sync copy,
  edits, hands offline/back, brain restart, clear). anybot --sample-state for such tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:14:23 +08:00
王性驊 46c0684cb4 需要處理: a bot hands a step to the person with its computer's live screen in the chat; the window fills to the top; the 電腦 card and viewer keep their text in place
- hand_over_computer (the original's box hand-off card): instruction, live screen with 接管,
  跳過 / 我完成了 / 接管; 我完成了 also in the viewer; a typed message answers it too. Header,
  sidebar and notifications say 等你處理 / 「{name}:需要你」; the phone shows it with 接管.
- Mac: the content reaches the top (no grey title bar); the top strip drags the window.
- Panel 電腦 card: each line stops before the picture; the brain's name on its own line.
- Viewer: buttons first, the title ends in … when narrow; the picture is centred.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:29:55 +08:00
王性驊 c3e2e28ec4 Only the brain keeps its box awake: a computer showing another brain leaves its own box alone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:10:05 +08:00
王性驊 ab564f706f The bots' computer never sleeps; a server brain doesn't work on the server; the computer choice lives in the side panel; bots default to their own computer
- No idle pause: an asleep box is woken; its files are saved once a day instead of before sleep.
- A headless brain offers no Local computer; attachments it receives go into the bot's own one.
- 「你的電腦」 kept by older versions means the bot's own computer; only an explicit choice moves it.
- The composer chip moved to the panel's 電腦 card (做事的電腦).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:07:04 +08:00
王性驊 3132f8ce91 Every computer goes by its own name; a server brain works on the computer the person uses
- A bot's own computer is 「<bot> 的電腦」; this one and the account's others go by their names.
  The server brain picked 你的電腦 by sorted host id, so a desktop left on the server won.
- 「我的電腦」 is the computer the person typed on (the relay names it); unknown means ask.
- A step moved back to the chosen computer tells the bot so.
- Composer chip and bot settings choose the computer by name; a screen asks the brain.
- A screen's 電腦 card and viewer show the brain's computer, not this one's box.
- A screen's chat copy that falls short asks for everything again instead of appending;
  清除聊天記錄 on a screen clears the brain's chat.
- Model requests to a private address go through the person's computer first.
- Phone typing on the box sends the text the tool reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 16:47:28 +08:00
王性驊 7391e3a101 Texture caches capped; big previews decode off the UI thread; helper processes reaped 2026-11-05 15:48:22 +08:00
王性驊 4fa5fab870 Remote: per-IP login lock, egress peers and timeouts narrowed; brain-mirror link covered by tests 2026-11-05 15:48:20 +08:00
王性驊 94cadca1b8 A brain on a server knows which computer is the person's; the phone page opens the brain in use
- On a server brain whose hands are the person's computer, 你的電腦 is that computer;
  the server itself is 大腦伺服器 (its browser too), so 「我的 Mac」 means the Mac.
- A brain with its own hands no longer lists the account's other brains as computers.
- 查看電腦 lists the computers the bot really has, with their real names.
- Phone page: with several brains on, it opens the one the account's computers use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:40:01 +08:00
王性驊 d78e75ebec First start: no bots, a guide instead; signing in syncs this computer and the account
- A new install (desktop or anybot --serve) starts with no bots; the main window shows
  「歡迎使用 AnyBot」: connect a model, make the first bot, or sign in.
- Old data whose five sample bots were never used starts empty too.
- Signing in syncs right away: an online brain of the account is used and this computer's
  bots are moved there; otherwise the backup's missing bots are taken in and backed up again.
- The five sample bots remain only for screenshots and tests (State::samples).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:25:01 +08:00
王性驊 b05bec66f4 Pages: phone page fits narrow screens; long stat values a size smaller; ANYBOT_SHOT_PAGE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-05 08:33:23 +08:00
王性驊 2bc573f095 頁面: pages a bot makes and keeps up to date (like the original's tracking pages)
- write_page / read_page / list_pages: Markdown pages with versions (last 10 kept), per bot;
  the reply gets a card (title, fading preview, page icon, 頁面 · 更新時間, 最近更新), and
  [標題](page:ID) links open the page
- The page opens large: summary, what changed, the version picker, 複製 / 存成檔案 / 刪除;
  listed under 資料庫 in the right panel
- Page blocks for richer pages, in the chat's Markdown too: ```stats tiles, ```steps progress,
  > [!NOTE]/[!TIP]/[!WARNING]/[!IMPORTANT] call-outs (with tables and Mermaid charts)
- Phone: the card in chats, page links, a page view with the same blocks; charts drawn by the
  AnyBot as SVG (GET /api/pages/<id>[/chart/<n>]); members may read pages
- Bots are told to make a page for things to track and to update it from a routine only when
  there is real news
- Screenshot views: ANYBOT_SHOT_VIEW=pagecard / page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-05 01:41:41 +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
王性驊 365dc87e54 Add a computer with one line: pairing codes, simpler setups
- 加一台電腦 (phone menu and the app's 大腦 card) gives a ten-minute,
  one-time code and the line to run: anybot setup <address> <code>. The
  new computer joins as hands for that brain with no password and nothing
  to answer, starts with the computer and checks the brain sees it.
- anybot setup without arguments is one screen: address and code (a pasted
  line fills both), or the account and password instead. No role, name or
  confirm questions; a brain is asked only when there are several.
- Hands computers are no longer offered as brains.
- The server setup asks only the domain, account and password.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 20:56:06 +08:00
王性驊 cb922da3fe anybot setup and the server setup: guided setup with a brain picker
- anybot setup: a full-screen terminal guide (role, name, account server,
  account, which brain) that saves the settings, installs a systemd user
  service (with a virtual screen when there is none), and checks that the
  account server and the brain see the computer. Flags for scripts.
- Hands can be limited to one brain; the account server says which AnyBot
  asks. Choosing a brain in the app does the same.
- deploy/server/setup.sh: domain, account, sign-ups and keys step by step;
  writes .env and Caddyfile, starts everything and checks HTTPS. The
  server's brain creates the account on first start.
- deploy/linux/hands.sh installs what's needed and opens anybot setup
  (no password kept in a file any more).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 20:38:45 +08:00
王性驊 b153051e58 Lasting connection to the account server, per-item sync, files and models via the brain
- Each AnyBot keeps one WebSocket to the account server (pinged, reopened
  within a second when cut). Requests come down it at once; calls to other
  AnyBots of the account (brain sync, hands) go up it. Frames carry raw
  bytes, compressed when that saves space. HTTP long-poll stays as fallback.
- The account server knows at once when an AnyBot goes away.
- Edits to lists and maps go item by item, so two computers editing one
  list keep both changes.
- Screens fetch chat files from the brain, get model lists through the
  brain's keys, and show the brain's computer as the brain's.
- Moving this computer's bots skips starter bots the brain has and bots
  already moved.
- The phone goes to the brain instead of a computer that shows it.
- deploy/linux/hands.sh: a Linux computer (with or without a screen) as
  hands, kept running by systemd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 19:30:32 +08:00
王性驊 a70d29fa51 Brain sync: edits in order and kept while typing, plain-language offline messages
- One worker sends edits, messages and actions to the brain in order.
- Edits carry a number; the brain says which it has, and a screen replays
  the rest on top of newer settings so typing isn't undone.
- A message or edit that didn't arrive makes the screen fetch everything again.
- An older copy of a routine can't reset when it last/next runs.
- Network and server failures read as words (no HTTP codes), naming what
  can't be reached; the account server notices a closed AnyBot in 8s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 19:07:55 +08:00
王性驊 5841d797be One brain, many screens: other AnyBots show and edit the brain's bots
- Brain answers /api/sync (per-screen deltas of settings and messages),
  /api/sync/edit (small edit operations) and /api/sync/act (chat actions).
- Relay forwards host-to-host sync requests within one account (role mirror).
- Desktop: choose a brain in 手機與帳號; its own bots are kept aside; offline
  shows the last copy read-only and reconnects by itself.
- Keys and tokens stay on the brain (redacted and restored on edits).
- Browser tools can run on another computer of the account (computer arg).
- anybot --serve: ANYBOT_DEVICE_LINK=1 and ANYBOT_BRAIN=名稱.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 17:46:43 +08:00
王性驊 d7ee3f5db9 AnyBot: first commit of the working desktop app
Rust/egui rebuild of Grok Bot as of 2026-11-04: chat with streaming
providers (xAI, OpenAI, Claude, Gemini, OpenRouter, OpenCode Go, Ollama,
custom), tools and approvals, the bot's Docker computer, computer use on
macOS / Linux X11 / Wayland, AnyBot's browser with a full DevTools-based
toolset, the encrypted vault, pinned grid and sidebar sections, Markdown
with Mermaid diagrams, phone access through the relay, and the Linux
build and test scripts.

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