diff --git a/internal/store/pg/heartbeat.go b/internal/store/pg/heartbeat.go index 7386260d..387dff46 100644 --- a/internal/store/pg/heartbeat.go +++ b/internal/store/pg/heartbeat.go @@ -276,12 +276,14 @@ func (s *PGHeartbeatStore) ListLogs(ctx context.Context, agentID uuid.UUID, limi // ListDeliveryTargets returns distinct (channel, chatID, title, kind) pairs from sessions for an agent. // Uses idx_sessions_agent (btree on agent_id) for fast lookup. -// Session key format: agent:{key}:{channel}:{kind}:{chatId} +// Session key format: agent:{key}:{channel}:{kind}:{chatId}[:topic:N] +// Extracts full chatId including topic/thread suffix via array_to_string([5:]). +// JOIN on base chatId (split_part segment 5) for contact display name resolution. func (s *PGHeartbeatStore) ListDeliveryTargets(ctx context.Context, agentID uuid.UUID) ([]store.DeliveryTarget, error) { rows, err := s.db.QueryContext(ctx, `SELECT DISTINCT ON (s.channel, chat_id) s.channel, - split_part(s.session_key, ':', 5) AS chat_id, + array_to_string((string_to_array(s.session_key::text, ':'))[5:], ':') AS chat_id, COALESCE( s.metadata->>'chat_title', cc.display_name, diff --git a/internal/store/sqlitestore/heartbeat.go b/internal/store/sqlitestore/heartbeat.go index f84c099b..d9c4b0f8 100644 --- a/internal/store/sqlitestore/heartbeat.go +++ b/internal/store/sqlitestore/heartbeat.go @@ -319,8 +319,8 @@ func (s *SQLiteHeartbeatStore) ListDeliveryTargets(ctx context.Context, agentID return nil, err } - // Parse chatId: 5th colon-separated segment of session_key. - chatID := extractSessionKeyPart(sessionKey, 5) + // Parse chatId: everything after 4th colon (includes :topic:N suffix for forum groups). + chatID := extractSessionKeyTail(sessionKey, 5) if chatID == "" { continue } @@ -369,3 +369,14 @@ func extractSessionKeyPart(key string, n int) string { } return parts[n-1] } + +// extractSessionKeyTail returns everything from the n-th colon-delimited segment onwards. +// For session key "agent:default:telegram:group:-100123:topic:42" with n=5, +// returns "-100123:topic:42" (includes topic/thread suffix). +func extractSessionKeyTail(key string, n int) string { + parts := strings.SplitN(key, ":", n) + if len(parts) < n { + return "" + } + return parts[n-1] +}