Attach any file, take shares from other apps, and survive a backwards highlight

Attachments were images only. Now any file can be attached: from the file
chooser behind the "+" menu, or from Android's share sheet, which the app
is now in. An image still goes to the model as a picture; anything else is
stored under its own name (`<hex>-<name>`, cleaned by `safe_file_name`)
and the Claude driver ends the message with `Attached file: /abs/path`,
since the CLI reads files by path and a model cannot be shown a trace. The
user-message field is renamed `images` -> `attachments` on both sides,
with a serde alias reading the rows written before. A share arrives before
anyone has said which session it is for, so it is held in AppRoot with a
banner on the list until a session takes it; an open session takes it at
once. Unreadable shares are reported beside the composer, not thrown.

The tool card crashed the app when opened on a command holding a quoted
glob such as `-path '*/.git/*'`: highlights 1.1.0's shell lexer answers
`x '*/a/*'` with a span whose end is before its start, and AnnotatedString
refuses the range. Such spans are dropped; the library is the place for
the fix. The echo driver gains `/bash <command>` so a card with a given
command can be produced on the emulator.

ui-sandbox.sh's token salvage read the tokens block's close only at a line
start, ran past the compact `),],` the server writes, and copied `setups`
into the new config twice, which the server then refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Fable 5.1 committed 2026-09-03 08:15:10 -04:00
1 parent 4bc69e8f9c
commit 6180663f14
25 files changed
+672 -165

No files matched your search

+13 -4
View File
@@ -713,11 +713,18 @@ host) and **hosts**. The manager runs at most one llama-server per
forwarded port (`ssh -L`) as well as a spawned process. A transport is
therefore "run this" plus "reach this port", and the second operation is
a no-op locally.
- Attachments need no file transfer, contrary to what this section said
- Images need no file transfer, contrary to what this section said
before: `attachment_block` base64s an uploaded image into the
stream-json message itself, and produced images come back the same way
for the translator to write out locally. Nothing has to exist on the
remote filesystem, so there is no `scp` step to get wrong.
- **Any other file is told to the session by path** (2026-09-03: a trace,
a log, a zip -- things a model cannot be shown and the CLI can read).
The upload stays under the session's `attachments/` and the message
ends with `Attached file: /abs/path`. That directory exists only on the
machine running this server, so a file attached to a remote (ssh)
session names a path that is not there. Shipping it is not built; the
one host in use runs its sessions locally. Images are unaffected.
### Usage limits (Claude)
@@ -1094,9 +1101,11 @@ window just fills.
with port forward, attachment shipping. *Host config and remote spawn
done 2026-08-25* (any session of any provider can name a host; the
command is the identical one wrapped in `ssh -T`, with every argument
shell-quoted). Attachment shipping turned out to be unnecessary for the
Claude driver — images ride the stdio JSONL as base64 in both
directions, so nothing needs `scp`. Still outstanding: remote
shell-quoted). Attachment shipping turned out to be unnecessary for
images — they ride the stdio JSONL as base64 in both directions, so
nothing needs `scp` — and became necessary again on 2026-09-03 for
files, which are attached by path (see "Transport" above). Still
outstanding: file shipping for remote sessions, and remote
llama-server with its port forward, which comes with phase 4.
Two things learned doing it: a remote session inherits ssh's non-login
PATH, which is narrower than an interactive shell's (point `command` at