Introduces a new `reaction` tool that lets the LLM add an emoji reaction to a Telegram message instead of sending a text reply. When the reaction tool (or message tool) handles a turn, CleanupState is now called on the channel manager so typing indicators and placeholder messages are properly removed even though no outbound message is published via the bus.
73 lines
3.2 KiB
Go
73 lines
3.2 KiB
Go
package channels
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/bus"
|
|
"github.com/sipeed/picoclaw/pkg/commands"
|
|
)
|
|
|
|
// TypingCapable — channels that can show a typing/thinking indicator.
|
|
// StartTyping begins the indicator and returns a stop function.
|
|
// The stop function MUST be idempotent and safe to call multiple times.
|
|
type TypingCapable interface {
|
|
StartTyping(ctx context.Context, chatID string) (stop func(), err error)
|
|
}
|
|
|
|
// MessageEditor — channels that can edit an existing message.
|
|
// messageID is always string; channels convert platform-specific types internally.
|
|
type MessageEditor interface {
|
|
EditMessage(ctx context.Context, chatID string, messageID string, content string) error
|
|
}
|
|
|
|
// MessageDeleter — channels that can delete an existing message.
|
|
// messageID is always string; channels convert platform-specific types internally.
|
|
type MessageDeleter interface {
|
|
DeleteMessage(ctx context.Context, chatID string, messageID string) error
|
|
}
|
|
|
|
// ReactionCapable — channels that can add a temporary reaction (e.g. 👀) to an
|
|
// inbound message as a processing indicator.
|
|
// ReactToMessage adds a reaction and returns an undo function to remove it.
|
|
// The undo function MUST be idempotent and safe to call multiple times.
|
|
type ReactionCapable interface {
|
|
ReactToMessage(ctx context.Context, chatID, messageID string) (undo func(), err error)
|
|
}
|
|
|
|
// MessageReactor — channels that can set an explicit emoji reaction on a
|
|
// specific message as a final user-visible action.
|
|
type MessageReactor interface {
|
|
SetMessageReaction(ctx context.Context, chatID, messageID, emoji string) error
|
|
}
|
|
|
|
// PlaceholderCapable — channels that can send a placeholder message
|
|
// (e.g. "Thinking... 💭") that will later be edited to the actual response.
|
|
// The channel MUST also implement MessageEditor for the placeholder to be useful.
|
|
// SendPlaceholder returns the platform message ID of the placeholder so that
|
|
// Manager.preSend can later edit it via MessageEditor.EditMessage.
|
|
type PlaceholderCapable interface {
|
|
SendPlaceholder(ctx context.Context, chatID string) (messageID string, err error)
|
|
}
|
|
|
|
// PlaceholderRecorder is injected into channels by Manager.
|
|
// Channels call these methods on inbound to register typing/placeholder state.
|
|
// Manager uses the registered state on outbound to stop typing and edit placeholders.
|
|
type PlaceholderRecorder interface {
|
|
RecordPlaceholder(channel, chatID, placeholderID string)
|
|
RecordTypingStop(channel, chatID string, stop func())
|
|
RecordReactionUndo(channel, chatID string, undo func())
|
|
}
|
|
|
|
// CommandRegistrarCapable is implemented by channels that can register
|
|
// command menus with their upstream platform (e.g. Telegram BotCommand).
|
|
// Channels that do not support platform-level command menus can ignore it.
|
|
type CommandRegistrarCapable interface {
|
|
RegisterCommands(ctx context.Context, defs []commands.Definition) error
|
|
}
|
|
|
|
// SyncSender — channels that can bypass the async bus to send a message synchronously.
|
|
// This is typically used by internal tools (like TaskTool) that must immediately
|
|
// receive the generated message ID in order to edit it later.
|
|
type SyncSender interface {
|
|
SendMessageWithID(ctx context.Context, msg bus.OutboundMessage) (string, error)
|
|
}
|