Commit Graph
18 Commits
Author SHA1 Message Date
HomerandClaude Opus 5.5 3101552858 Settings › About: the Desktop release the server recommends (GET /apps)
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
Offered when newer than this install, a beta only to a beta install, and
only with the project's own release page as the link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 14:19:11 +00:00
HomerandClaude Opus 5.5 9b07527c3a Scheduled-result notifications: first lines, Open / Run again / Pause; a click opens
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
A run's own notification (run.notification, server dev) gives the body (the
result's first lines) and the actions with labels in the person's language;
they become the notification's action type. Every notification is
remembered by id (watch::Notes) so a click opens the chat or the task, and
Run again / Pause post /schedules/{id}/run|pause without the window. An
older server's run is said as before. Fixtures re-pinned at server dev
e0c2332, schedule.json added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 14:08:04 +00:00
HomerandClaude Opus 5.5 2b87fa4c29 Voice (dictate, read aloud) and Draw a picture over /v1, with the app's models scope
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
The server kept voice and images on /v1 (models scope, which the app's token
already asks for); /me's services and scopes decide what is offered. Rust
sends the recording to /v1/audio/transcriptions, reads /v1/audio/speech back
as a data: URL (CSP media-src data:), and for /v1/images/generations takes
only the id of each of the person's own files from the answer and fetches
/v1/files/<id>/content from the app's own server. The microphone is allowed
only within seconds of the page's own Dictate (voice_arm); WebKitGTK's
media stream is switched on through its settings getter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 14:02:56 +00:00
HomerandClaude Opus 5.5 67ce6076c5 Library upload, new folder, rename and delete; a chat's tools and skills (/scope)
ci / ui (push) Waiting to run
ci / check (push) Failing after 4s
ci / start (push) Failing after 4s
Files -> Server writes through /api/v2/files/{upload,mkdir,rename} and
DELETE /files (the trash); upload is a Rust command (library_upload) that
picks files in the system dialog and sends them multipart in the field
`files`. A chat's menu opens Tools and skills..., the web's chat-settings
switches over GET/POST /chats/{id}/scope and /allow/clear. A popover can
open at a context menu's point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:53:38 +00:00
HomerandClaude Opus 5.5 d691a4dcfa Memory page and search inside chats, files and memory (Ctrl+K, GET /search)
ci / ui (push) Waiting to run
ci / check (push) Failing after 7s
ci / start (push) Failing after 5s
The account's memory as the web's Settings -> Memory keeps it: add, change,
remove, over /api/v2/memories. Ctrl+K asks the server's search once two
letters are typed and lists the hits below the titles, the matched ranges
drawn as <mark> elements over plain text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:44:49 +00:00
HomerandClaude Opus 5.5 be70e1a628 Pinned chats and chat folders in the sidebar
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 4s
The server's /api/v2 sets `pinned` on PATCH /chats/{id} and makes, renames and deletes
folders. The sidebar lists the pinned chats first, then the folders (nested, folded as the
server keeps them, each counting its chats), then the rest by day; searching lists every
match flat. A chat's menu pins it and moves it (to no folder, any folder, or a new one);
a folder's menu renames it, makes one inside it, deletes it (its chats stay). Tests F8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:24:34 +00:00
HomerandClaude Opus 5.5 04736db057 Language and theme follow the account: PATCH /me for the theme, /me's language by default
ci / ui (push) Waiting to run
ci / check (push) Failing after 2s
ci / start (push) Failing after 2s
The server's /api/v2 now has PATCH /me {language, theme} and /me lists its languages and
themes. The theme is the account's and choosing one saves it there (a refusal is said);
a server whose /me lists no themes keeps the earlier choice in the app. The language is the
account's unless Settings chose this computer's or another (kept in the app, as the phone
does); a change of the account's opens the window again in it, once.

Fixtures re-pinned to the server's dev (f7f2ff2), with the new /api/v2 parity ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:19:44 +00:00
HomerandClaude Opus 5.5 151fc5fcca Settings: language and theme, kept in the app
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
ci / ui (push) Waiting to run
Appearance in Settings chooses the language (the system's, or one of the nine the app has;
the window opens again in it, its replies and shells let go first) and the theme (the
account's, or Moria or Shire, drawn at once and the window painted in it). Kept in
localStorage on this computer: /api/v2 has no PATCH /me for either yet, so the account's
own stay as they are. i18n.js reads the choice and carries each language's own name from
the server's catalogue. Tests E5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:14:36 +00:00
HomerandClaude Opus 5.5 d4a1f13cf1 Terminal: a shell that ends while its panel is shown again is not replaced
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 2s
Showing the panel connects a frame later (the panel needs its width first). A shell that ended
before that frame -- reopened and closed by the server within one frame, as headless CI's slow
frames made happen -- was quietly replaced by a new one, against "no reconnect of its own".
The frame now connects only if no shell was open as the showing began. The cause of the
B3 failures on GitHub since 94e903e; a test makes it happen every time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:14:23 +00:00
HomerandClaude Opus 5.5 effcc2c2fd tests/ui: a failure's annotation on GitHub names the line of run.mjs
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 13:07:48 +00:00
HomerandClaude Opus 5.5 97c2301bab A new agent chat on another linked computer (as the web and Android can)
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
Where the account has another computer linked (GET /devices), a chip before the folder
chooses it; this computer stays the default. Its folder is one its agent chats have worked
in, or a path typed in; the Terminal before the first message opens there too. Tests D4;
failing UI tests are also GitHub annotations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 12:55:54 +00:00
HomerandClaude Opus 5.5 94e903ef70 Archived chats: a page to find them again, Restore chat, delete
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
Archive was one-way in the app. Archived (sidebar, under Files) reads
GET /api/v2/chats?archived=true, newest first and paged; a row opens the
chat, Restore chat PATCHes archived:false and reads the sidebar again, and
the row's menu deletes. An open archived chat says so in its header, with
Restore chat there and in its menu. The words are the web's own ("Archived",
"Restore chat"). Tests: D2 at 1280 and 390 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 12:19:35 +00:00
HomerandClaude Opus 5.5 4b5b22c7d4 Subagents (C4): the tree in the activity panel, read-only sessions, findings, stop; agent chats' setting
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
On the server's /api/v2 (3.4.0, server dev 5d7b79c):
- The activity panel reads GET /chats/{chat}/tree beside the activity and
  draws ui/js/tree.js's rows in a Subagents section, the server panel's words
  and layout: nested by parent, position, phase, context %, state, model,
  mode + request options, messages and the last one, open slots, the ended
  ones folded and dimmed. A team's members are no longer drawn again among
  the tasks. The stream's `tree` frame redraws it.
- A subagent's conversation (/subagents/{id}/transcript, read again every 3 s
  while it works) and its findings open read-only in the panel; Stop asks,
  then POSTs /stop. With an agent chat's device away: the kept tree with the
  server's note, and its 409 sentence for the rest.
- A new agent chat's Subagents chip from /models?kind=agent&device= (each
  model's `subagents`, `agent_subagents.offered` and `device_runs`); an open
  agent chat's from its own `subagents`, as before.
- An approval item's `subagent` names it on the card.
- Progress keys are the spec's own ({{field}}), as the server's catalogues
  have them; SERVER_PENDING is gone, every sentence is translated.

tests/ui reads the server's contract fixtures (scripts/fetch-fixtures.sh ->
tests/ui/fixtures, SOURCE says the commit): status frames, tree, tree frame,
transcript, findings, models?kind=agent, a subagent's approval; six C4 cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 10:44:35 +00:00
HomerandClaude Opus 5.5 89c769c806 Subagents (C4, ahead of the server): the 3.4.0 tree as rows, not yet in the panel
ci / ui (push) Waiting to run
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
ui/js/tree.js draws subagents.md §12's data: the main agent at the root, each
subagent under its parent in the order added (name, id, position, state in
team.read.states' words, model, mode with request options, context % and a
meter, its progress line, its room messages and the last one), open slots, and
the ended ones folded apart, dimmed, with how each ended; open its session,
its findings, stop a live one. Not wired into the activity panel yet: the
server's /api/v2 does not carry the tree, the transcript or the findings yet.

tests/ui: the spec's own example tree, drawn and acted on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 09:38:52 +00:00
HomerandClaude Opus 5.5 3baae016e1 Progress: the reply's line is the 3.4.0 progress object, {{text}} · {{elapsed}}
ci / start (push) Failing after 2s
ci / check (push) Failing after 3s
ui/js/progress.js draws harness spec 3.4.0's `progress` (progress.md) with the
spec's texts as the page's sentences: the thirteen phases, their variants and
field words, the line with its clock in whole seconds (5s, 1m 05s, 1h 02m),
none for stopped and failed, retrying counted down. A live reply takes
`progress` from any stream frame that carries it and ticks once a second; with
no progress (an older server, or null) it draws the status text as before.

The sentences are the server's to translate: gen-i18n.py takes them from its
catalogues once they are there (SERVER_PENDING), English until then, without
failing.

tests/ui: every case of the spec's conformance/progress.json (copied, 3.4.0),
and a live stream's progress, clock, fallback and stopped line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 09:10:20 +00:00
HomerandClaude Opus 5.5 ac0d4ce623 Terminal: a shell on the agent chat's computer, before the first message too
ci / check (push) Failing after 2s
ci / start (push) Failing after 2s
The Terminal panel opens a shell on the device an agent chat works on, in its
folder: for a new agent chat as soon as the device and folder are chosen (the
server's /api/v2/devices/{device}/terminal/ws?directory=, which the chat's first
message takes over -- the same socket carries on), and for an open agent chat
from the header (/api/v2/chats/{chat}/terminal/ws, the web page's shell).
Offered where GET /devices says the device opens a terminal.

The socket is Rust's (src-tauri/src/terminal.rs, tungstenite on the rustls
ureq already brings): the bearer token goes in the handshake and never reaches
the page, which gets the frames as `terminal` events and sends keys, sizes and
close through commands. 4401 signs the app out as a 401 does.

xterm and its fit addon are the server's vendored build, pinned through
fetch-vendor.sh like CodeMirror and loaded on the first open. Send to chat puts
the selection, the last marked command and its output, or the screen into the
composer, never sent. The terminal and the activity panel take turns in the
panel column. Continue in a terminal stays in the chat's menu.

tests/ui: seven B3 cases with a mocked socket, at 1280 and 390 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 09:06:01 +00:00
HomerandClaude Opus 5.5 ec32bca644 Subagents: a new chat reads /models again, so subagents switched on later show
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s
The Subagents chip on a new chat follows `/models` -> model.subagents.offered, the same
team_run.offered the web page renders from. The app read /models once, at sign-in, and kept
it while it stayed open in the tray: subagents switched on afterwards (or a model added)
never reached a new chat until a restart. startNew() now re-reads it (at most every 5 s,
keeping the last list if the read fails) and redraws the draft's chips (modelsChanged()).
An open chat already re-reads its own `subagents` with GET /chats/{id}.

tests/ui: A5 cases -- parallel model offered: chip, slider to the server's cap, no note;
one-request model offered named_only: the `own` note; offered false everywhere: no chip;
switched on while open: the next new chat has it; an open chat follows its `subagents`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 08:17:30 +00:00
HomerandClaude Opus 5.5 5a87eec28d Approval cards show again: the buttons no longer throw, the command is the item's detail
ci / check (push) Failing after 3s
ci / start (push) Failing after 2s
An agent chat's bash approval left "Waiting for you to allow bash…" with no card: cardOf()
called append(actions, a, b, c) while append() took one array, so `children.flat` threw for
every approval and plan card (questions used el.append and worked). renderCards() had already
unhidden #cards, which stayed empty. append() now takes children as rest arguments too.

- The editable command is `detail` (services/device_link.py puts the fixed "Run a command" in
  the title); it is sent back as the item's text only when changed. Non-editable approvals
  show the title and the device's input. `purpose` ("It says: …"), `reason` and the asking
  subagent (`job`) are shown, as on the web page.
- renderCards() keeps a card already on the screen (by id) instead of drawing every card again
  on each `ask` frame, which the server re-sends whenever the countdown changes; a card that
  cannot be drawn shows the error instead of an empty box.
- tests/ui/: headless harness with a mocked Tauri bridge; five A1 cases (device bash card
  shows and is visible, Allow/edit/Deny post to /chats/{id}/interactions/{card}, redraw keeps
  edits, reopen gets the card from the stream's first pass, 390 px).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 08:13:02 +00:00