Class RecapService

java.lang.Object
com.axelor.ai.chat.RecapService

public class RecapService extends Object
Builds a conversation's recap: one written account of what it did and settled.

The recorded tool calls are merged per record and handed to the model as facts the summary must be built from and may not exceed. A ledger with no writes and a model that says nothing yields no card at all - a recap is never reconstructed from what the assistant claimed it did.

  • Method Details

    • scopeOf

      public static RecapService.Scope scopeOf(boolean all, LocalDateTime lastSeen, LocalDateTime tip)
      The unread tail, or the whole conversation when all, when the reader has no mark, or when their mark is already at the tip. The mark comes from the client because that is the only place it exists - a participant row records a first open, and the owner has no row at all.
    • recap

      public Recap recap(AiChat chat, boolean all, LocalDateTime lastSeen)
      Produces the recap, or null when there is nothing to recap. An unchanged tip re-renders what is stored and makes no model call; all always regenerates, being a request for a different range than the stored card answers.
    • postToRecord

      public Long postToRecord(AiChat chat, String markdown, User author)
      Publishes a recap to the pinned record's activity stream, as a comment authored by the caller. There is no confirmation step - what is posted is what they were reading - and unpost(com.axelor.ai.db.AiChat, java.lang.Long, com.axelor.auth.db.User) is what pays for that.

      The markdown is escaped on the way to HTML, because the activity widget sanitises rather than escapes what it renders.

      Returns:
      the message id, or null when there is no record to post to, or none they may read
    • unpost

      public boolean unpost(AiChat chat, Long messageId, User author)
      Takes a posted recap back off the record. Not a full undo: followers were notified when the comment landed, and that cannot be unsent.

      Three conditions, all necessary: the message is one of ours, it is on the record this conversation is about, and the caller wrote it - a person may remove their own comment, and no one else's.

      Returns:
      true when a message was removed
    • markPosted

      public void markPosted(AiChat chat, String messageUuid, Long postedId)
      Records on the card itself which comment it became, or that it is no longer posted. Per card rather than per conversation, since a conversation can produce several and each is posted on its own.

      Silent when the row cannot be found: a mark that fails to stick costs a reader the undo button, which is not worth failing a post that already succeeded.

    • read

      public Recap read(String json)