Zum Inhalt springen
BeeuniBeeuni
Deutsch
Esc
↑↓navigieren↵öffnen⌘Jvorschau
Auf dieser Seite

React-Hooks

Führe eine Beeuni-Sitzung in React mit dem useSession-Hook aus.

@beeuni/sdk/react ergänzt das SDK um React-Hooks. Diese Seite behandelt useSession, den Hook, der eine Sitzung von Anfang bis Ende ausführt, sowie die anderen Hooks, die für React-Apps als stabil bestätigt sind.

useSession(projectId, sessionId, options?)

useSession startet die Sitzung, öffnet den vom Server ausgewählten Ereignistransport und synchronisiert Nachrichten, Status und ausstehende Prompts. Rufe ihn einmal pro Sitzungsansicht auf.

import { useSession } from '@beeuni/sdk/react';

function Chat({ projectId, sessionId }: { projectId: string; sessionId: string }) {
  const s = useSession(projectId, sessionId);

  if (s.phase !== 'ready') return <Booting stage={s.stage} onRetry={s.retry} />;

  return (
    <>
      {s.messages.map(({ info, parts }) => (
        <Message key={info.id} info={info} parts={parts} />
      ))}
      <Composer busy={s.isBusy} onSend={s.send} onStop={s.cancel} />
    </>
  );
}

Für die Bereitschaft ist der Server maßgeblich. Die Laufzeit ist bereit, wenn POST /start stage: 'ready' zurückgibt. useSession führt keine separate clientseitige Zustandsprüfung durch.

Rückgabewerte

Feld Typ Inhalt
phase 'starting' | 'ready' | 'error' Gesamtzustand. Zeige einen Startbildschirm bis ready.
messages { info, parts }[] Die Nachrichtenliste. Teile werden live gestreamt.
savedTranscript 'loading' | 'shown' | 'none' Ob die gespeicherte Unterhaltung angezeigt werden kann, bevor der Computer aufwacht. loading: Eine gespeicherte Kopie ist unterwegs. shown: Nachrichten sind in der Liste. none: Nichts kann angezeigt werden, bis die Laufzeit antwortet.
conversationEmpty boolean Die gespeicherte Kopie belegt, dass die Unterhaltung leer ist, seitdem kein Turn beendet wurde und nichts offen ist oder in der Warteschlange steht. Zeige das Eingabefeld statt eines Startbildschirms.
status SessionStatus Der Sitzungsstatus.
isBusy boolean Der Agent generiert eine Antwort.
questions, permissions array Ausstehende Agentenfragen und Anfragen zur Tool-Freigabe. Ein permission ist hier eine einzelne Tool-Freigabe der Laufzeit, keine IAM-Berechtigung.
diffs, todos array Live-Dateidiffs und To-do-Einträge.
sendError BeeuniSendError | null Der letzte send-Fehler: billing, runtime-not-ready oder runtime-error.
rewindMessageId string | null Die ausgewählte Benutzernachricht, während ein umkehrbares Zurücksetzen vorbereitet ist.
rewindPending boolean Eine Anfrage zum Zurücksetzen oder Wiederherstellen läuft.
rewindError BeeuniSendError | null Der letzte Fehler beim Zurücksetzen oder Wiederherstellen.
models, agents, defaultAgent, commands — Auswählbare Modelle, auswählbare Agenten, der Standardagent und Slash-Befehle. Verfügbar, bevor die Laufzeit startet.
retry () => void Erzwingt eine erneute Prüfung von /start.

Aktionen

Aktion Funktion
send(text, override?) Sendet einen Prompt. override setzt { model?, agent? } nur für diese Nachricht.
sendParts(parts, override?) Sendet Text und Laufzeit-URL-Dateiteile über den ausgewählten Transport. Private vorbereitete Handles verwenden die Prompt-Routen der Plattform.
rewind(messageId) Setzt diese kanonische Sitzung auf eine Benutzernachricht zurück. Die ausgewählte Nachricht und der spätere Verlauf werden ausgeblendet und bleiben wiederherstellbar.
restoreRewind() Stellt den entfernten Verlauf wieder her, bevor ein weiterer Prompt seinen Ersatz festschreibt.
cancel() Stoppt den aktuellen Lauf und entfernt ausstehende Fragen und Berechtigungen. Hält zuerst die Prompts in der Warteschlange der Sitzung zurück, damit ein wartender Prompt keinen neuen Lauf startet.
runCommand(command, args) Führt einen Slash-Befehl des Projekts aus.
answerQuestion(id, answers) Beantwortet eine ausstehende Agentenfrage.
rejectQuestion(id) Lehnt eine ausstehende Agentenfrage ab.
answerPermission(id, reply, message?) Beantwortet eine Anfrage zur Tool-Freigabe. reply ist 'once', 'always' oder 'reject'.

useSession gibt auch removeQuestion und removePermission zurück. Verwende sie nicht. Sie entfernen den Prompt aus dem lokalen Zustand, benachrichtigen aber nie den Agenten, sodass der Lauf blockiert bleibt. Verwende stattdessen answerQuestion, rejectQuestion oder answerPermission.

Optionen

Option Standard Funktion
waitMs 15000 Das an /start gesendete Long-Poll-Budget.
replayStartStash true Sendet einen Prompt erneut, der vor dem Anlegen der Sitzung gespeichert wurde, sobald die Sitzung bereit ist.
enabled true Setze false, um den Hook zu verzögern, etwa bis eine Abrechnungsprüfung erfolgreich ist.
chatEngine true Setze false, wenn deine App eine eigene Chat-Oberfläche für diese Sitzung einbindet, um Nachrichten nicht doppelt zu synchronisieren.
initialRuntimeSessionId null Ein Laufzeitsitzungs-Pin, den dein Server bereits für diese Sitzung hält. Das Transkript wird daraus angezeigt, während /start läuft; die Antwort von /start bleibt maßgeblich. initialOpenCodeSessionId ist der veraltete Name dafür.
browserPresence false Hält die Präsenz-Lease dieses Tabs, während eine angemeldete Person die Seite nutzt (Eingabe in den letzten 10 Minuten). Die Lease hält den Computer der Sitzung wach.
presenceAlerts false Dieser Tab zeigt eigene Benachrichtigungen an. Wird über die Präsenz-Lease gesendet: Der Server überspringt Telefon und Web Push nur, während ein benachrichtigender Tab genutzt wird. Eine Änderung wird sofort gesendet. Übergib true nur, wenn das Flag notification_center des Projekts aktiviert ist; andernfalls ignoriert der Server es. Benötigt browserPresence.
presencePageExit false Beendet die Präsenz-Lease, wenn die Seite geschlossen wird oder in den Zurück-/Vorwärts-Cache wechselt, damit ein Turn, der direkt nach dem Schließen des Tabs endet, weiterhin eine Benachrichtigung auslöst. Aktiviert: pagehide meldet Abwesenheit, und jede Abwesenheitsmeldung wird mit keepalive gesendet, sodass sie die Seite überdauert. Deaktiviert: keine pagehide-Meldung und kein keepalive. Ein sich schließender Tab wird weiterhin ausgeblendet und meldet Abwesenheit, aber der Browser kann diese Anfrage beim Entladen der Seite abbrechen; die Lease bleibt dann bis zu ihrem Ablauf nach 90 s bestehen. Übergib das Flag notification_center des Projekts. Eine Änderung gilt sofort, ohne neue Präsenzmeldung. Benötigt browserPresence.
repositoryMode — Nur Telemetrie. Eine Sitzung, die vor einem Repository-Austausch erstellt wurde, startet und läuft auch ohne diese Option mit der aktuellen Projektkonfiguration. Nur ihr /workspace-Klon stammt noch aus dem alten Repository, daher erfordert ein Push daraus zuerst einen Rebase.

Das Senden erfolgt optimistisch. send zeigt deine Nachricht sofort an; anschließend ergänzen Stream- Ereignisse die Antwort des Agenten.

rewind(messageId) erstellt niemals eine Sitzung. Es verwendet die kanonische Sitzung aus POST /start. Die Laufzeit stellt den Dateizustand wieder her und hält den entfernten Transkriptverlauf wiederherstellbar. Der nächste akzeptierte Prompt schreibt den Ersatzverlauf fest.

Weitere stabile Hooks

@beeuni/sdk/react exportiert außerdem React Query-Hooks für Daten, die keine laufende Sitzung benötigen. Jeder entspricht einer Methode des Clients und benötigt keinen Provider.

Hook Liest
useProjectModels(projectId) Auswählbare Modelle für das Projekt.
useProjectModelPickerCatalog(projectId) Den rohen /model-picker-Datensatz pro Wire-Modell (reasoning_options, temperature, limit) und managedPricingRoutes-Kundenpreisschätzungen für jede geeignete verwaltete Route. Die bedienende Route bestimmt die endgültige Credit-Abbuchung.
useProjectSessions(projectId, { parent, startedBy, q, limit }) Die Sitzungen eines Projekts, seitenweise. parent: 'root' gibt Sitzungen der obersten Ebene mit child_count zurück; startedBy: 'me' | 'others' | 'automated' filtert danach, wer den Lauf gestartet hat; q durchsucht jede Sitzung, die der Betrachter öffnen darf, nicht nur geladene Seiten. Jeder Filtersatz hat seinen eigenen Cache-Eintrag.
useSessionChildren(projectId, parentSessionId, { q, limit, enabled }) Die Sitzungen, die eine übergeordnete Sitzung erzeugt hat (parent=<id>), neueste zuerst, seitenweise. Setze enabled: false, bis die übergeordnete Sitzung geöffnet wird.
useVisibleAgents({ projectId }) Die sichtbaren Agenten des Projekts.
useProjectConfig(projectId) Die Laufzeitkonfiguration des Projekts: Standardagent, Befehle.
useProjectSecrets(projectId) Secrets: auflisten, hinzufügen, entfernen und persönliche Überschreibungen.
useAccountSecretResources(accountId) Metadaten zu Anbieter-Secrets des Kontos und Nutzungsfreigaben. Werte werden nie zurückgegeben.
useSessionProviderSecretPools(projectId, sessionId) Konfigurierte Pools, einschließlich leerer Auswahlen; setPool aktualisiert einen Anbieter und frischt den Sitzungscache auf.
useProjectTriggers(projectId) Trigger: auflisten, erstellen, aktualisieren, entfernen, auslösen.
useProjectTriggerEventTypes(projectId, connector) Die App-Ereignisse, auf die ein Connector reagieren kann. Inaktiv, bis connector gesetzt ist.
useChangeRequests(projectId, status?) Änderungsanfragen: auflisten, öffnen, zusammenführen, schließen, Änderungen anfordern.
useRuntimeSupports(capability) Ob die Laufzeit der geöffneten Sitzung eine Funktion bereitstellt (session.rewind, session.compact, …), anhand der /beeuni/health-Antworten, die der Poller für die Laufzeit-Wiederverbindung liest. true bis zur ersten Antwort. Siehe Was die Laufzeit unterstützt.
useNotificationInbox({ userId, limit?, enabled? }) Die neueste Posteingangsseite des Aufrufers (limit standardmäßig 20), unreadCount sowie markRead(ids), markAllRead(), markSessionRead(sessionId). Fragt alle 60 s ab, solange die Seite sichtbar ist, und ruft bei Fokus erneut ab. Ein Schreibvorgang ändert den Cache sofort, stellt ihn bei einem Fehler wieder her und ruft dann jeden Posteingangseintrag erneut ab. Keine Anfrage ohne userId.
useNotificationPreferences({ userId, enabled? }) Die Push- und E-Mail-Auswahl des Aufrufers pro Art, email_available und update(patch) (optimistisch).
useSessionWatch({ userId, projectId, sessionId, enabled? }) { watching } für eine Sitzung und setWatching(watching) (optimistisch), um sie stummzuschalten oder zu verfolgen.
resetRuntimeQueries(queryClient) Kein Hook. Entfernt jede zwischengespeicherte Laufzeitabfrage (Sitzungen, Nachrichten, Agenten, Befehle, Diffs). Rufe ihn auf, nachdem die Laufzeit der Sitzung durch einen Neustart oder ein Neuladen der Konfiguration ersetzt wurde, damit der nächste Lesevorgang aus der neuen Laufzeit erfolgt.

Die drei Benachrichtigungs-Hooks verwenden userId (qk.notifications) als Cache-Schlüssel, sodass ein Benutzerwechsel im selben Tab nie den Posteingang des vorherigen Benutzers zeigt. Übergib die ID des angemeldeten Benutzers.

Benachrichtigungen werden durch das projektspezifische notification_center Feature-Flag gesteuert, das standardmäßig deaktiviert ist. Aktiviere jeden Hook nur mit enabled: useFeatureFlag(projectId, 'notification_center').enabled, damit ein Projekt mit deaktiviertem Flag keine Benachrichtigungsanfrage sendet.

Ein Agent kann einen 1-Klick-Verbindungslink erzeugen (/connect/<token>). Die Daten und Laufzeitrichtlinien des Ablaufs liegen im SDK; ein Host rendert darauf seinen eigenen Dialog und injiziert seine Adapter.

Export Rolle
useConnectorSetup(token, options) Der gesamte Ablauf: laden, was der Link benennt, POST /start, die gehostete Seite des Anbieters über das injizierte openPopup öffnen, POST /finalize nach dem Zeitplan 3 s / 5 s / 5 Minuten abfragen und phase (loading, ready, starting, opened, connected, error), die App-Informationen, den Fehler und die Identität melden, als die das Konto autorisiert wurde. options enthält backendUrl, den storage-Adapter und openPopup des Hosts; onOpened wird nach jedem Öffnen eines Popups ausgelöst.
useConnectorLinkInfo(token, options) Ein gemeinsamer, speichergestützter Cache pro Link-Token, sodass alle Karten und das Modal einen einzigen GET-Aufruf der ratenbegrenzten öffentlichen Route teilen und das App-Logo im ersten Frame anzeigen. Dieselben backendUrl/storage-Optionen.
createConnectorLinkInfoCache(fetchInfo, { storage }) Die Cache-Factory selbst (frameworkunabhängig, Speicher injiziert) für einen Host, der eine eigene Instanz möchte.
resolveConnectorStart({ start, finalize }) Die /start-Ergebnisregel: gehostete URL → Popup, bereits verbunden → einmal abschließen, andernfalls die Fehlermeldung.
nextConnectorPollDelay(attempt, elapsedMs) Der begrenzte Abfragezeitplan (zuerst 3 s, danach 5 s, endet nach 5 Minuten).

Connector-Daten

useConnectorQuery(projectId, slug, action, args, { account, enabled, staleTime }) liest die Ausgabe einer Connector-Aktion als zwischengespeicherte Abfrage. error ist ein ConnectorCallError: Rendere eine Verbindungsschaltfläche aus error.connectUrl oder eine Kontoauswahl aus error.availableAccounts. Verwende ihn nur für eine Aktion, die liest; jeder Abruf führt die Aktion aus und schreibt ein Audit-Ereignis. Die Ausgabe bleibt 30 s aktuell, bei Fokus wird nie erneut abgerufen, und nur ein vorgelagertes 429 oder 503 wird wiederholt. Siehe Connectors aus dem Code.

Den Lesevorgang zum Öffnen früh starten

prefetchSessionOpen(queryClient, projectId, sessionId) startet den Lesevorgang zum Öffnen der Sitzung, bevor die Sitzungsansicht eingebunden wird. Er sendet eine GET .../snapshot-Anfrage (Sitzungsdatensatz, Turn, Warteschlange und die ersten 40 Transkriptnachrichten) und befüllt daraus den Cache für den Sitzungsdatensatz. useSession nutzt dann diese Anfrage, statt eine eigene zu starten.

Rufe ihn auf, wenn eine Route eine Sitzung benennt, oder bei Hover, Fokus oder Berührung eines Sitzungslinks. Er liest nur: Er ruft nie /start auf und weckt nie einen Computer. Er wird nie abgelehnt. Ein erneuter Aufruf für dieselbe Sitzung innerhalb von 30 Sekunden sendet keine Anfrage.

import { prefetchSessionOpen } from '@beeuni/sdk/react';

<a
  href={`/projects/${projectId}/sessions/${sessionId}`}
  onFocus={() => void prefetchSessionOpen(queryClient, projectId, sessionId)}
/>;

Bei einem Neuladen aus dem Cache rendern

Zwei Speicher bewahren auf, was ein Benutzer bereits gesehen hat, sodass es beim Neuladen oder einem Kaltstart der App im ersten Frame gerendert und an Ort und Stelle aktualisiert wird. Beide sind benutzerspezifisch und begrenzt, und ein Host leert beide beim Abmelden.

  • createPersistedQueryCache speichert die React-Query-Ergebnisse, anhand derer ein Benutzer navigiert: Konten, Projekte, Projektdetails, die seitenweise Sitzungsliste und Sitzungsdatensätze (isPersistableQueryKey). Ein wiederhergestellter Eintrag behält sein ursprüngliches Alter und wird daher beim Einbinden erneut abgerufen. Die Standardgrenzen sind 1.000.000 Zeichen und 7 Tage.
  • createSavedCopyStore speichert die zuletzt gespeicherten Kopien der Transkripte, die der Server gesendet hat. Registriere ihn mit setSavedCopyStore, und useSession rendert die gespeicherte Kopie vor dem ersten Frame. Die Serverkopie wird dann anhand der Nachrichten-ID damit abgeglichen, und das SDK liest sie 3 Sekunden nach dem Ende jedes Turns erneut. Die Standardgrenzen sind 12 Sitzungen, 1.500.000 Zeichen und 14 Tage. Bei einer Kopie mit mehr als 300.000 Zeichen werden die neuesten Nachrichten behalten, die hineinpassen; ältere Nachrichten werden vom Server geladen, wenn der Benutzer nach oben scrollt.
import {
  browserKeyValueStorage,
  createPersistedQueryCache,
  createSavedCopyStore,
  isPersistableQueryKey,
  setSavedCopyStore,
} from '@beeuni/sdk';

const storage = browserKeyValueStorage(); // null where there is no localStorage
if (storage) {
  const cache = createPersistedQueryCache({ storage, userId, shouldPersist: isPersistableQueryKey });
  cache.restore(queryClient); // synchronous with localStorage: no pending frame
  const stop = cache.persist(queryClient);
  setSavedCopyStore(createSavedCopyStore({ storage, userId }));
}

Übergib unter React Native AsyncStorage als storage. restore gibt dann ein Promise zurück.

Der Speicher für gespeicherte Kopien enthält nur Serveraufzeichnungen: den Transkriptspiegel, den die API schreibt, wenn ein Turn endet. Das Live-Transkript wird nie auf das Gerät geschrieben, sodass ein angehaltener Turn nicht als laufender zurückkehren kann. Ein Laufzeit-Lesevorgang, der keine Nachrichten zurückgibt, belässt die gespeicherten Nachrichten auf dem Bildschirm: Das bedeutet, dass der Computer seinen Zustand verloren hat, nicht, dass die Unterhaltung leer ist. Der erste Laufzeit-Lesevorgang mit Nachrichten gleicht sie ab.

Abmelden und Kontowechsel

Das SDK hält benutzerspezifischen Sitzungszustand im Arbeitsspeicher: Transkripte, ausstehende Fragen und Berechtigungen, Turn-Bestätigungen und Modellauswahlen. Rufe resetIdentityState() bei jedem Identitätswechsel auf: beim Abmelden und wenn sich ein anderer Benutzer anmeldet. Dazu gehört auch eine Anmeldung in einem anderen Tab, die den Benutzer ohne Neuladen der Seite ändert.

Rufe diesen Handler auf, wenn dein Anmeldeablauf einen Nutzer an- oder abmeldet.

import { resetIdentityState } from '@beeuni/sdk/react';

let previousUserId: string | null = null;

function onIdentityChange(userId: string | null) {
  if (userId !== previousUserId) {
    queryClient.clear();
    resetIdentityState();
  }
  previousUserId = userId;
}

resetIdentityState() entfernt auch den Eintrag localStorage aus dem Modellspeicher. Es leert weder die eigenen Caches des Hosts, etwa React Query, noch die an createBeeuni übergebene Tokenquelle. Setze diese im selben Handler zurück. Es wirft nie eine Ausnahme.

Bei den Speichern aus Beim Neuladen aus dem Cache rendern leerst du sie im selben Handler: await cache.clear(), dann await savedCopies.clear() und setSavedCopyStore(null). Keiner der beiden Speicher stellt jemals Daten für einen anderen Benutzer wieder her, aber ein abgemeldetes Gerät sollte sie nicht behalten.

Weiter

  • Sitzungen — das Sitzungshandle, das useSession umschließt, und die BeeuniSendError-Arten.
  • Referenz — die vollständige REST-Schnittstelle, aus der diese Hooks lesen.

Gespeicherter Verlauf beim Start

useSession(projectId, sessionId) zeigt den gespeicherten Chatverlauf an, während sein Computer startet. Das SDK liest die Datenbank unabhängig von der Bereitschaft der Laufzeitumgebung. Live-Nachrichten werden dann anhand ihrer ursprünglichen IDs abgeglichen. Hosts benötigen weder eine separate Verlaufsabfrage noch einen Nachrichtenspeicher.

Der gespeicherte Verlauf wird genau wie das Live-Transkript dargestellt: Text, Reasoning und jeder Tool-Aufruf mit Eingabe, Ausgabe und Fehler. Die vollständige Ansicht eines Sub-Agenten liest dessen eigenes gespeichertes Transkript: Übergib den Scope des übergeordneten Agenten und savedChild: true an useSessionSync(subAgentSessionId, { beeuniSessionScope, savedChild: true }). Das erste Fenster enthält die neuesten 40 Nachrichten mit höchstens 1.000.000 Zeichen. Beim Hochscrollen werden ältere Fenster aus dem gespeicherten Verlauf geladen, auch wenn der Computer ausgeschaltet ist. Anhänge, die den Computer benötigen, werden verfügbar, sobald die Laufzeitumgebung bereit ist.

savedTranscript teilt einem Host mit, was er während des Computerstarts darstellen soll. Es ist loading, solange noch eine gespeicherte Kopie eintreffen kann, shown, sobald Nachrichten in messages vorliegen, und none, wenn nichts angezeigt werden kann, bevor die Laufzeitumgebung antwortet. Ein unbekannter Zustand ist loading, niemals none.

conversationEmpty ist wahr, wenn es nichts gibt, worauf gewartet werden muss. Die gespeicherte Kopie belegt, dass die Unterhaltung leer ist: Beim vollständigen Lesen der Laufzeitumgebung der Sitzung wurden keine Nachrichten gefunden. Seitdem wurde kein Turn beendet, und nichts ist offen oder in der Warteschlange. Fehlende Datensätze machen den Wert nie wahr, sodass eine ältere Sitzung mit Verlauf niemals als leer angezeigt wird. Eine Sitzung erhält diesen Nachweis bei ihrem ersten Start mit aktiviertem gespeichertem Verlauf.

if (s.messages.length === 0) {
  // Nothing saved and nothing to wait for: the user can type now.
  if (s.conversationEmpty) return <Composer />;
  // One round trip for a saved copy; the computer can take minutes.
  return s.savedTranscript === 'none' ? <Booting stage={s.stage} /> : <MessageSkeleton />;
}

Bei Tool-Aufrufen, die vor dem 2026-09-28 gespeichert wurden, gingen Eingabe und Ausgabe verloren. Der Server liefert jeden davon mit der Eingabe aus, die sich aus dem erhaltenen Titel oder den Metadaten belegen lässt: Befehl und Ausgabe eines Befehls, Pfad eines Dateiaufrufs, Suchmuster, Beschreibung eines Sub-Agenten, URL eines Abrufs, Todo-Liste, Name eines Skills. Beim nächsten Start der Sitzung wird der gesamte Verlauf erneut gespeichert, 1.

Ausstehende Prompts

useSessionPrompts(projectId, sessionId) sendet an den persistenten Sitzungseingang. Der Server führt ausstehende Prompts automatisch aus, jeden als eigenen Turn.

Übergib placement: 'transcript', um eine ausstehende Nachricht in der Unterhaltung anzuzeigen. Sie wird vor jedem composer-Eintrag ausgeführt und beendet die aktive Antwort, nachdem der aktuelle Tool-Aufruf abgeschlossen ist. Übergib placement: 'composer', um sie in der bearbeitbaren Liste über dem Eingabefeld zu belassen. Sie wartet, bis die aktive Antwort abgeschlossen ist. Jede Platzierung behält die Sendereihenfolge bei. Übergib delivery: 'steer' | 'queue' | 'interrupt', um festzulegen, wie der Prompt einen laufenden Turn erreicht. steer übergibt ihn beim nächsten Schritt an den Turn; der Turn wird nicht angehalten. queue wartet auf das Ende des Turns. interrupt beendet den Turn nach dem laufenden Tool. Wenn nur delivery angegeben ist, sendet das SDK die daraus abgeleitete Platzierung: interrupt ist transcript, die anderen sind composer. Eine Steer-Zeile, die nicht steuern kann, zeigt delivery: 'queue' an, wobei steer_fallback auf unsupported, not_prompter oder turn_ended gesetzt ist. interrupt(promptId) (“Stop and send”) macht aus einer wartenden Zeile einen Transkripteintrag; eine bereits übertragene Zeile antwortet mit 409.

Im Web-Eingabefeld sendet Enter als steer, während ein Turn läuft, und als Transkript- Sendung, während die Sitzung inaktiv ist. Command+Enter (Control+Enter unter Windows/Linux) verwendet die Platzierung im Eingabefeld. Shift+Enter fügt einen Zeilenumbruch ein.

Listenzeilen enthalten full_text für vollständige Vorschauen nach dem Neuladen. text bleibt die begrenzte Vorschau für ältere Clients. Anhangsbytes sind von Listenantworten ausgeschlossen. Löschen gibt den vollständigen Prompt zurück, um das Löschen verlustfrei rückgängig machen zu können.

Ausstehende Zustellung und aktive Antworten

useSessionWorking() behält state: 'working' bei, während ein Prompt im persistenten Eingang wartet. Dadurch bleibt Stop verfügbar. pendingDelivery: true kennzeichnet einen Prompt, der noch auf dem Weg zur Laufzeitumgebung ist; die Web-App zeigt immer dann einen einzelnen Aktivitätsindikator an, wenn state working ist, unabhängig vom Wert dieses Flags. Aktive Turns und neue Aktivitäten der Laufzeitumgebung setzen es zurück. Ein Abbruch mit Zeitüberschreitung bestätigt nicht, dass die Ausführung beendet wurde.

Die Übernahme durch einen Worker prüft nur die Zulassung und lässt den Prompt weiter warten. Die Zustellung beginnt, nachdem die Zulassung erfolgreich war. Ein bestätigter aktiver Turn entfernt die Darstellung als ausstehend, selbst wenn der vorherige Snapshot des Eingangs diesen Prompt noch aufführt. Aktivitäten der Laufzeitumgebung bewahren bei dieser Übergabe die Nachrichten-ID des aktiven Turns.

Das Web-Eingabefeld bezeichnet Command/Ctrl+Enter als Queue List und “Stop and send” einer Zeile als Quick Queue. Quick Queue-Einträge werden zuerst ausgeführt. Ein wartender Quick Queue-Eintrag erscheint als getönte Blase nach zugestellten Turns, ohne Statustext. Queue List-Einträge bleiben bearbeitbar, bis die Zustellung beginnt. Der Server stellt verpasste Abschlussereignisse anhand exakter Nachweise aus der Laufzeitumgebung wieder her, auch nach dem Neuladen, ohne eine nicht erreichbare Laufzeitumgebung als abgeschlossenen Turn zu behandeln.

Jeder einzelne Druck auf Enter zeigt den ausstehenden Prompt sofort an, auch wenn eine frühere Annahme-Anfrage noch offen ist. Nur ein Zustellungsfehler fügt Text hinzu: seine Ursache, Retry und Remove. Der Servereingang bestimmt weiterhin die Ausführungsreihenfolge.

Der Hook liest Änderungen an der Warteschlange aus dem Steuerungsstream der Sitzung (GET .../sessions/:id/events?channels=control), mit einer Verbindung pro Sitzung, unabhängig davon, wie viele Komponenten ihn einbinden. Jeder Schreibvorgang einer Eingangszeile wird als beeuni.control.queue-Frame übermittelt. Die GET .../prompts-Abfrage läuft nur, solange dieser Stream nicht verbunden ist.

Warum ein Turn endete

Das Transkript eines unterbrochenen Turns enthält nur MessageAbortedError. Die Steuerungsebene speichert, was sie darüber weiß, wie jeder Turn endete: die von der Sandbox genannte Ursache, etwa SandboxMemoryGuard, und welche Turns ohne Angabe einer Ursache abbrachen. Ein angeforderter Stopp — über die Stop-Schaltfläche, abort() oder einen Prompt, der an eine beschäftigte Sitzung gesendet wurde — wird als Anforderung erfasst und niemals als Fehler gemeldet.

useSessionTurnOutcome(projectId, sessionId) gibt last_ended, recent_failures und den Lesezeitpunkt atMs aus dem Cache zurück, den useSessionWorking() aktuell hält. Es stellt keine Anfrage. Übergib das Ergebnis an turnEndNotice, zusammen mit dem, was das Transkript über den Turn aussagt:

const outcome = useSessionTurnOutcome(projectId, sessionId);
const notice = turnEndNotice(outcome, turn.userMessage.info.id, {
  hasError: Boolean(turnError),
  isAbort: turnErrorIsAbort,
});
// notice: { kind: 'sandbox-memory', usedPct: 97, detail: 'sandbox memory at 97% …' }
//       | { kind: 'cause', name: 'SomeGuard', message: '…' }
//       | { kind: 'unexplained' }
//       | null

Der Host ordnet jedem kind seinen eigenen Text zu und parst niemals die Nachricht der Sandbox. null bedeutet „zeige, was das Transkript zeigt“: Ein tatsächlicher Fehler bleibt sichtbar, ein Abbruch wird nicht dargestellt. Ein ungeklärter Fehler wird erst gemeldet, wenn der Lesezeitpunkt einige Sekunden nach dem Ende des Turns liegt, da die Ursache oft einen Frame nach dem Abbruch eintrifft. turnEndCause(outcome, messageId) gibt die unverarbeitete erfasste Ursache zurück oder null.

War diese Seite hilfreich?