Zum Hauptinhalt springen

Protokollreferenz

Diese Seite behandelt Leitungsverhalten und Befehlsroutinggarantien. Wenn Sie Produktworkflows implementieren, beginnen Sie zuerst mit Architektur und der Controller-Implementierungsanleitung, und verwenden Sie dann diese Seite als strikte Vertragsreferenz.

Aktuelle Protokolltypen sind in packages/shared-protocol/src/index.ts definiert.

Wahrheitsquelle Codepfade

AnliegenQuelle
Geteilte Hüllen- und Payload-Verträgepackages/shared-protocol/src/index.ts
Relay-Protokollbehandlung und Routingpackages/relay/src/index.ts
Controller-Hüllenerzeugungpackages/cli/src/index.ts

Nachrichtenfluss

Hüllenvertrag

Jeder WebSocket-Frame verwendet eine Hüllenform für stabile cross-component-Korrelation.

FeldBeschreibung
protocolVersionDerzeit 1.0
messageTypeFrame-Familie: hello, auth, command, result, event usw.
requestIdPrimärer Korrelationsschlüssel über Controller, Relay und Node
timestampISO-8601; durchgesetzt gegen Replay-Abweichungsfenster
senderRolecontroller, relay oder node
payloadNachrichtenspezifisches Objekt

Nachrichtenfamilien

FamilieZweck
hello / hello_ackRollen- und Fähigkeitsverhandlung
auth / auth_ackZugriffstoken-Authentifizierung
refresh / refresh_ackZugriffstoken-Erneuerung
commandController-gesteuerte Aktionen
result / errorTerminalergebnisse
eventFortschritt und Listener-Updates
ping / pongSitzungsaktivität
tab_lock / tab_unlockSperrlebenszyklussignale
command_cancelExplizite Stream- oder Befehlsabbruch

Listener-Lebenszyklus

listener.subscribe und listener.unsubscribe geben jeweils normale Terminalergebnisse zurück (result oder error). Streaming-Daten werden später als event-Frames geliefert, die mit der ursprünglichen Subscribe-requestId verbunden sind.

AktionErforderliches PayloadTerminalverhalten
listener.subscribelistener, optionale optionsSofortiges result oder error
listener.unsubscribetargetRequestIdSofortiges result oder error

Nach erfolgreichem Unsubscribe werden weitere Updates für diese Subscribe-requestId mit listener_not_found abgelehnt.

network.http_intercept Optionen

OptionErforderlichBeschreibung
tabSessionIdJaMuss auf eine aktive verwaltete Sitzung auflösen
siteJaNormalisiert zu Kleinbuchstaben; wird gegen Tab-URL validiert
urlPatternsNeinGlob-Filter
requestHostAllowlistNeinExplizite cross-host-Erlaubnisliste
modeNeinnetwork, fetch oder hybrid (Standard network)
includeBodyNeinStandard true
includeHeadersNeinStandard false; sensible Header werden geschwärzt
maxBodyBytesNeinStandard 256000; nur positive numerische Werte
mimeTypesNeinMIME-Präfix-Erlaubnisliste
streamAdapterNeinBefehlseigener Adapterhinweis
selfUserIdNeinBefehlseigener Kontextwert

Listener-Update-Form

Listener-Updates sind messageType=event-Frames mit payload.type=listener_update und requestId gleich der ursprünglichen Subscribe-Anfrage. payload.data trägt entweder rohe Transport-Payloads oder befehlseigene Shared-Domain-Objekte.

Shared-Objekt-Diskriminatoren: chat.message, chat.typing, chat.participant, chat.message_deleted, content.article, content.post, content.post_comment.

Befehlsvertrag

Jede command-Payload muss einen Ziel-Node identifizieren und Replay-Schutzfelder enthalten.

FeldErforderlichBeschreibung
targetNodeIdJaErforderlich durch Protokollinvariante
tabSessionIdBedingtErforderlich für tab-bereichsspezifische Aktionen
actionJaAktions-ID inklusive Befehls- und Listener-Aktionen
payloadJaAktionsspezifische Daten
timeoutMsNeinRelay-Timeout-Budget
waitPolicyNeinfail_fast oder wait_with_timeout
idempotencyKeyNeinReplay-Dedupe-Schlüssel zur Laufzeit
replayNonceJaErforderlich für Annahme

Befehlsaktionen

AktionBeschreibung
command.listSeitenbefehlsmetadaten bewerben
command.runBefehlslogik ausführen
command.testTest-Hook ausführen; greift auf execute zurück, wenn keiner deklariert ist
command.reddit_postsLegacy-Alias für command.run mit site=reddit.com, command=getPosts
primitive.tab.openVerwalteten Tab öffnen
primitive.tab.closeVerwalteten Tab schließen
primitive.tab.navigateVerwalteten Tab navigieren
primitive.tab.queryVerwalteten Tab-Zustand abfragen
primitive.dom.extract_textSichtbaren Text aus Tab extrahieren
primitive.dom.extract_htmlSeiten-HTML extrahieren
primitive.dom.extract_clean_htmlDOM mit semantischen Attributen extrahieren, Skripte/Styles entfernt
primitive.dom.extract_distilled_htmlDestilliertes HTML extrahieren (Lesbarkeit)
primitive.dom.extract_markdownMarkdown-Darstellung extrahieren
primitive.page.screenshotScreenshot des Tabs oder einer URL

command.list Deskriptormetadaten

command.list gibt Befehlsdeskriptoren zurück, die Befehlsmetadaten enthalten, die von Controllern für Validierung, Preload-Verhalten und Timeout-Planung verwendet werden.

FeldErforderlichBeschreibung
siteJaSeitenbereich, für den der Befehl gültig ist
idJaBefehls-ID innerhalb des Seitenbereichs
displayNameJaMenschlich lesbarer Befehlsname
descriptionJaBefehlszusammenfassung
requiresAuthNeinGibt an, dass eine manuelle Anmeldeübergabe erforderlich sein kann
preloadHostNeinBevorzugter URL-Host für Auto-Open-Workflows
inputFieldsNeinEingabeschema für Befehlseingabevalidierung
timeoutPolicyNeinTimeout-Hinweise für Controller

Wenn angegeben, unterstützt timeoutPolicy sowohl feste als auch eingabeskalier Timeout-Hinweise:

timeoutPolicy FeldErforderlichBeschreibung
defaultMsNeinVorgeschlagenes Standard-Timeout für diesen Befehl
scaling.inputFieldNeinEingabefeldname für die Skalierung
scaling.baseMsNeinBasistimeout-Budget vor Skalierung
scaling.perUnitMsNeinZusätzliches Timeout-Budget pro Eingabeeinheit
scaling.minMsNeinUntere Klemme für aufgelöstes Timeout
scaling.maxMsNeinObere Klemme für aufgelöstes Timeout

Controller können diese Metadaten verwenden, um effektive Timeout-Budgets zu berechnen, während explizite benutzerdefinierte Timeout-Overrides beibehalten werden.

Inhaltsextraktion wird auch über erstklassige Controllerschnittstellen bereitgestellt:

  • CLI: otto extract-content [url] --format markdown|distilled_html|clean_html|raw_html|text (Standard ist Markdown)
  • MCP: otto_extract_content-Tool mit format-Auswahl und gemeinsamer Zielsetzung (url oder tabSession)

Diese Schnittstellen ordnen die obigen primitiven DOM-Aktionen zu und bieten eine konsolidierte Oberfläche für Agenten und CLI-Benutzer.

command.test kann ein stream-Manifest in result.payload.data zurückgeben. Controller sollten Folge-Subscribe-Verkehr auf demselben authentifizierten WebSocket beibehalten, Heartbeat (ping/pong) für lange Sitzungen aufrechterhalten und command_cancel gegen die ursprüngliche Test-requestId verwenden, wenn aktive Stream-Tests beendet werden.

Routing, Warteschlangen und Zuverlässigkeit

  • Relay routet jeden Befehl an genau eine Node-Sitzung und verfolgt requestId-Eigentum, sodass Ergebnisse immer an den ursprünglichen Controller zurückkehren.
  • Gleiche Tab-Arbeit (targetNodeId:tabSessionId) ist FIFO; cross-Tab-Arbeit ist parallel.
  • Warteschlangentiefenlimits werden pro Tab und pro Controller durchgesetzt.
  • Befehle, die unter wait_with_timeout warten, können als queue_wait_timed_out beendet werden.
  • Timeout-Fenster erzeugen Terminal-Timeout-Ergebnisse; Node-Trennungen erzeugen node_disconnected; Sperrkonflikte erzeugen lock_conflict.
  • Replay-Nonces und Zeitstempel-Abweichungsfenster werden am Eingang durchgesetzt.
  • Controller-Trennungsaufräumung bereinigt besitzte wartende Arbeit und löst eigentumsbereichsbezogene Tab-Bereinigung aus.

Tab-Eigentum und Bereinigung

  • Relay injiziert interne Tab-Eigentumsmetadaten beim Weiterleiten von Controller-erstellten Tab-Open-Befehlen.
  • Node speichert Eigentum nach tabSessionId.
  • Bei Controller-Trennung oder Heartbeat-Timeout schickt Relay primitive.tab.close_owned, um nur Tabs zu schließen, die dieser Controller-Identität gehören.
  • Sperrschlüssel sind targetNodeId:tabSessionId; nur ein Controller kann zu einer Zeit eine Sperre halten.
  • Leasing-Ablauf gibt Sperren automatisch frei. Sperrereignisse enthalten Leasing-Metadaten (lockOwnerControllerId, lockLeaseMs, lockExpiresAt) für Beobachtbarkeit.

Versionierung

Aktuelle Version: 1.0. additive Änderungen werden bevorzugt; Breaking Changes erfordern eine neue Hauptversion.

command.reddit_posts-Alias wird während der Migration zu command.run beibehalten.

Nächste Schritte