picoclaw/pkg/channels/interfaces.go
Dmitrii Balabanov 81d606766a Add reaction tool with typing/placeholder cleanup
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.
2026-03-09 19:38:35 +02:00

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)
}