Skip to main content

Module texts

Module texts 

Source
Expand description

Texts read and sent through your phone, as this device does its part (docs/texts.md; the rules are sioul_core::texts, the reading and the sending Java’s: android/…/Texts.java, TextSend.java).

  • On the phone, at each exchange (light_step, under one lock for its processes): Android’s word on each text sent copied into its outcomes; each request decided (texts::verdict), claimed in the private ledger, flushed, before Java hands it to Android; a claim with no word from Android looked for among the texts Sioul sent, else said in doubt.
  • On the phone, never inside an exchange (heavy_step: after the background service’s exchange, or in a thread of the window’s): the whole history read a batch at a time (BATCH texts, MEDIA_BATCH bytes of media put as sealed blobs), every column kept, while the phone charges; then what the phone’s texts changed, when they did (import_now); the texts deleted on the phone marked so, once a day; the sizes the settings say.
  • On a computer: the Texts page (view, conversation), a text written for the phone to send (send, again); the media’s blobs brought and kept sealed (fetch_media, in a thread, never inside an exchange); how far this computer’s clock may run ahead of the phone’s.
  • Every line, and every media file kept here, sealed at rest with a key made from the sharing key (sioul_sync::textseal): no sharing key here, nothing is read or written.

Structs§

Choice 🔒
This device’s own texts settings (texts.toml in the configuration, never shared): on a computer, the phone that sends; on a phone, the largest media file it brings to your computers (MB; none: MEDIA_CAP_MB).
Clock 🔒
How far this computer’s clock may run ahead of a phone’s (texts/clock.json in the state folder): for each phone, the last time its entry said, and the least gap seen in the last day.
Files 🔒
Where the import writes: this phone’s log, its reader, the media copied from Android for a moment.
Gap 🔒
Kept 🔒
The texts, the requests and their outcomes as last read for this device: the whole history is opened once, not at each look of the page (9,800 sealed lines read twice per conversation opened froze the window for seconds); then only the lines the phones’ logs added (rules::Logs: the page reads itself again at each exchange that brings a text), and the requests and outcomes again when their files changed (size and time). The texts each once across phones (rules::one_each), with the country their numbers were keyed by, without the rows’ raw columns (fields, addrs), which only the fingerprints read.
PartResult 🔒
One result, as Java wrote it (TextSend.line): a text’s part sent or delivered; or a multimedia message’s word (“mms”): Android’s code, the row it filed, the HTTP status, the carrier’s answer (M-Send.conf, hex).
Phone 🔒
This phone’s Android.
Raw 🔒
A row as Java read it (Texts.sms, Texts.mms; android/jvm-checks/TextsCheck.java): every column.
Read 🔒
What a step read: its texts as they travel, the media bytes put in the sharing.
Reader 🔒
The reader’s state and the import’s measures, private to the phone (texts/reader.json in the state folder): the rows its log holds, those still to read, when the import began, what the phone holds and how much has gone.
Rows 🔒
Rows of the provider’s two tables (texts::Row), as reader.json keeps them: [id, date] each, in order.
Step 🔒
What the phone’s quick step works with: where it reads and writes (the data folder’s texts, the private texts folder, the other copies of the requests, the sharing’s memory), the sharing’s folder and key, Android (a stand-in in tests).

Enums§

Prepared 🔒
A multimedia message made ready on the phone, before its claim.
Seal 🔒
What seals the lines and the media: the sharing key’s, or the demo’s stand-in (plain; a line marked).
Weigh 🔒
What one multimedia message from here may weigh (decision 5).

Constants§

ANDROID_MAX 🔒
Android’s own maximum when the carrier’s file says nothing (bytes): 300 kB.
CAPS_MB 🔒
The sizes offered for the largest media file (MB): the blobs take 64 MB at most.
DAY_MS 🔒
A day, in milliseconds.
LOOKS 🔒
The settings and your lists and address books, as the page last read them: read again when the settings’ file changed, or after a minute.
LOOK_AGAIN_MS 🔒
A day’s look that could not list every row is tried again this long after.
LOW_KB 🔒
The smaller choice of Settings ▸ Texts (kB).
MMS_FROM 🔒
A multimedia message’s address types (addr.type): who sent it, to whom.
MMS_NOTIFICATION 🔒
A multimedia message still to download (m_type: Android has only its notification).
MMS_SHARE 🔒
How many multimedia messages, at most, a step reads beside the texts.
MMS_TO 🔒
OUTGOING 🔒
Where a multimedia message waits on the phone, in the private texts folder.
OWN_ADDRESS 🔒
What Android writes for “this phone” in a message’s addresses.
READER_VERSION 🔒
The reader of the archive. The first version read 30 days: its marks would pass the history, so its reader starts again from the first row. The second and third knew rows by their ids alone: the log tells which rows it holds (Reader::index), and what it lacks is read as a history.
RESULTS_ASIDE 🔒
Java’s results set aside at the last trim (trim_results), read beside its file until the next.

Statics§

ATTACHING 🔒
One attaching at a time: a second one waits, then makes its own anew.
ATTACH_TURN 🔒
Each attaching’s turn, and each letting go’s: an attaching whose turn passed (a newer one asked, or the files let go meanwhile) makes nothing, or deletes what it made. The window never waits on ATTACHING.
FETCHED 🔒
The phones’ logs as last seen by fetch_media (each file’s size and time), and whether media were left for next time: nothing new, nothing done.
KEPT 🔒
LIMITS_ASKED 🔒
When the carriers’ limits were last asked in this process (ms): once an hour at most.
RESULTS_TRIMMED 🔒
When Java’s results were last trimmed in this process (ms): once a day.
TRIMMED 🔒
When this device last took its old requests and outcomes out (ms): once a day.
WORKING 🔒
The import (a phone’s window) or the media’s fetching (a computer) running in a thread of this process.

Traits§

Android 🔒
What the import asks Android (Java’s Texts.call, through steps::java): the phone’s own provider of texts; a stand-in in tests.

Functions§

again 🔒
Send again: a request of its own, a new key, the same number and words; a multimedia message’s media again, sealed in the sharing already.
ahead_of 🔒
How far this clock may run ahead of a phone’s (ms): the least gap of the last day, 0 unknown.
ask_media_again 🔒
A medium the page shows that is not here: Sioul keeping the folder itself asks for it again as if new, once it had stopped asking (three days in vain, sioul_sync::remote::sealed_step; review of 18 October 2026, L-8).
at_start 🔒
At the window’s start (lib.rs run, once this process is the profile’s Sioul): what an earlier run left attached on the Texts page, one that quit or crashed with files attached, goes (the review of 18 October 2026, I-6).
attach 🔒
The files chosen on the page (sources, files or their addresses) made fit for one multimedia message to a conversation (attach::make; what an earlier attaching made goes first), off the window’s thread: {round (as asked: the page keeps its latest), media: [{source, kind, ct, path, url, size, said}], said: [why each other did not go], limit (its words), max (bytes)}. Nothing travels until Send.
attach_limit 🔒
What a multimedia message from here to a conversation may weigh (bytes) and its pictures’ long side at most (0 none), from the phone that sends (weigh); else why nothing can be attached, its words’ key: no phone, a group (a later step), the phone not having said what its carrier takes (Attach is offered only once it has, decision 11), its carrier taking none.
attach_made 🔒
The files chosen made fit (attach::make), on a computer.
attached_folder 🔒
Where the files attached on the page wait, made fit (Sioul’s cache, yours alone).
before_exchange 🔒
Before an exchange: on a phone, the quick part of its step; on a computer, how far its clock may run ahead of the phone’s. Then, in a thread of its own that never holds the exchange: the import’s next batch (a phone’s window; the background service runs it after its exchange) or the media brought here (a computer); what came said to the window (qt) as an exchange’s news are (shared_in), so that the pages showing texts read them again at once. Once a day, old requests and outcomes out (texts never).
bring_media 🔒
Each part of a message that travels, copied from Android into the private folder, hashed, put in the sharing as a sealed blob (never inside a line), the copy deleted; within budget bytes, the first part of a step always. Whether every part was brought (else the message waits for the next step).
call 🔒
What the window asks (Sioul::texts): “view” {query}, “conversation” {id}, “send” {to, body}, “send-mms” {to, words, media: [{ct, path}], phone} (a multimedia message, its media made fit already by attach: a file elsewhere is refused), “again” {key}, “parts” {body, media: [{ct, size}], id, phone} (with media, how much the message takes), “sending” and “limit” {value} (Settings ▸ Texts on a computer), “media” {hash, ct} (its address, to show or open it), “save-media” {hash, ct, path}, “close” (the page closed: the media opened for it and the files attached deleted), “unattach” (the files attached let go), “setup”, “ask” (Android’s question for the permissions), “info” (Sioul’s app info), “part” {on}, “cap” {value}; and “access…”, what Android withholds here (access::call). Its JSON, and whether what travels changed (to share now).
cap_mb 🔒
The largest media file brought to your computers, in MB.
changes 🔒
Java’s word on the phone (Texts.changes): whether its texts changed since it was last asked with clear (a text came, was sent, deleted or read: Android’s provider watched by the background service; not watched in this process, or no answer: yes, as at every step before), and whether the phone is on its charger.
choice 🔒
choice_path 🔒
conversation 🔒
One conversation (TextsPage.qml): {id, title, messages, can_write, group, attach (Attach offered: the phone said what its carrier takes), attach_said (else why not)}.
conversation_of 🔒
A person’s conversation on the Texts page, from their numbers as written: the first whole one, keyed; “” while texts are not read here.
delete 🔒
A conversation deleted in Sioul (23 October 2026): Sioul is never the phone’s SMS app (it asks no SMS role, docs/texts.md), so Android lets it delete nothing from the phone’s provider. Its texts until now leave Sioul on every device (a sealed mark; the phone writes its log again without them, so every computer’s copy follows); the phone’s own texting app keeps them. A text that comes later starts it again.
demo 🔒
The demo profile (SIOUL_DEMO=1, which tools/demo/run.sh sets in its sandbox with no network, and nothing else does): its texts are stand-ins written plain by tools/demo/make-demo.py, its phone a stand-in.
draft_taken 🔒
A draft an AI agent wrote, used (its words, for the box: sending stays yours) or discarded: taken out of the drafts either way. {body}, “” when gone.
failed_status 🔒
The carrier’s refusal Android read for a message it filed among the failed (box 5), its status (resp_st, as Texts.findMms gives it), when it read one: none when Android filed it there with no answer it could read (SendRequest.persistIfRequired).
fetch_media 🔒
The media the texts name and this device has not yet: brought from the sharing’s blobs, sealed here, MEDIA_BATCH bytes at a time (the first always); one the sync app has not brought yet waits for next time. Whether one was brought.
folding 🔒
Whether a phone’s notification of a text (its sender’s key, its time) is a text the Texts page holds, or held before its conversation was deleted: folded into it, never a second item on the Porch. None where texts are not read here: every notification stays a line.
forget_hidden_media 🔒
The media of hidden texts gone from this device’s copies, unless a text shown holds them too.
guard 🔒
What the tab says beside its question once the texts’ permissions were asked and are still not all given (Texts.state): “guarded” on Android 15 and later, where restricted settings may keep them from an app installed from a file (13 and 14 keep notification access only); “at-once” when Android answered without showing a question (“Don’t allow” chosen twice); else “”.
heavy_step 🔒
The part that may take a while, never inside an exchange: the import’s next step when due (import_now: caught up, what came; a history, all of it, on the charger), else the newest texts while a history waits for the charger (recent_now); and the day’s look for deletions. Under its own lock: one import at a time on the phone.
here_media 🔒
import_now 🔒
Whether the import reads the phone’s texts now, at now (ms; docs/texts.md, “Reading, on the phone: paced”). A history (the first import’s, or a block of old texts put at once), all of it only while the phone charges: it may write and send hundreds of megabytes, on mobile data too. Caught up, when the phone’s texts changed since the last look, when the last step left texts that came (their media over its share), and with the day’s look for deletions all the same (a change Android did not say): most steps find nothing new, and ask Android nothing.
import_step 🔒
One step of the import (docs/texts.md, “Reading, on the phone: paced”). Every row the phone holds is listed with its date (texts-ids), and those its log lacks are the ones to read, wherever their ids are (the plain texts’ table gives a deleted newest text’s id to the next one; a provider emptied starts again at 1). Rows that appeared since the last step are read at once, on the battery too, oldest first; 500 or more at once are no texts that came but a block of old ones (SMS Backup & Restore restoring a history), read as a first import is: the newest first by date, with all (on the charger) BATCH at a time, else only those newer than the newest text read before and than a day before the history was found, so that a text that comes meanwhile reaches your computers within a minute or two. Media within MEDIA_BATCH bytes, the first always. A step with nothing to read asks Android one listing. Whether anything was written.
importing_in_bulk 🔒
A bulk import going on, on the charger or waiting for it (import_now): the sharing’s full rounds wait meanwhile (steps), so that it does not restate the records again and again (8 October 2026: a first import made six full rounds, each sent twice).
int 🔒
kept_words 🔒
What this device keeps of the texts, for its part’s line in the sharing panel (“Keeps 4,830 texts and 210 MB of media here.”); “” when none.
let_attached_go 🔒
The files attached let go, and any attaching under way told so: the window’s thread never waits.
light_step 🔒
The quick part of the phone’s step, at every exchange: Android’s words copied, the requests decided and sent, a lost claim looked for, what the carriers let it send said (once an hour at most), what a multimedia message left behind swept. Under one lock for the phone’s processes. Whether something was written.
limit_lines 🔒
What a phone’s carriers take, in words, read only: one line, or one a SIM in its order (“SIM 2: multimedia messages up to 600 kB. Pictures up to 2592 × 1944 pixels.”); none said yet.
limits_from 🔒
What each SIM’s carrier lets the phone send, as Java read it (Texts.limits).
listed 🔒
Every row the phone holds, from a texts-ids answer: each id with its own date (sms_at, mms_at). None when the dates did not come with the ids: then nothing is read for this step, never every row taken as new.
look_again 🔒
Once a day: what the phone holds measured for the settings; the log’s own counts taken again (Reader::index); and each text gone from the phone marked so in the log, a line each, once (the archive keeps the text): a row the phone no longer lists, by its id and its date, so that a text deleted and the next one taking its id are told apart. The rows to read are the steps’ own (import_step). Whether a line was written.
looked 🔒
Whether Java could look in the provider (Texts.findMms): the permission given and the query answered. A look not made is never read as “not there”: made again at the next step.
looks 🔒
The settings and your senders for the page’s looks (LOOKS): each opening of a conversation read them twice, on the window’s thread.
made_in 🔒
Whether path is a file in folder (the files attached, made fit), its links and .. resolved: none elsewhere is sent as a medium.
mark_read 🔒
A conversation opened in Texts: read up to its newest text, on every device, and the phone’s notifications of it seen (gone from the Porch’s notices).
marked 🔒
Every device’s marks, and every text with those hidden: for the Porch’s folding (a notification of a text deleted since folds into nothing shown).
measure_clock 🔒
At each exchange: the sending phone’s entry’s time, when it changed, compared with this computer’s clock; the least such gap of the last day is how far this clock may run ahead of the phone’s (transit included: an upper bound, so that a request looks older, never younger).
media_path 🔒
A media file kept here, sealed: texts/media/<hash> in the data folder.
media_to_send 🔒
The media of this computer’s multimedia messages that may still go (written within their quarter of an hour), by their sealed files’ names in the sharing and the size each was sealed at: they go up first on the urgent lane (remote::send_urgent), before the request that names them.
mms_outcomes 🔒
Each multimedia message’s outcome from its result (texts::took, with the HTTP status Java read): sent (Android’s Ok and the carrier’s), not sent and why, in doubt when each of Android’s tries ended on the network (“network”: the carrier may have it); and the keys whose result is Android’s Ok without the carrier’s answer, for the sent box to say (Step::copy_results). Never “delivered”: no report is asked.
name_rows 🔒
Each outcome’s row by its name in the log (texts::Row::name): Android says a sent message’s row by its id alone, which an older one may have held (the plain texts’ table gives a deleted newest text’s id again); the row’s date, read from Android now, tells which it is (a multimedia message’s in seconds). A row Android no longer holds is left unnamed, never named after an older message.
names 🔒
notices 🔒
The Porch’s notices of texts not read yet (23 October 2026): one per conversation, its sender and the newest’s first words, opening it in Texts; [] where texts are not read here.
now_ms 🔒
open_media 🔒
A media file opened for the page or saved: its plain copy in opened_folder; none when it is not here.
opened_folder 🔒
Where a media file is opened for the page: Sioul’s cache (yours alone), emptied when the page closes.
outcomes_from 🔒
Each text’s outcomes from its parts’ results: sent when every part was; not sent, and why, when one was not; delivered when the carrier said every part was received (never “not delivered” for a report that did not come).
part_of 🔒
A part as it travels: its words in the line; its content said, to be put in the sharing (bring_media) when it is not over cap bytes.
parts 🔒
How many texts a draft takes: {parts, said}.
parts_mms 🔒
How much a multimedia message takes, as its words are typed: {parts, said (“One multimedia message (412 kB of 600 kB)”), over, max (bytes)}, its media counted by their lengths alone (mms::size_with_lengths).
phone 🔒
Whether this device reads and sends texts: a phone. SIOUL_TEXTS makes a computer’s step run too, to look at it.
phone_step 🔒
The background service’s step, after its exchange: the quick part, then the import’s next batch. Whether something was written to share now.
phones 🔒
The phones in the sharing, the one chosen to send first, else the one that shared last.
private 🔒
raws 🔒
read_rows 🔒
The rows wanted read from Android in one question, taken in that order, each as it travels, its media put in the sharing within budget (the first medium of a step always). A multimedia message whose media do not fit stops the multimedia messages there for this step; the plain texts go on. A row gone meanwhile, or whose id another row took meanwhile, is left to the next listing. None when Android did not answer.
readable 🔒
Whether the Texts page has something to show here: the part on, and a phone that sends.
reason_of 🔒
Android’s code for a part not sent, as the words say it (SmsManager’s RESULT_ERROR_…).
recent_now 🔒
Whether the newest texts are read now while a history waits for the charger (import_now): at a first import, at the first step of a reader of an older version (its log tells which rows it holds), then each time the phone’s texts changed, on the battery too; only the rows that came and the history’s newest (import_step), so that a text that comes during a long import reaches your computers within a minute or two.
records 🔒
The texts, the requests and their outcomes (KEPT): the logs read on where they grew, the texts made again only then (or for another country); the requests and outcomes read again when a file changed. The texts each once, a text found in two phones’ logs (a restore onto a new phone) shown once (rules::one_each).
request_mms 🔒
A multimedia message’s request, its media sealed in the sharing already.
requests_from 🔒
The requests under each root (<root>/send/<device>.jsonl), each key once, the first root’s first: the ledger then decides each once.
results_of 🔒
Java’s results (TextSend.Result‘s lines): its file, and the one set aside at the last trim; only those of the outcomes’ month (rules::KEPT_DAYS), so that a result whose outcome was trimmed is never said, written and shared again (the review of 18 October 2026, I-f).
root 🔒
row_of 🔒
“content://sms/414” → “sms-414”, “content://mms/sent/31” → “mms-31”: the row as the log names it, its date read after (name_rows).
sealed 🔒
This device’s name in the sharing, the sealer, and the sharing’s folder and key, while the part “texts” is on here (the demo: no folder).
sealed_here 🔒
Whether a multimedia message’s media are all in the sharing (the folder, or the copy fetched from its server beside it), not opened.
send 🔒
A text written here for the phone to send: refused at once when the phone would refuse it (said why), else a request with a key of its own in this device’s file, which the sharing carries. {said, shared, key}.
send_mms 🔒
A multimedia message written here for the phone to send (docs/texts.md, “Multimedia messages sent from a computer”; the media reduced already, each its content type and bytes): refused at once when the phone would refuse it (said why); else each medium sealed into the sharing’s blobs (content-addressed: one sent twice travels once) and into this computer’s own media, so that the message shows it at once, then the request, whose media go up before it (media_to_send). Never a file’s own name: a medium is its content alone. {said, shared, key}.
sending 🔒
Settings ▸ Texts, on a computer: how much a multimedia message from here may weigh, the carrier’s or less (300 kB), and what the phone said its carrier takes, read only. {limit: a setting’s row, phone: its lines}.
sending_phone 🔒
sends_texts 🔒
Whether a phone sends texts for this computer: the part on here, and its texts read here (its log): a text that came to it is answered from it.
sent_row 🔒
The row Sioul’s multimedia message was filed as in the sent box, by its key (tr_id), as Java found it (Texts.findMms: Sioul’s rows alone): its name in the log; none in the sent box (a failed one is out of sight).
sent_to 🔒
The texts this computer wrote from a phone to a number (dial) since a moment (ms), oldest first, for the Porch’s reply under a line (replies::Mine): the words and their state in the texts’ own words (“Sent at 14:03.”).
set_cap 🔒
The largest media file brought to your computers, chosen on the phone (MB).
set_limit 🔒
The most a multimedia message from here may weigh: the carrier’s (“carrier”) or 300 kB (“300”).
setup 🔒
The phone’s tab (TextsSetup.qml): {android, state (each permission, the SIMs), on (the part here), sharing, progress (what the phone holds and how much has gone), importing (more to go), cap (the setting row of the largest media file brought)}.
size_words 🔒
“1.2 MB”.
stamps 🔒
Each file of the requests and the outcomes, its size and time.
standing_in 🔒
Where a device stands, by the sharing’s two sets (share::asking).
standing_of 🔒
Where each device that may ask this phone stands in the sharing now (share::asking), for the replies’ step (replies.rs).
string 🔒
text_of 🔒
A row Java read, as it travels: its people keyed (its conversation’s, else its own addresses), its words, its parts said (their content left for bring_media), every column kept as it came.
texted_since 🔒
The numbers this computer texted (phones::key) whose phone took the text since a moment (ms, the phone’s clock): handed, sent or delivered then.
threads_of 🔒
The conversations’ people of a texts-read answer, by thread.
trim_results 🔒
Java’s results file kept to the outcomes’ month, once a day, in the phone’s step under its lock (the review of 18 October 2026, I-f). Java appends to it by its name at any moment, from either of the phone’s processes: it is never written over. It is set aside by a rename, and the lines kept are appended to the new one Java’s next line makes; the file set aside is read too until the next trim, which first brings back the line Java may have appended to it as it was renamed.
unhex 🔒
Hex’s bytes; none for what is not hex.
view 🔒
The Texts page’s list (TextsPage.qml): {can (the part on, a phone that sends), phone: {id, name, shared, said}, conversations, said, never, empty (the list’s words when it has no row)}; without them, can false and why. With query, the conversations holding a text with all its words (or whose people’s names or numbers do), each with the newest such text as its last words.
weigh 🔒
What one multimedia message from here to a conversation (id, its number’s key) may weigh, from a phone (decision 5): as the phone last said its carriers take (texts::limits_of), for the SIM the conversation last used (weighed).
weighed 🔒
What a message may weigh by what the phone said (limits, none before it said): its carrier’s for sim (the conversation’s last; when it is unknown, -1, or the phone did not name it, the smallest of those that take multimedia messages), and no more than chosen here (chosen_kb, Settings ▸ Texts: 300 kB); with the carrier’s largest picture’s long side.
with_drafts 🔒
The conversations with the drafts an AI agent wrote for them (textdraft, docs/mcp.md, “Texts”): how many wait in each, said under its last words; a draft to someone with no conversation yet makes one, first.
write_flushed 🔒
A private file written whole beside, flushed to the disk, then put in place.
write_log 🔒
Texts added to this phone’s log, each line once: how many were written, or why none could be.
write_whole 🔒
A private file written whole beside, then put in place.

Type Aliases§

Vault 🔒
The sharing’s folder and key: where the media’s blobs go and come from.