Documentation
¶
Index ¶
- func CountMessageTokens(ctx context.Context, model *api.Model, agent *api.Agent, messages []Message) ([]int, error)
- func MessageToAPI(m Message) api.Message
- func MessagesToAPI(messages []Message) []api.Message
- type Conversation
- type ConversationList
- type ConversationListItem
- type Message
- type Repo
- type TemplateData
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CountMessageTokens ¶ added in v0.8.0
func CountMessageTokens(ctx context.Context, model *api.Model, agent *api.Agent, messages []Message) ([]int, error)
CountMessageTokens counts tokens for each message using the provider's CountTokens endpoint. Messages that already have a stored count (Metadata.Tokens > 0) are reused. Empty messages (no text, no tool calls, no tool results) trivially count as 0 and are skipped. Returns an error when the provider doesn't support token counting.
func MessageToAPI ¶
func MessagesToAPI ¶
Types ¶
type Conversation ¶
type Conversation struct {
ID uint `gorm:"primaryKey"`
ShortName sql.NullString
Title string
Agent sql.NullString
Workspace sql.NullString
ContextLength int
SelectedRootID *uint `gorm:"index"`
SelectedRoot *Message `gorm:"foreignKey:SelectedRootID"`
RootMessages []Message `gorm:"-:all"`
LastMessageAt time.Time
}
type ConversationList ¶
type ConversationList struct {
Total int
Items []ConversationListItem
HasMore bool
}
type ConversationListItem ¶
type Message ¶
type Message struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
Metadata api.MessageMeta
ConversationID *uint `gorm:"index"`
Conversation *Conversation `gorm:"foreignKey:ConversationID"`
ParentID *uint `gorm:"index"`
Parent *Message `gorm:"foreignKey:ParentID"`
Replies []Message `gorm:"foreignKey:ParentID"`
SelectedReplyID *uint `gorm:"index"`
SelectedReply *Message `gorm:"foreignKey:SelectedReplyID"`
Role api.MessageRole
Content string
ReasoningContent string
Parts []api.ContentPart `gorm:"serializer:json-compat"`
ToolCalls []api.ToolCall `gorm:"serializer:json-compat"` // a json array of tool calls (from the model)
ToolResults []api.ToolResult `gorm:"serializer:json-compat"` // a json array of tool results
}
func MessageFromAPI ¶
func MessagesFromAPI ¶
func (*Message) AfterFind ¶
AfterFind is a GORM hook that runs after loading a Message from the database. For legacy rows that lack Parts, it builds Parts from the Content/ReasoningContent fields.
func (*Message) BeforeSave ¶
BeforeSave is a GORM hook that clears the legacy Content and ReasoningContent fields before writing, so only Parts is persisted.
func (*Message) SetTextContent ¶
SetTextContent updates the first text-type part, or appends one if none exists.
func (*Message) TextContent ¶
TextContent returns the message's text content, extracted from text-type parts. AfterFind guarantees Parts is always populated.
func (*Message) ThinkingContent ¶
ThinkingContent returns the message's thinking/reasoning content, extracted from thinking-type parts. AfterFind guarantees Parts is always populated.
type Repo ¶
type Repo interface {
LoadConversationList(limit int) (ConversationList, error)
LoadConversationsSince(since time.Time) ([]Conversation, error)
SearchConversations(query string, limit int) (ConversationList, error)
FindConversationByShortName(shortName string) (*Conversation, error)
FindLatestConversationByWorkspace(workspace string) (*Conversation, error)
ConversationShortNameCompletions(search string) []string
GetConversationByID(id uint) (*Conversation, error)
GetRootMessages(conversationID uint) ([]Message, error)
CreateConversation(title string) (*Conversation, error)
UpdateConversation(*Conversation) error
DeleteConversation(id uint) error
GetMessageByID(messageID uint) (*Message, error)
SaveMessage(message Message) (*Message, error)
UpdateMessage(message *Message) error
CloneBranch(toClone Message) (*Message, uint, error)
Reply(to *Message, messages ...Message) ([]Message, error)
// BranchMessage creates a new message at the same position as msg (same
// parent and conversation) with the given content, without copying any
// descendants, and sets it as the selected path. Returns the new message.
BranchMessage(msg Message, content string) (*Message, error)
// BranchRootMessage creates a new root message in oldRoot's conversation
// with the given content. The old root's selected reply is re-parented to
// the new root and the conversation's selected root is updated. This
// avoids mutating a shared root in-place when the system prompt changes.
// Returns the new root message.
BranchRootMessage(oldRoot *Message, content string) (*Message, error)
PathToRoot(message *Message) ([]Message, error)
PathToLeaf(message *Message) ([]Message, error)
// GetSelectedThread returns the "selected thread" of the conversation:
// a chain of messages starting from SelectedRoot, following each
// message's SelectedReply until the leaf is reached.
GetSelectedThread(*Conversation) ([]Message, error)
// SetSelected marks message as the selected choice at its position in the
// tree. If the message has no parent, it becomes the conversation's
// SelectedRoot; otherwise it becomes its parent's SelectedReply.
SetSelected(message *Message) error
// DeleteMessage deletes the given message. If withDescendants is false,
// its children are re-parented to the deleted message's parent (or made
// root messages), preserving the selected path where possible. If
// withDescendants is true, the message and all its descendants are
// deleted, and the parent's selected reply is updated to a sibling if
// one exists.
DeleteMessage(msg Message, withDescendants bool) error
// CycleSelectedRoot advances (forward=true) or retreats (forward=false)
// the conversation's SelectedRoot among the available root messages.
// Returns nil without error when there is only one root message.
CycleSelectedRoot(conv *Conversation, forward bool) (*Message, error)
// CycleSelectedReply advances or retreats the message's SelectedReply
// among its available replies.
// Returns nil without error when there is only one reply.
CycleSelectedReply(message *Message, forward bool) (*Message, error)
// StartConversation creates a new conversation with the given messages.
StartConversation(messages ...Message) (*Conversation, []Message, error)
CloneConversation(toClone Conversation) (*Conversation, uint, error)
}
Repo exposes message and conversation management operations.
type TemplateData ¶ added in v0.7.0
type TemplateData struct {
Date string // current date in YYYY-MM-DD format
Workspace string // effective workspace path (sandbox-aware)
}
TemplateData carries the variables available in system prompt templates.