Zum Artikel springen
HB CodeDocsApp herunterladen

HandbuchArchitektur

Befehlsausgabe, Dokumente und Vorschauen

Wo die Befehlsausgabe bei Codex und bei Claude liegt und wie ein Betrachter sie in Bereichen liest, wie HTML-Dokumente auf drei Plattformen in einem abgeschotteten Ursprung laufen, wie Webseiten zu Markdown werden und wie Dateien in Blöcken übertragen werden.

Gegen den Quellcode geprüft am 5. Oktober 2026

Auf dieser Seite

Codex-Befehlsausgabe als Desktop-Artefakt

Die beiden Agenten bewahren Befehlsausgabe an verschiedenen Orten auf. Dieser Abschnitt behandelt Codex. Nur ein Codex-Run schreibt ein Desktop-Artefakt: eine Datei pro Befehl im Ordner codex-command-outputs unter dem lokalen Datenordner der App, benannt mit 32 Hexadezimalziffern und der Endung .output. Die Katalogtabelle codex_command_outputs ordnet dem Schlüssel (run_id, command_id) die Datei, ihre Bytelänge, ihre Generation und die Markierungen complete und source_incomplete zu. Eigentümer ist die Basis-Session, und ein Lesezugriff aus einer anderen Session scheitert mit einem Konflikt.

Nur Codex: Befehlsausgabe wird vom Desktop abgeholt, solange der Befehl läuft, und von Codex, sobald er abgeschlossen ist
Nur Codex: Befehlsausgabe wird vom Desktop abgeholt, solange der Befehl läuft, und von Codex, sobald er abgeschlossen istEin Codex-Befehl im Zeitverlauf. Codex streamt Ausgabe-Deltas und schreibt eine eigene Mitschnittdatei, der Desktop hängt jedes Delta an sein Artefakt an, und die Timeline-Zeile erhält nur Größe und Generation. Ein offener Betrachter liest bis zu 256 KiB auf einmal aus dem Artefakt. Bei item/completed vergleicht der Desktop seine Bytes mit dem aggregatedOutput von Codex. In diesem Fall ist das Aggregat nicht gekürzt, und seine Bytes weichen ab. Es ersetzt deshalb das Artefakt als Generation 2, ein Lesezugriff für Generation 1 erhält einen Konflikt, und der Betrachter aktualisiert die Zeile. Sobald die Zeile abgeschlossen ist, zeigt sie auf die Mitschnittdatei von Codex, und Lesezugriffe gehen über den Desktop an thread/commandOutput/read.
Codexführt den Befehl aus
Desktop-Artefakt
Mitschnittdatei
Ausgabe-Deltas mit Bytes
abgeschlossen, mit Aggregat
Generation 1, jedes Delta angehängt
Generation 2
andere Bytes, nicht gekürzt: Generation 2
Timeline-Zeile
Größe und Generation, keine Bytes
abgeschlossen, zeigt jetzt auf Codex
Betrachter
geschlossen, kein Lesen
liest bis 256 KiB
Generation 1 ist weg: Konflikt, Zeile aktualisieren
nicht mehr gelesen
liest den Mitschnitt von Codex über den Desktop
item/started
item/completed
Zeile steht fest
  • Live-ZeilecommandOutput.artifact

    Der Desktop hängt jedes Ausgabe-Delta an sein Artefakt an, bevor sich die Zeile ändert, und sendet dann runId, byteLength, generation, complete und sourceIncomplete höchstens alle 100 ms pro Befehl. Kein Ausgabe-Byte gelangt in die Timeline.

  • Bereichslesenrun.chatCommandOutputRead

    Nur ein offener Betrachter liest, 1 Byte bis 256 KiB pro Anfrage, und appSessionId bindet den Lesezugriff an die besitzende Basis-Session. Eine Generation, die das Artefakt nicht mehr hält, wird mit einem Konflikt beantwortet, und der Betrachter aktualisiert die Zeile, bevor er erneut liest. Telefone rufen ihn über das Relay auf, der Betrachter auf dem Desktop ruft denselben Lesezugriff direkt auf.

  • Abschlussitem/completed

    Der Desktop vergleicht seine Bytes mit dem aggregatedOutput von Codex. Dieselben Bytes markieren das Artefakt an Ort und Stelle als vollständig. Abweichende Bytes ohne Kürzung ersetzen es als nächste Generation. Ein gekürztes Aggregat ersetzt nie einen längeren Stream, was die nächste Abbildung zeigt.

  • Abgeschlossene ZeileprotocolOutput

    Sobald thread/items/list den Befehl liefert, zeigt die Zeile auf die Mitschnittdatei, die Codex während des Laufs geschrieben hat, und ein offener Betrachter auf dem Desktop folgt ihr über die unveränderte Block-ID. Der Desktop leitet Lesezugriffe als thread/commandOutput/read weiter und prüft die zurückgegebene Identität. capturedComplete ist false, wenn Codex keinen vollständigen Mitschnitt behalten hat.

Codex sendet jedes Ausgabe-Byte im Delta-Stream und behält für item/completed ein begrenztes Aggregat von höchstens 1 MiB. Der Desktop behandelt das Aggregat deshalb als Prüfung und nicht als Wahrheit. Er zählt die Bytes und die Deltas des Streams in einem Ledger und entscheidet mit dieser Zählung, ob der gespeicherte Stream alles enthält.

Nur Codex: Ein gekürztes Aggregat ersetzt nie einen längeren Stream
Nur Codex: Ein gekürztes Aggregat ersetzt nie einen längeren StreamGrößen im Maßstab für einen Codex-Befehl, der 3 MiB ausgegeben hat. Der Delta-Stream trug alle 3 MiB. Das aggregatedOutput von Codex behält 1 MiB: einen Anfang von 512 KiB, eine Marke, die 2.097.152 ausgelassene Bytes nennt, und ein Ende von 512 KiB. Bei item/completed folgen drei Ergebnisse. Wenn der Desktop alle 3 MiB im Stream gezählt hat, behält das Artefakt den Stream als Generation 1, und sourceIncomplete bleibt false. Wenn der Desktop nur 2,4 MiB gezählt hat, behält das Artefakt trotzdem den längeren Stream als Generation 1, und sourceIncomplete ist true. Wenn das Speichern des Streams fehlgeschlagen ist, wird das Aggregat zu Generation 2, und sourceIncomplete ist true.
Delta-Streamjedes Byte
alle 3 MiB, in Reihenfolge
AggregatCodex behält 1 MiB
Anfang
... 2,097,152 bytes omitted ...
Ende
Das Desktop-Artefakt nach item/completed
Stream bewiesenLedger zählt 3 MiB
Stream behalten
Generation 1, sourceIncomplete false
Stream längerLedger zählt 2,4 MiB
Stream behalten, 2,4 MiB
fehlt
Generation 1, sourceIncomplete true
Stream fehlerhaftAnhängen schlug fehl
Anfang
... 2,097,152 bytes omitted ...
Ende
Generation 2, sourceIncomplete true
0 MiB
1 MiB
2 MiB
3 MiB
  • Zwei Formen der KürzungAggregateTruncation

    Codex unified exec behält einen gleich großen Anfang und ein gleich großes Ende von zusammen 1 MiB und setzt „... N bytes omitted ...“ dazwischen. Codex classic exec schneidet das Aggregat bei 1 MiB ohne Marke ab. Der Desktop erkennt die zweite Form, wenn der Stream mehr Bytes geliefert hat, als das Aggregat enthält, mit 8 Bytes Spielraum pro Delta.

  • Stream-LedgerStreamedOutputLedger

    Der Desktop zählt die Bytes und die Deltas, die Codex für den Befehl gesendet hat. Der Stream ist als vollständig bewiesen, wenn die Zählung plus 8 Bytes die Summe aus Anfang, Auslassung und Ende erreicht. Ein Aggregat ohne Marke kann das nie beweisen.

  • Behalten oder ersetzensettle_truncated_snapshot_from_path

    Der Stream bleibt, wenn er als vollständig bewiesen ist oder wenn das Artefakt mehr Bytes enthält als das Aggregat. Das Aggregat ersetzt das Artefakt nur dann als nächste Generation, wenn der Stream unbewiesen und nicht länger ist oder wenn ein Anhängen fehlgeschlagen ist.

  • MarkierungsourceIncomplete

    True bedeutet, dass der Betrachter weniger zeigt, als der Befehl ausgegeben hat, oder dass der Desktop das Gegenteil nicht beweisen kann. Nur ein als vollständig bewiesener Stream lässt den Wert auf false.

Jedes Anhängen wird vorab protokolliert. Der Desktop fügt eine Zeile in codex_command_output_pending_appends ein, mit dem erwarteten Offset, der Länge, der Generation und einem SHA-256-Digest der Bytes. Danach schreibt er die Bytes in die Datei und bestätigt, was byte_length im Katalog weiterbewegt und die offene Zeile entfernt. Jedes spätere Anhängen, jeder Lesezugriff, jeder Abschluss und der Aufräumlauf beim Start führen zuerst dieselbe Wiederherstellung aus.

Die App stoppteDie Wieder­herstellung findetDie Wieder­herstellung tut
Nach der offenen Zeile, vor den BytesEine offene Zeile. Die Datei ist so lang, wie der Katalog angibt.Entfernt die offene Zeile. Das Delta ist verloren, und die Datei bleibt unverändert.
Mitten im SchreibenEine offene Zeile. Die Datei ist länger als der Katalog und kürzer als das offene Ende.Kürzt die Datei auf die Kataloglänge und entfernt die offene Zeile.
Nach den Bytes, vor der BestätigungEine offene Zeile. Die Datei endet am offenen Ende.Vergleicht den SHA-256-Digest des Endstücks. Bei Übereinstimmung wird die Datei synchronisiert und das Anhängen bestätigt. Bei einer Abweichung wird das Endstück abgeschnitten und ein Speicherfehler gemeldet.
Mit Bytes, die keine Zeile erklärtKeine offene Zeile. Die Datei ist länger als der Katalog.Kürzt die Datei auf die Kataloglänge.
Und die Datei hat Bytes verlorenDie Datei ist kürzer als der Katalog, oder sie fehlt.Meldet einen Fehler. Bei item/completed ersetzt das Aggregat das Artefakt als nächste Generation.

Nach einem fehlgeschlagenen Anhängen zeigt die Zeile „Command output is unavailable because this device could not store it.“, und der Desktop verwirft die späteren Deltas dieses Befehls. Bei item/completed übernimmt ein Befehl mit Aggregat das Aggregat als sein Artefakt. Ein Befehl ohne Aggregat behält diese Zeile, denn die unvollständige Datei darf nicht vollständig aussehen.

Das Löschen einer Session entfernt ihre Katalogzeilen in der Löschtransaktion und danach die Dateien. Beim Start entfernt der Desktop verwaiste Staging-Dateien. Nach dem Aufwärmen von Codex stellt er jedes offene Anhängen wieder her und räumt den Ordner auf: Eine Datei, die keine Katalogzeile nennt, wird nur entfernt, wenn sie älter als 1 Stunde ist, denn eine neuere Datei kann zu einem Befehl gehören, der noch läuft.

Claude-Befehlsausgabe bleibt im Transkript

Eine Claude-Session hat kein Desktop-Artefakt. Wenn ein Bash-tool_result eintrifft, fügt der Desktop eine Ausgabezeile hinzu, die einen Protocol-Zeiger auf das gespeicherte Ergebnis trägt und keine Bytes. Der Exit-Code ist 0, wenn das Ergebnis kein Fehler ist. Bei einem fehlgeschlagenen Befehl liest der Desktop ihn aus der ersten Zeile des Ergebnisses, die Claude als Exit code N schreibt.

Die Ausgabe eines Claude-Befehls hat eine Kopie, im Transkript, und jeder Lesezugriff lädt dieses Transkript ganz
Die Ausgabe eines Claude-Befehls hat eine Kopie, im Transkript, und jeder Lesezugriff lädt dieses Transkript ganzEin Claude-Bash-Befehl im Zeitverlauf. Solange der Befehl läuft, enthält die Timeline nur die Aufrufzeile. Wenn das tool_result eintrifft, speichert Claude Code das ganze Ergebnis in seinem Transkript, und die Timeline erhält eine Ausgabezeile, die einen Protocol-Zeiger und keine Bytes enthält. Der Betrachter öffnet sich später. Für jedes Bereichslesen startet der Desktop einen neuen Agent-Host, der Host liest das ganze Transkript über das SDK und endet, und der Desktop gibt einen Ausschnitt von höchstens 256 KiB zurück. Eine Ausgabe von 3 MiB braucht mindestens 12 solche Lesezugriffe.
Timeline-Zeilekeine Ausgabe-Bytes
Claude Codeführt Bash aus
Transkriptgehört Claude Code
nur Aufrufzeile
Ausgabezeile mit Protocol-Zeiger, keine Bytes
Befehl läuft
ganzes Ergebnis gespeichert: 3 MiB
tool_result
Agent-HosttoolOutput
Betrachter
geschlossen, kein Lesen
ein neuer Host-Prozess für jedes Lesen
lädt das ganze Transkript
Bytes 0 bis 262.143
lädt alles noch einmal
Bytes 262.144 bis 524.287
Bash startet
Ergebnis trifft ein
erstes Lesen
nächstes Lesen
Ein Codex-Befehl hat zusätzlich eine Desktop-Artefaktdatei. Ein Claude-Befehl hat keine. Das Transkript ist die einzige Kopie, und jeder Ausschnitt von 256 KiB kostet ein vollständiges Laden des Transkripts.
  • AusgabezeilecommandOutput.protocolOutput

    Der Zeiger nennt das Transkript in threadId (die Claude-Session-ID oder die Subagenten-ID), die Benutzernachricht, die das Ergebnis enthält, in turnId und die tool_use_id in itemId. updatedAtOrdinal ist 1, byteLength ist die Länge des Ergebnistexts, und capturedComplete ist true. Die Live-Zeile und die gespeicherte Zeile tragen denselben Zeiger.

  • Lesenrun.chatCommandOutputRead → toolOutput

    Der Desktop startet einen Host-Prozess für diese eine Anfrage. Der Host lädt jede Nachricht der Unterhaltung oder des Subagenten mit getSessionMessages oder getSubagentMessages, gibt das erste tool_result mit dieser tool_use_id zurück und endet.

  • AusschnittMAX_COMMAND_OUTPUT_RANGE_BYTES

    Der Desktop schneidet den angefragten Bereich aus dem ganzen Ergebnistext. Eine Anfrage verlangt 1 Byte bis 256 KiB, availableBytes ist die volle Länge, und complete ist immer true. Die Betrachter auf den Telefonen fragen aufeinanderfolgende Bereiche an, wie gezeichnet. Der Betrachter auf dem Desktop fragt überlappende Seiten an und schneidet sie an Zeilenenden.

  • Keine Desktop-Kopiecodex_command_outputs

    Nur ein Codex-Run schreibt ein Desktop-Artefakt. Bei Claude gelangt kein Ausgabe-Byte in appdata.db oder in den Artefaktordner. Ein Ergebnis, das das Transkript nicht mehr enthält, wird mit „This command output is not in the saved Claude conversation.“ beantwortet.

Der Lesezugriff nutzt dieselbe Methode wie bei Codex, run.chatCommandOutputRead mit einer Protocol-Quelle, und dieselbe Grenze von 256 KiB pro Antwort. Die Kosten unterscheiden sich. Jeder Aufruf startet einen einmaligen Agent-Host im Claude-Hauptordner, sendet toolOutput und wartet, bis der Host endet. Der Host lädt alle Nachrichten der Unterhaltung, oder des Subagenten, wenn der Zeiger einen nennt, und gibt das erste tool_result mit der tool_use_id zurück. Danach schneidet der Desktop den Text zu. Ein Ergebnis, das kein reiner Text ist, wird zuerst zu Text: Ein Textblock behält seinen Text, ein tool_reference-Block wird zum Tool-Namen, und jeder andere Block wird zu seinem Typ in eckigen Klammern.

Nur Bash erhält eine Ausgabezeile. Jedes andere Claude-Tool hat eine Zeile: die Aufrufzeile, die an Ort und Stelle mit dem Ergebnistext abgeschlossen wird. Bei beiden Agenten dekodiert die Detailansicht einer solchen Tool-Zeile das Ergebnis mit decode_tool_output_container. Die Funktion packt JSON-Hüllen bis zu einer Tiefe von 6 aus und behandelt ein verschachteltes Objekt nur dann als Befehlstransport, wenn es Transportfelder wie stdout, stderr oder wall_time_seconds hat.

FrageCodexClaude
Bytes, während der Befehl läuftDesktop-Artefaktdatei, pro Delta angehängtKeine. Die Ausgabe­zeile erscheint mit dem Ergebnis.
Bytes nach dem BefehlDie Mitschnittdatei von Codex, gelesen über den App-ServerDas tool_result in Claudes Transkript
Quelle der ZeileDesktop-Artefakt im Live-Betrieb, danach Zeiger auf CodexZeiger auf das Transkript, live und ge­speichert
Kosten eines Bereichs­lesensEin Dateibereich oder eine App-Server-AnfrageEin Host-Start und ein voll­ständiges Laden des Tran­skripts
Kann unvoll­ständig seinJa, wenn der Desktop oder Codex weniger behalten hat, als der Befehl ausgegeben hatNein, das Ergebnis ist ganz ge­speichert

HTML-Dokumente in einer Sandbox

Jede HTML-Vorschau ist eine eigene Website, und die Ressourcenwurzel ist ihr oberster Ordner
Jede HTML-Vorschau ist eine eigene Website, und die Ressourcenwurzel ist ihr oberster OrdnerLinks der Datenträger des Desktops, rechts die Anfragen einer Vorschauseite unter /docs/report.html. Jede Anfrage landet auf demselben Pfad unter der Ressourcenwurzel, daher laden relative Importe und fetch-Aufrufe, ein Pfad kann nicht über die Wurzel steigen, ein Symlink, der hinausführt, wird abgewiesen, und eine versteckte Datei unter der Wurzel wie .env wird ebenfalls abgewiesen. Darunter gibt die Sandbox der Seite keinen Zugriff auf die App, und eine Navigationsnachricht ist das Einzige, worauf die App reagiert.
Sandbox
kein Zugriff auf Seite oder Speicher der App
hbcode.html.open
Die Appöffnet eine Datei unter der Wurzel oder eine Webseite
Desktop-Datenträger
~/Pictures/logo.png
~/.ssh/id_ed25519
~/work/shop
Ressourcenwurzel
docs/report.html
src/chart.js
data/sales.json
assets → ~/Pictures
.ssh/id_ed25519
.env
verlässt die Wurzel
fehlt, 404
versteckt, 404
Vorschauseite
ptc-document://<preview-id>.localhost
keine URL reicht über die Wurzel
/
/docs/report.html
die Seite selbst
/src/chart.js
import "../src/chart.js"
/data/sales.json
fetch("../data/sales.json")
/assets/logo.png
<img src="../assets/logo.png">
/.ssh/id_ed25519
fetch("../../../.ssh/id_ed25519")
/.env
fetch("../.env")
  • Ressourcenwurzelopen_html_preview_command

    Der Projektordner, wenn er das Dokument enthält, sonst der eigene Ordner des Dokuments. Eine Dateisystemwurzel, der Home-Ordner und ein übergeordneter Ordner des Home-Ordners dienen nie als gemeinsame Wurzel: Ein Dokument, das direkt in einem solchen Ordner liegt, kann nur sich selbst lesen. Der Aufrufer erzeugt die Vorschau-UUID, und der Desktop weigert sich, diese ID an ein zweites Dokument zu binden.

  • Pfadprüfungptc-document://<preview-id>.localhost/<path>

    Der Handler weist einen dekodierten Pfad mit .., einem Backslash, einem Doppelpunkt oder NUL ab, liefert für einen Ordner index.html und antwortet mit 404, wenn der kanonische Pfad fehlt oder die Wurzel verlässt. Er antwortet auch mit 404 für eine Datei oder einen Ordner, deren Name mit einem Punkt beginnt, außer in den versteckten Ordnern, die das Dokument enthalten.

  • Sandboxsandbox allow-scripts

    Skripte, Module und fetch laufen in einem opaken Ursprung ohne Zugriff auf die Seite oder den Speicher der App. Eine Nachricht hbcode.html.open oder hbcode.html.ready aus diesem Frame ist das Einzige, worauf die App reagiert, und nur für eine Datei unter der Wurzel oder eine http(s)-Seite.

  • Telefonefiles.readHtmlPreviewResource

    Die iPhone-App unter ptc-document://<preview-id>.localhost und die Android-App unter https://ptc-<preview-id>.invalid lösen dieselben Pfade über den Desktop auf, in geprüften Blöcken von bis zu 4 MiB und ohne Skriptbrücke in die App.

Das Protokoll antwortet auf OPTIONS mit 204, bedient GET und HEAD, beantwortet jede andere Methode mit 405 und setzt Cache-Control no-store und X-Content-Type-Options nosniff. Jeder abgewiesene oder fehlende Pfad wird mit 404 beantwortet. Die Datei auf dem Datenträger bleibt unverändert, und der Desktop ändert jede HTML-Antwort an zwei Stellen. Er fügt am Ende des head ein style-Element mit der ID hb-theme ein, das der Seite das App-Theme als benutzerdefinierte Eigenschaften --hb-* gibt. Ein Dokument ohne head-Element oder eines, das kein UTF-8 ist, erhält kein Theme. Danach hängt er navigation.js nach dem Dokumentende an. Dieses Skript sendet hbcode.html.open an den Elternteil und blockiert jedes Schema außer ptc-document und http(s). Lokale Links in einem Dokument gehen in den Vorschauverlauf ein, Weblinks öffnen sich in der Webvorschau, und Neu laden oder eine Dateiänderung aktualisiert die Darstellung.

Der Lesebereich ist kleiner als die Ressourcenwurzel. Eine Datei oder ein Ordner, deren Name mit einem Punkt beginnt, etwa .env, .git oder .ssh, wird abgewiesen. Die versteckten Ordner, die das Dokument enthalten, sind die Ausnahme: Eine Website, die nach .vitepress/dist gebaut wurde, liest weiterhin ihre eigenen Dateien. Ein Projektordner, der die Dateisystemwurzel, der Home-Ordner oder ein übergeordneter Ordner des Home-Ordners ist, wird nie zur Wurzel. Die Wurzel ist dann der eigene Ordner des Dokuments, und wenn auch dieser Ordner einer von diesen ist, liest das Dokument nur sich selbst.

Webseiten als Markdown

Ein Weblink öffnet sich als Markdown-Darstellung statt als Live-Seite. Die WebView extrahiert den Artikelinhalt und wandelt ihn mit einer GFM-fähigen Turndown-Pipeline um, die Rust-Seite wandelt mit quick_html2md für Inhalte um, die die WebView nie erreichen, und die Browser Bridge hat einen dritten, handgeschriebenen DOM-zu-Markdown-Renderer, dessen Ausgabe der Desktop als capturedBrowserMarkdown speichert und mit derselben Titelkopfzeile umschließt. Drei Konverter, ein Zielformat.

Dateizugriffe und Übertragungen

files.readContent liefert ein Textdokument von höchstens 2 MiB. Eine größere Datei scheitert mit „Text preview is too large“. Die Anfrage trägt projectDirectory, path sowie optional encoding und allowExternalFile, und der Desktop akzeptiert encoding und ignoriert es. Die Anfrage hat keine Block-Offset- oder Medienfelder, weil Text- und Binäranfragen getrennt bleiben. files.readBinary und files.readMediaRendition lesen sequenzielle Blöcke ab Offset null. Jede Antwort trägt offset, nextOffset (null am Dateiende), dataBase64, byteCount, contentVersion, modifiedAt und mimeType, und Renditionen ergänzen originalByteCount. Benachbarte Grenzen: Medienrenditionsquellen bis 1 GiB, Stream-Transkodierungen bis 256 MiB mit 40-Sekunden-Timeouts, Medienbereichslesezugriffe von 1 MiB und Chat-Anhang-Uploads in 1-MiB-Blöcken, höchstens 2.048 davon.

Eine Datei jeder Größe wird in unabhängigen Lesezugriffen von je 4 MiB übertragen, gebunden an eine Version
Eine Datei jeder Größe wird in unabhängigen Lesezugriffen von je 4 MiB übertragen, gebunden an eine VersionEine maßstabsgetreu gezeichnete Datei mit 9.961.472 Bytes wird in drei Anfragen an den Offsets 0, 4.194.304 und 8.388.608 gelesen. Der Desktop öffnet die Datei für jede Anfrage und behält dazwischen nichts, während das Telefon Version und Größe aus der ersten Antwort festhält. Wird die Datei während der Übertragung gespeichert, trägt die nächste Antwort eine neue Version, und das Telefon verwirft den ganzen Lesevorgang.
report.pdf9.961.472 Bytes
4 MiB
4 MiB
1,5 MiB
0
4.194.304
8.388.608
Desktopöffnet, liest, antwortet
behält zwischen Anfragen nichts
TelefonDatei unverändert
hält Version A und 9.961.472 Bytes fest
wieder Version A
nextOffset null
Telefonmittendrin gespeichert
Version A
Datei gespeichert
Version B
File changed while loading. Open it again.
  • Blocklesenfiles.readBinary

    Jede Anfrage nennt den Pfad und einen Offset. Der Desktop öffnet die Datei, liest dort bis zu 4 MiB und antwortet mit dem nächsten Offset, dem gesamten byteCount und einer contentVersion. Ressourcen der HTML-Vorschau und Medienrenditionen nutzen denselben Leser.

  • Festgehaltene VersioncontentVersion

    Bei files.readBinary ist sie ein Hash aus Pfad, Größe und Änderungszeit, gebildet bei jedem Öffnen der Datei. Beide Telefone behalten Version und Größe der ersten Antwort und verwerfen den ganzen Lesevorgang, wenn eine spätere Antwort abweicht. Eine Datei, die unter den Offset geschrumpft ist, erhält dieselbe Meldung vom Desktop.

  • Relay-FrameDEVICE_LINK_MAX_FRAME_BYTES

    Ein Block von 4 MiB ergibt etwa 5,3 MiB base64, daher bleibt jede Antwort weit unter der Frame-Grenze des Relays von 32 MiB, und die Datei selbst hat keine Größengrenze.

Syntaxhervorhebung

Quellvorschauen auf dem Desktop nutzen Shiki-Grammatiken, und jede Telefon-App hebt mit ihrer eigenen Engine hervor.