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:
1 parent
4bc69e8f9c
commit
6180663f14
25 files changed
+672
-165
No files matched your search
@@ -539,17 +539,24 @@ fun setSessionCwd(settings: ServerSettings, sessionId: String, cwd: String) {
|
||||
) {}
|
||||
}
|
||||
|
||||
/** Uploads one picked image; the returned id goes into [sendMessage]. */
|
||||
/**
|
||||
* Uploads one attachment; the returned id goes into [sendMessage]. [name] is what the server keeps
|
||||
* a file under and tells the session; for an image it is ignored, since the model is shown the
|
||||
* picture rather than told its name.
|
||||
*/
|
||||
fun uploadAttachment(
|
||||
settings: ServerSettings,
|
||||
sessionId: String,
|
||||
bytes: ByteArray,
|
||||
mime: String,
|
||||
name: String,
|
||||
): String {
|
||||
val boundary = "----aiapp-${System.currentTimeMillis()}"
|
||||
// The header is a line: a quote or a line break in the name would end it early.
|
||||
val safeName = name.replace(Regex("[\"\r\n]"), "_")
|
||||
val head =
|
||||
("--$boundary\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"image\"\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"$safeName\"\r\n" +
|
||||
"Content-Type: $mime\r\n\r\n")
|
||||
.encodeToByteArray()
|
||||
val tail = "\r\n--$boundary--\r\n".encodeToByteArray()
|
||||
|
||||
Reference in new issue
Block a user