Class AbstractMessage
java.lang.Object
uno.anahata.asi.agi.event.BasicPropertyChangeSource
uno.anahata.asi.agi.message.AbstractMessage
- All Implemented Interfaces:
PropertyChangeSource, Rebindable
- Direct Known Subclasses:
AbstractModelMessage, UserMessage
The abstract base class for all messages in a conversation, providing common
metadata and functionality for the rich, hierarchical V2 domain model.
This class ensures each message has a unique identity, timestamp, and full
access to the Agi context. It supports thread-safe iteration of its
components via a CopyOnWriteArrayList to facilitate background
persistence during active generation.
- Author:
- anahata
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AgiA backward reference to the Agi session that owns this message.private final List<AbstractPart> The list of parts that make up the message content.private longA monotonically increasing number assigned to the message when it is added to a agi, representing its order in the conversation.private final longThe timestamp when this message was created, in milliseconds since the epoch.Fields inherited from class BasicPropertyChangeSource
propertyChangeSupport -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionabstract BlobPartaddBlobPart(String mimeType, byte[] data) Creates and adds a new binary data part to this message.abstract BlobPartaddBlobPart(Path path) Creates and adds a new binary data part from a local file path.voidaddPart(@NonNull AbstractPart part) Safely adds a single part to this message, establishing the bidirectional relationship and ensuring the part is fully initialized before firing property change events.abstract TextPartaddTextPart(String text) Creates and adds a new text part to this message.protected voidHook for subclasses to inject specialized metadata into the message header.asText(boolean includePruned) Convenience method to get the message content as a single string, concatenating the text representation of all its parts.Creates a standardized text header containing metadata for this message.intgetDepth()Calculates the "depth" of this message, defined as its distance from the most recent message in the agi history.abstract StringGets the ID of the device where this message was created or processed.intCalculates the total effective tokens consumed by this message, including the in-band metadata header and all of its parts.abstract StringgetFrom()Gets the identity of the sender of this message.protected StringReturns the identity label for the metadata header (e.g., "Message ID: 12").getParts()Gets an unmodifiable list of all parts in this message.getParts(boolean includePruned) The definitive, encapsulated method for retrieving the parts of a message that should be sent to the model, respecting the pruning policy.intCalculates the remaining depth of the message as the maximum remaining depth of all its parts.abstract RolegetRole()Gets the role of the entity that created this message.intgetTokenCount(boolean includePruned) Calculates the total number of tokens in this message, summing the token counts of its visible parts.booleanChecks if all parts in this message are explicitly pinned.booleanChecks if all parts in this message are explicitly pruned.booleanChecks if any part in this message is explicitly pinned.booleanCalculates the EFFECTIVE pruned state of this message.booleanisEmpty()Checks if the message is empty.booleanDetermines if this message is eligible for "hard pruning" (permanent removal from history).booleanChecks if this message is eligible for pruning or removal.voidPins all parts in this message.voidExplicitly prunes all parts in this message.voidremove()Removes this message from the agi history.voidremovePart(AbstractPart part) Removes a part from this message and severs the bidirectional link.voidResets the cached token counts on all parts contained within this message, forcing a lazy recalculation under the new selected model's tokenizer.voidSets all parts in this message to AUTO.booleanHook for subclasses to declare if they should generate in-band metadata headers.Methods inherited from class BasicPropertyChangeSource
addPropertyChangeListener, addPropertyChangeListener, rebind, removePropertyChangeListener, removePropertyChangeListenerMethods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface PropertyChangeSource
getPropertyChangeSupport
-
Field Details
-
timestamp
private final long timestampThe timestamp when this message was created, in milliseconds since the epoch. -
sequentialId
private long sequentialIdA monotonically increasing number assigned to the message when it is added to a agi, representing its order in the conversation. -
parts
The list of parts that make up the message content. Uses CopyOnWriteArrayList to allow thread-safe iteration during background serialization (e.g., auto-save) while the model is adding parts or appending text to existing parts. -
agi
A backward reference to the Agi session that owns this message. This is the root of the V2 context management system, allowing any domain object to access the full application state. It is intentionally not transient to support full serialization with Kryo.
-
-
Constructor Details
-
AbstractMessage
public AbstractMessage()
-
-
Method Details
-
getRole
Gets the role of the entity that created this message. This is implemented by subclasses to provide compile-time type safety.- Returns:
- The role of the message creator.
-
getFrom
Gets the identity of the sender of this message. For user messages, this is typically the user's name. For model messages, it's the model ID. For tool messages, it's the identity of the execution context.- Returns:
- The sender's identity.
-
getDevice
Gets the ID of the device where this message was created or processed. This could be a hostname, a JVM ID, or a cloud identifier.- Returns:
- The device ID.
-
isPrunnableOrRemovable
public boolean isPrunnableOrRemovable()Checks if this message is eligible for pruning or removal. A message is prunnable if it is attached to a agi and has been assigned a sequential ID (i.e., it's not the system message or a transient message).- Returns:
trueif the message is prunnable.
-
addPart
Safely adds a single part to this message, establishing the bidirectional relationship and ensuring the part is fully initialized before firing property change events.- Parameters:
part- The part to add.- Throws:
IllegalArgumentException- if the part is already attached to this or another message.
-
removePart
Removes a part from this message and severs the bidirectional link.- Parameters:
part- The part to remove.- Throws:
IllegalArgumentException- if the part is not attached to this message.
-
remove
public void remove()Removes this message from the agi history. -
getDepth
public int getDepth()Calculates the "depth" of this message, defined as its distance from the most recent message in the agi history. The head message has a depth of 0.- Returns:
- The depth of the message.
-
asText
Convenience method to get the message content as a single string, concatenating the text representation of all its parts.- Parameters:
includePruned- whether to include pruned parts- Returns:
- The concatenated text content.
-
isAnyPinned
public boolean isAnyPinned()Checks if any part in this message is explicitly pinned.- Returns:
trueif at least one part is pinned.
-
isAllPinned
public boolean isAllPinned()Checks if all parts in this message are explicitly pinned.- Returns:
trueif all parts are pinned.
-
isAllPruned
public boolean isAllPruned()Checks if all parts in this message are explicitly pruned.- Returns:
trueif all parts are PRUNED.
-
isEffectivelyPruned
public boolean isEffectivelyPruned()Calculates the EFFECTIVE pruned state of this message. A message is effectively pruned ONLY if it contains no visible (un-pruned) parts.- Returns:
trueif the message is effectively pruned.
-
isGarbageCollectable
public boolean isGarbageCollectable()Determines if this message is eligible for "hard pruning" (permanent removal from history). In the atomic model, a message is collectable if it is effectively pruned.- Returns:
trueif the message can be safely removed from history.
-
pinAllParts
public void pinAllParts()Pins all parts in this message. -
setAutoAllParts
public void setAutoAllParts()Sets all parts in this message to AUTO. -
pruneAllParts
public void pruneAllParts()Explicitly prunes all parts in this message. -
resetTokenCounts
public void resetTokenCounts()Resets the cached token counts on all parts contained within this message, forcing a lazy recalculation under the new selected model's tokenizer. -
getTokenCount
public int getTokenCount(boolean includePruned) Calculates the total number of tokens in this message, summing the token counts of its visible parts.- Parameters:
includePruned- whether to include pruned parts- Returns:
- The total token count.
-
getEffectiveTokenCount
public int getEffectiveTokenCount()Calculates the total effective tokens consumed by this message, including the in-band metadata header and all of its parts.- Returns:
- The total effective token count.
-
getParts
The definitive, encapsulated method for retrieving the parts of a message that should be sent to the model, respecting the pruning policy.- Parameters:
includePruned- If true, all parts are returned, bypassing the pruning check.- Returns:
- A new list of the visible parts.
-
getParts
Gets an unmodifiable list of all parts in this message.- Returns:
- The list of parts.
-
getRemainingDepth
public int getRemainingDepth()Calculates the remaining depth of the message as the maximum remaining depth of all its parts.- Returns:
- The maximum remaining depth.
-
addTextPart
-
addBlobPart
-
addBlobPart
-
createMetadataHeader
Creates a standardized text header containing metadata for this message. This is used for in-band metadata injection to improve model self-awareness.- Returns:
- A formatted metadata header string.
-
getIdentityLabel
Returns the identity label for the metadata header (e.g., "Message ID: 12"). Subclasses can override this to hide or customize the identity.- Returns:
- The identity label.
-
appendMetadata
Hook for subclasses to inject specialized metadata into the message header.- Parameters:
sb- The StringBuilder building the header.
-
shouldCreateMetadata
public boolean shouldCreateMetadata()Hook for subclasses to declare if they should generate in-band metadata headers.- Returns:
trueif metadata headers should be generated.
-
isEmpty
public boolean isEmpty()Checks if the message is empty. A message is considered empty if it contains no parts.- Returns:
trueif the message is empty,falseotherwise.
-

