mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
de62f94315
When input tokens exceed a configurable threshold after a conversation round, the system asynchronously compacts older messages into a summary. Cascading compactions reference prior summaries via <prior_context> tags to maintain conversational continuity without duplicating content. - Add bot_history_message_compacts table and compact_id on messages - Add compaction_enabled, compaction_threshold, compaction_model_id to bots - Implement compaction service (internal/compaction) with LLM summarization - Integrate into conversation flow: replace compacted messages with summaries wrapped in <summary> tags during context loading - Add REST API endpoints (GET/DELETE /bots/:bot_id/compaction/logs) - Add frontend Compaction tab with settings and log viewer - Wire compaction service into both dev (cmd/agent) and prod (cmd/memoh) entry points - Update test mocks to include new GetBotByID columns
94 lines
4.2 KiB
Go
94 lines
4.2 KiB
Go
package message
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
// MessageAsset carries media asset metadata attached to a message.
|
|
// ContentHash is the content-addressed identifier for the media file.
|
|
type MessageAsset struct {
|
|
ContentHash string `json:"content_hash"`
|
|
Role string `json:"role"`
|
|
Ordinal int `json:"ordinal"`
|
|
Mime string `json:"mime"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
StorageKey string `json:"storage_key"`
|
|
Name string `json:"name,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
}
|
|
|
|
// Message represents a single persisted bot message.
|
|
type Message struct {
|
|
ID string `json:"id"`
|
|
BotID string `json:"bot_id"`
|
|
SessionID string `json:"session_id,omitempty"`
|
|
SenderChannelIdentityID string `json:"sender_channel_identity_id,omitempty"`
|
|
SenderUserID string `json:"sender_user_id,omitempty"`
|
|
SenderDisplayName string `json:"sender_display_name,omitempty"`
|
|
SenderAvatarURL string `json:"sender_avatar_url,omitempty"`
|
|
Platform string `json:"platform,omitempty"`
|
|
ExternalMessageID string `json:"external_message_id,omitempty"`
|
|
SourceReplyToMessageID string `json:"source_reply_to_message_id,omitempty"`
|
|
Role string `json:"role"`
|
|
Content json.RawMessage `json:"content"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
Usage json.RawMessage `json:"usage,omitempty"`
|
|
Assets []MessageAsset `json:"assets,omitempty"`
|
|
CompactID string `json:"compact_id,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// AssetRef links a media asset to a persisted message.
|
|
// ContentHash is the content-addressed identifier for the media file.
|
|
type AssetRef struct {
|
|
ContentHash string `json:"content_hash"`
|
|
Role string `json:"role"`
|
|
Ordinal int `json:"ordinal"`
|
|
Mime string `json:"mime,omitempty"`
|
|
SizeBytes int64 `json:"size_bytes,omitempty"`
|
|
StorageKey string `json:"storage_key,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
}
|
|
|
|
// PersistInput is the input for persisting a message.
|
|
type PersistInput struct {
|
|
BotID string
|
|
SessionID string
|
|
SenderChannelIdentityID string
|
|
SenderUserID string
|
|
ExternalMessageID string
|
|
SourceReplyToMessageID string
|
|
Role string
|
|
Content json.RawMessage
|
|
Metadata map[string]any
|
|
Usage json.RawMessage
|
|
Assets []AssetRef
|
|
ModelID string
|
|
}
|
|
|
|
// Writer defines write behavior needed by the inbound router.
|
|
type Writer interface {
|
|
Persist(ctx context.Context, input PersistInput) (Message, error)
|
|
}
|
|
|
|
// Service defines message read/write behavior.
|
|
type Service interface {
|
|
Writer
|
|
List(ctx context.Context, botID string) ([]Message, error)
|
|
ListSince(ctx context.Context, botID string, since time.Time) ([]Message, error)
|
|
ListActiveSince(ctx context.Context, botID string, since time.Time) ([]Message, error)
|
|
ListLatest(ctx context.Context, botID string, limit int32) ([]Message, error)
|
|
ListBefore(ctx context.Context, botID string, before time.Time, limit int32) ([]Message, error)
|
|
ListBySession(ctx context.Context, sessionID string) ([]Message, error)
|
|
ListSinceBySession(ctx context.Context, sessionID string, since time.Time) ([]Message, error)
|
|
ListActiveSinceBySession(ctx context.Context, sessionID string, since time.Time) ([]Message, error)
|
|
ListLatestBySession(ctx context.Context, sessionID string, limit int32) ([]Message, error)
|
|
ListBeforeBySession(ctx context.Context, sessionID string, before time.Time, limit int32) ([]Message, error)
|
|
DeleteByBot(ctx context.Context, botID string) error
|
|
DeleteBySession(ctx context.Context, sessionID string) error
|
|
LinkAssets(ctx context.Context, messageID string, assets []AssetRef) error
|
|
}
|