Interface ResponseListener

All Superinterfaces:
Serializable
Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface public interface ResponseListener extends Serializable
Listener for LLM response events.

The listener is called when the turn ends — normally when the assistant's stream has completed, whether successfully or with an error, but also when the turn fails before a stream ever opens. It fires at most once per prompt: a prompt rejected by the RequestInterceptor and a postponed prompt abandoned because its UI was detached end without firing it. The same lifecycle moment as AIController.onResponse(ResponseListener.ResponseEvent). Use it to persist conversation state (via AIOrchestrator.getHistory()), trigger follow-up actions, or surface errors to the user.

On success the response text may still be empty if the model emitted only tool calls or stopped without producing visible content. Such turns are successful exchanges; check event.getResponse().isEmpty() if the listener should only react to text-bearing responses. Empty responses are not appended to AIOrchestrator.getHistory().

On failure ResponseListener.ResponseEvent.getError() carries the cause (timeout, stream error, a provider's tool call limit as a ToolCallLimitExceededException, any throw between AIController.onRequest(RequestListener.RequestEvent) and the start of the stream, or a RequestInterceptor failure — a throw, a fail, or an interception timeout); the response text is empty — text received before the failure is not passed on. An interceptor failure fires the listener without a preceding AIController.onRequest(RequestListener.RequestEvent), so an error does not imply that per-turn setup has happened.

A turn the model completed but the AIController could not apply is a failure too: when AIController.onResponse(ResponseEvent) throws on a successful turn, the listener receives that exception as the error, with an empty response text. The assistant's text stays in the message list and in AIOrchestrator.getHistory(), since the model did produce it. A throw while the controller handles a turn that had already failed does not replace the original error.

The listener is not called when history is restored via Builder.withHistory().

Threading: the listener runs as a ui.access() task, right after AIController.onResponse(ResponseEvent) when a controller is attached. The session is locked and the Vaadin thread locals are bound, so UI components can be updated directly; blocking work (e.g. database writes) holds the session lock for its duration, as in any ui.access() task. If the UI is detached when the turn ends, the listener still runs, without a session and without the controller hook.

Since:
25.3
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Interface
    Description
    static class 
    Event fired when a turn ends, on success or failure.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Called when the turn has ended (see the class documentation for the exact moments).
  • Method Details

    • onResponse

      void onResponse(ResponseListener.ResponseEvent event)
      Called when the turn has ended (see the class documentation for the exact moments).
      Parameters:
      event - the response event