feat(discord): include channel name in dynamic context
This commit is contained in:
parent
9222351871
commit
621836cbe9
4 changed files with 63 additions and 1 deletions
|
|
@ -55,6 +55,7 @@ type processOptions struct {
|
||||||
SessionKey string // Session identifier for history/context
|
SessionKey string // Session identifier for history/context
|
||||||
Channel string // Target channel for tool execution
|
Channel string // Target channel for tool execution
|
||||||
ChatID string // Target chat ID for tool execution
|
ChatID string // Target chat ID for tool execution
|
||||||
|
ChatName string // Optional human-readable chat name for prompt context
|
||||||
UserMessage string // User message content (may include prefix)
|
UserMessage string // User message content (may include prefix)
|
||||||
Media []string // media:// refs from inbound message
|
Media []string // media:// refs from inbound message
|
||||||
DefaultResponse string // Response when LLM returns empty
|
DefaultResponse string // Response when LLM returns empty
|
||||||
|
|
@ -67,6 +68,7 @@ const (
|
||||||
defaultResponse = "I've completed processing but have no response to give. Increase `max_tool_iterations` in config.json."
|
defaultResponse = "I've completed processing but have no response to give. Increase `max_tool_iterations` in config.json."
|
||||||
sessionKeyAgentPrefix = "agent:"
|
sessionKeyAgentPrefix = "agent:"
|
||||||
metadataKeyAccountID = "account_id"
|
metadataKeyAccountID = "account_id"
|
||||||
|
metadataKeyChatName = "chat_name"
|
||||||
metadataKeyGuildID = "guild_id"
|
metadataKeyGuildID = "guild_id"
|
||||||
metadataKeyTeamID = "team_id"
|
metadataKeyTeamID = "team_id"
|
||||||
metadataKeyParentPeerKind = "parent_peer_kind"
|
metadataKeyParentPeerKind = "parent_peer_kind"
|
||||||
|
|
@ -619,6 +621,7 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
|
||||||
SessionKey: sessionKey,
|
SessionKey: sessionKey,
|
||||||
Channel: msg.Channel,
|
Channel: msg.Channel,
|
||||||
ChatID: msg.ChatID,
|
ChatID: msg.ChatID,
|
||||||
|
ChatName: inboundMetadata(msg, metadataKeyChatName),
|
||||||
UserMessage: msg.Content,
|
UserMessage: msg.Content,
|
||||||
Media: msg.Media,
|
Media: msg.Media,
|
||||||
DefaultResponse: defaultResponse,
|
DefaultResponse: defaultResponse,
|
||||||
|
|
@ -761,7 +764,7 @@ func (al *AgentLoop) runAgentLoop(
|
||||||
opts.UserMessage,
|
opts.UserMessage,
|
||||||
opts.Media,
|
opts.Media,
|
||||||
opts.Channel,
|
opts.Channel,
|
||||||
opts.ChatID,
|
displayChatID(opts.ChatID, opts.ChatName),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resolve media:// refs to base64 data URLs (streaming)
|
// Resolve media:// refs to base64 data URLs (streaming)
|
||||||
|
|
@ -1818,6 +1821,13 @@ func inboundMetadata(msg bus.InboundMessage, key string) string {
|
||||||
return msg.Metadata[key]
|
return msg.Metadata[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func displayChatID(chatID, chatName string) string {
|
||||||
|
if chatID == "" || chatName == "" {
|
||||||
|
return chatID
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s (%s)", chatID, chatName)
|
||||||
|
}
|
||||||
|
|
||||||
// extractParentPeer extracts the parent peer (reply-to) from inbound message metadata.
|
// extractParentPeer extracts the parent peer (reply-to) from inbound message metadata.
|
||||||
func extractParentPeer(msg bus.InboundMessage) *routing.RoutePeer {
|
func extractParentPeer(msg bus.InboundMessage) *routing.RoutePeer {
|
||||||
parentKind := inboundMetadata(msg, metadataKeyParentPeerKind)
|
parentKind := inboundMetadata(msg, metadataKeyParentPeerKind)
|
||||||
|
|
|
||||||
|
|
@ -889,6 +889,16 @@ func TestTargetReasoningChannelID_AllChannels(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDisplayChatID_AppendsChatName(t *testing.T) {
|
||||||
|
if got := displayChatID("123456789012345678", "#general"); got != "123456789012345678 (#general)" {
|
||||||
|
t.Fatalf("displayChatID() = %q, want %q", got, "123456789012345678 (#general)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := displayChatID("123456789012345678", ""); got != "123456789012345678" {
|
||||||
|
t.Fatalf("displayChatID() without chatName = %q, want %q", got, "123456789012345678")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHandleReasoning(t *testing.T) {
|
func TestHandleReasoning(t *testing.T) {
|
||||||
newLoop := func(t *testing.T) (*AgentLoop, *bus.MessageBus) {
|
newLoop := func(t *testing.T) (*AgentLoop, *bus.MessageBus) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
|
||||||
|
|
@ -449,12 +449,31 @@ func (c *DiscordChannel) handleMessage(s *discordgo.Session, m *discordgo.Messag
|
||||||
"display_name": sender.DisplayName,
|
"display_name": sender.DisplayName,
|
||||||
"guild_id": m.GuildID,
|
"guild_id": m.GuildID,
|
||||||
"channel_id": m.ChannelID,
|
"channel_id": m.ChannelID,
|
||||||
|
"chat_name": resolveDiscordChannelName(c.session, m.ChannelID),
|
||||||
"is_dm": fmt.Sprintf("%t", m.GuildID == ""),
|
"is_dm": fmt.Sprintf("%t", m.GuildID == ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.HandleMessage(c.ctx, peer, m.ID, senderID, m.ChannelID, content, mediaPaths, metadata, sender)
|
c.HandleMessage(c.ctx, peer, m.ID, senderID, m.ChannelID, content, mediaPaths, metadata, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveDiscordChannelName(session *discordgo.Session, channelID string) string {
|
||||||
|
if session == nil || channelID == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if session.State != nil {
|
||||||
|
if channel, err := session.State.Channel(channelID); err == nil && channel != nil && channel.Name != "" {
|
||||||
|
return "#" + channel.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err := session.Channel(channelID)
|
||||||
|
if err != nil || channel == nil || channel.Name == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return "#" + channel.Name
|
||||||
|
}
|
||||||
|
|
||||||
// startTyping starts a continuous typing indicator loop for the given chatID.
|
// startTyping starts a continuous typing indicator loop for the given chatID.
|
||||||
// It stops any existing typing loop for that chatID before starting a new one.
|
// It stops any existing typing loop for that chatID before starting a new one.
|
||||||
func (c *DiscordChannel) startTyping(chatID string) {
|
func (c *DiscordChannel) startTyping(chatID string) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package discord
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestChannelRefRegex(t *testing.T) {
|
func TestChannelRefRegex(t *testing.T) {
|
||||||
|
|
@ -96,3 +98,24 @@ func TestMsgLinkRegex_MultipleMatches(t *testing.T) {
|
||||||
t.Errorf("3rd match = %v, want guild=7 chan=8 msg=9", matches[2])
|
t.Errorf("3rd match = %v, want guild=7 chan=8 msg=9", matches[2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveDiscordChannelName_FromState(t *testing.T) {
|
||||||
|
session, err := discordgo.New("Bot test-token")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("discordgo.New() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session.StateEnabled = true
|
||||||
|
session.State = discordgo.NewState()
|
||||||
|
session.State.GuildAdd(&discordgo.Guild{ID: "guild-1"})
|
||||||
|
session.State.ChannelAdd(&discordgo.Channel{
|
||||||
|
ID: "123",
|
||||||
|
Name: "general",
|
||||||
|
Type: discordgo.ChannelTypeGuildText,
|
||||||
|
GuildID: "guild-1",
|
||||||
|
})
|
||||||
|
|
||||||
|
if got := resolveDiscordChannelName(session, "123"); got != "#general" {
|
||||||
|
t.Fatalf("resolveDiscordChannelName() = %q, want %q", got, "#general")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue