Commit Graph

23 Commits

Author SHA1 Message Date
AnyBot Dev f4c135a98b Audit timeline: what this turn did, on the phone (S5)
- oplog gets wall-clock times on tool records (serde-default: old logs read
  fine), and OpLog::timeline turns the machine log into a story: per turn —
  the prompt, model calls (retries counted into one line), every tool with
  the arguments it ran with and its status (等核准/進行中/完成/被拒絕/失敗),
  messages typed mid-turn, stop, outcome
- GET /api/bots/<id>/audit (owner/admin; members' allow-list untouched)
- 對話詳細資訊 gains a 稽核 tab: newest turn first, running tool shows
  進行中…, an approval gate shows as 等核准 — the phone can answer the question
  'what is my bot doing right now, exactly', step by step
- the log stays the machine format recovery reads; the timeline is derived
2026-11-09 17:59:26 +08:00
AnyBot Dev b23ac40c0b Relay 2FA: TOTP + recovery codes, argon2id, one-page logout (S2)
- login with 2FA on returns a 5-minute challenge, not a session; the session
  comes from /relay/2fa/verify with an authenticator code — or one of eight
  recovery codes, each good once (hash slot emptied)
- /relay/2fa/enroll hands out the secret (QR) + codes once; enabling completes
  only when a real code proves the app has the secret; disable proves the code
- /relay/sessions/logout kicks every device of the account from one page
- password hashes are argon2id (memory-hard, OWASP parameters); stored PBKDF2
  hashes still sign in — no forced reset, upgrade on next password change
- TOTP is RFC 6238 (vectors pinned in tests); mobile page prompts for the
  second step; protocol.md documents the endpoints
- fixes a double-lock in /relay/me found by the flow test (handlers hold one
  data guard: read through it)
2026-11-09 17:52:42 +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
王性驊 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
王性驊 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
王性驊 e8e5e6fba1 Real-use fixes: the person sees the screens the bot shows, files reach the phone, no blank-tab loops
From real runs on the cloud brain with the person's Mac (Threads patrol, a post draft, "show me my
screen"):
- computer_use_show: a plain picture of any computer's screen goes into the chat (the bot sees it
  too). The bot used to describe a screenshot in words and fail to send it.
- The phone shows the bot's attachments: pictures in place, other files download on a tap (api/file,
  only from the chats' file folder). It showed nothing for the bot and names only for the person.
- send_file works from the person's other computers (fetch_file over the relay, 20 MB, secrets stay).
- The same call with the same answer again and again is warned the 3rd time and stopped from the
  4th (a blank tab was read 11 times, then the bot said Threads was logged out without opening it);
  a blank tab says so; checking a login means opening the site.
- Screenshot lists: a nameless row around a named button isn't numbered, a nameless row takes the
  words inside it, empty spacer rows aren't numbered (System Settings: 63 numbers -> 33, all named).
- Writing "in my voice" reads the person's own recent posts first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
2026-11-06 19:37:45 +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
王性驊 61e0531d32 One AnyBot icon everywhere; the phone page fills the screen and shows the app's bot faces
- New icon: the bot's cloud body and slanted eyes (as in the app's avatars) on a dark tile —
  the Mac/Linux app, browser tabs, iPhone home screen (PNG: it ignores SVG), Android and
  notifications. The web had its own ring-and-dot.
- anybot --write-icon out.png size [file.svg] draws any SVG (for the web PNGs).
- Phone: lists that reach the bottom keep their last row above the home bar and Safari's
  toolbar (it looked cut off); bots show their shape, colour and eyes instead of a letter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:20:29 +08:00
王性驊 ad0234d0ce Phone: the computer list waits for a brain that is restarting and goes in by itself (it sat on 離線 until tapped)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:07:43 +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
王性驊 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
王性驊 80fa0cb11f Relay locks, rate-limits and answers by the real peer (proxy trust opt-in); phone page follows 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
王性驊 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
王性驊 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