feat(channel): pass conversation type through to agent gateway and persist in route

Propagate conversation type (direct/group/thread) from channel adapters
all the way to the agent prompt. Store conversation_type on bot_channel_routes
so the bot knows whether a message originates from a p2p chat, group, or thread.

Schema changes are folded into the 0001 init migration (destructive update).
This commit is contained in:
BBQ
2026-02-13 05:10:35 +08:00
parent 0406f42e86
commit faaadf14c5
18 changed files with 173 additions and 153 deletions
+1
View File
@@ -178,6 +178,7 @@ export const createAgent = (
channelIdentityId: identity.channelIdentityId || identity.contactId || '',
displayName: identity.displayName || identity.contactName || 'User',
channel: currentChannel,
conversationType: identity.conversationType || 'direct',
date: new Date(),
attachments: files,
})
+1
View File
@@ -33,6 +33,7 @@ export const IdentityContextModel = z.object({
contactAlias: z.string().optional(),
userId: z.string().optional(),
currentPlatform: z.string().optional(),
conversationType: z.string().optional(),
replyTarget: z.string().optional(),
sessionToken: z.string().optional(),
})
+3 -1
View File
@@ -4,18 +4,20 @@ export interface UserParams {
channelIdentityId: string
displayName: string
channel: string
conversationType: string
date: Date
attachments: ContainerFileAttachment[]
}
export const user = (
query: string,
{ channelIdentityId, displayName, channel, date, attachments }: UserParams
{ channelIdentityId, displayName, channel, conversationType, date, attachments }: UserParams
) => {
const headers = {
'channel-identity-id': channelIdentityId,
'display-name': displayName,
'channel': channel,
'conversation-type': conversationType,
'time': date.toISOString(),
'attachments': attachments.map(attachment => attachment.path),
}
+1
View File
@@ -16,6 +16,7 @@ export interface IdentityContext {
userId?: string
currentPlatform?: string
conversationType?: string
replyTarget?: string
sessionToken?: string
}
+1
View File
@@ -207,6 +207,7 @@ CREATE TABLE IF NOT EXISTS bot_channel_routes (
channel_config_id UUID REFERENCES bot_channel_configs(id) ON DELETE SET NULL,
external_conversation_id TEXT NOT NULL,
external_thread_id TEXT,
conversation_type TEXT,
default_reply_target TEXT,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
@@ -0,0 +1,2 @@
-- 0002_channel_identity_avatar (down)
ALTER TABLE channel_identities DROP COLUMN IF EXISTS avatar_url;
@@ -0,0 +1,3 @@
-- 0002_channel_identity_avatar
-- Add avatar_url column to channel_identities for sender profile display.
ALTER TABLE channel_identities ADD COLUMN IF NOT EXISTS avatar_url TEXT;
@@ -0,0 +1,2 @@
-- 0003_route_conversation_type (down)
ALTER TABLE bot_channel_routes DROP COLUMN IF EXISTS conversation_type;
@@ -0,0 +1,3 @@
-- 0003_route_conversation_type
-- Add conversation_type column to bot_channel_routes for conversation context.
ALTER TABLE bot_channel_routes ADD COLUMN IF NOT EXISTS conversation_type TEXT;
+6 -1
View File
@@ -1,6 +1,6 @@
-- name: CreateChatRoute :one
INSERT INTO bot_channel_routes (
bot_id, channel_type, channel_config_id, external_conversation_id, external_thread_id, default_reply_target, metadata
bot_id, channel_type, channel_config_id, external_conversation_id, external_thread_id, conversation_type, default_reply_target, metadata
)
VALUES (
sqlc.arg(bot_id),
@@ -8,6 +8,7 @@ VALUES (
sqlc.narg(channel_config_id)::uuid,
sqlc.arg(conversation_id),
sqlc.narg(thread_id)::text,
sqlc.narg(conversation_type)::text,
sqlc.narg(reply_target)::text,
sqlc.arg(metadata)
)
@@ -19,6 +20,7 @@ RETURNING
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -33,6 +35,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -53,6 +56,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -69,6 +73,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
+1
View File
@@ -279,6 +279,7 @@ func (p *ChannelInboundProcessor) HandleInbound(ctx context.Context, cfg channel
RouteID: resolved.RouteID,
ChatToken: chatToken,
ExternalMessageID: sourceMessageID,
ConversationType: msg.Conversation.Type,
Query: text,
CurrentChannel: msg.Channel.String(),
Channels: []string{msg.Channel.String()},
+42 -71
View File
@@ -63,14 +63,15 @@ func (s *DBService) Create(ctx context.Context, input CreateInput) (Route, error
}
row, err := s.queries.CreateChatRoute(ctx, sqlc.CreateChatRouteParams{
ChatID: pgConversationID,
BotID: pgBotID,
Platform: input.Platform,
ChannelConfigID: pgConfigID,
ConversationID: input.ConversationID,
ThreadID: toPgText(input.ThreadID),
ReplyTarget: toPgText(input.ReplyTarget),
Metadata: metadata,
ChatID: pgConversationID,
BotID: pgBotID,
Platform: input.Platform,
ChannelConfigID: pgConfigID,
ConversationID: input.ConversationID,
ThreadID: toPgText(input.ThreadID),
ConversationType: toPgText(input.ConversationType),
ReplyTarget: toPgText(input.ReplyTarget),
Metadata: metadata,
})
if err != nil {
return Route{}, fmt.Errorf("create route: %w", err)
@@ -208,13 +209,14 @@ func (s *DBService) ResolveConversation(ctx context.Context, input ResolveInput)
}
newRoute, err := s.Create(ctx, CreateInput{
ChatID: createdConversation.ID,
BotID: input.BotID,
Platform: input.Platform,
ChannelConfigID: input.ChannelConfigID,
ConversationID: input.ConversationID,
ThreadID: input.ThreadID,
ReplyTarget: input.ReplyTarget,
ChatID: createdConversation.ID,
BotID: input.BotID,
Platform: input.Platform,
ChannelConfigID: input.ChannelConfigID,
ConversationID: input.ConversationID,
ThreadID: input.ThreadID,
ConversationType: input.ConversationType,
ReplyTarget: input.ReplyTarget,
})
if err != nil {
return ResolveConversationResult{}, fmt.Errorf("create route: %w", err)
@@ -260,81 +262,50 @@ func (s *DBService) resolveConversationCreatorChannelIdentityID(ctx context.Cont
func toRouteFromCreate(row sqlc.CreateChatRouteRow) Route {
return toRouteFields(
row.ID,
row.ChatID,
row.BotID,
row.Platform,
row.ChannelConfigID,
row.ConversationID,
row.ThreadID,
row.ReplyTarget,
row.Metadata,
row.CreatedAt,
row.UpdatedAt,
row.ID, row.ChatID, row.BotID, row.Platform, row.ChannelConfigID,
row.ConversationID, row.ThreadID, row.ConversationType, row.ReplyTarget,
row.Metadata, row.CreatedAt, row.UpdatedAt,
)
}
func toRouteFromFind(row sqlc.FindChatRouteRow) Route {
return toRouteFields(
row.ID,
row.ChatID,
row.BotID,
row.Platform,
row.ChannelConfigID,
row.ConversationID,
row.ThreadID,
row.ReplyTarget,
row.Metadata,
row.CreatedAt,
row.UpdatedAt,
row.ID, row.ChatID, row.BotID, row.Platform, row.ChannelConfigID,
row.ConversationID, row.ThreadID, row.ConversationType, row.ReplyTarget,
row.Metadata, row.CreatedAt, row.UpdatedAt,
)
}
func toRouteFromGet(row sqlc.GetChatRouteByIDRow) Route {
return toRouteFields(
row.ID,
row.ChatID,
row.BotID,
row.Platform,
row.ChannelConfigID,
row.ConversationID,
row.ThreadID,
row.ReplyTarget,
row.Metadata,
row.CreatedAt,
row.UpdatedAt,
row.ID, row.ChatID, row.BotID, row.Platform, row.ChannelConfigID,
row.ConversationID, row.ThreadID, row.ConversationType, row.ReplyTarget,
row.Metadata, row.CreatedAt, row.UpdatedAt,
)
}
func toRouteFromList(row sqlc.ListChatRoutesRow) Route {
return toRouteFields(
row.ID,
row.ChatID,
row.BotID,
row.Platform,
row.ChannelConfigID,
row.ConversationID,
row.ThreadID,
row.ReplyTarget,
row.Metadata,
row.CreatedAt,
row.UpdatedAt,
row.ID, row.ChatID, row.BotID, row.Platform, row.ChannelConfigID,
row.ConversationID, row.ThreadID, row.ConversationType, row.ReplyTarget,
row.Metadata, row.CreatedAt, row.UpdatedAt,
)
}
func toRouteFields(id, conversationID, botID pgtype.UUID, platform string, channelConfigID pgtype.UUID, externalConversationID string, threadID, replyTarget pgtype.Text, metadata []byte, createdAt, updatedAt pgtype.Timestamptz) Route {
func toRouteFields(id, conversationID, botID pgtype.UUID, platform string, channelConfigID pgtype.UUID, externalConversationID string, threadID, conversationType, replyTarget pgtype.Text, metadata []byte, createdAt, updatedAt pgtype.Timestamptz) Route {
return Route{
ID: id.String(),
ChatID: conversationID.String(),
BotID: botID.String(),
Platform: platform,
ChannelConfigID: channelConfigID.String(),
ConversationID: externalConversationID,
ThreadID: dbpkg.TextToString(threadID),
ReplyTarget: dbpkg.TextToString(replyTarget),
Metadata: parseJSONMap(metadata),
CreatedAt: createdAt.Time,
UpdatedAt: updatedAt.Time,
ID: id.String(),
ChatID: conversationID.String(),
BotID: botID.String(),
Platform: platform,
ChannelConfigID: channelConfigID.String(),
ConversationID: externalConversationID,
ThreadID: dbpkg.TextToString(threadID),
ConversationType: dbpkg.TextToString(conversationType),
ReplyTarget: dbpkg.TextToString(replyTarget),
Metadata: parseJSONMap(metadata),
CreatedAt: createdAt.Time,
UpdatedAt: updatedAt.Time,
}
}
+21 -19
View File
@@ -7,17 +7,18 @@ import (
// Route maps external channel conversations to an internal conversation.
type Route struct {
ID string `json:"id"`
ChatID string `json:"chat_id"`
BotID string `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID string `json:"channel_config_id,omitempty"`
ConversationID string `json:"conversation_id"`
ThreadID string `json:"thread_id,omitempty"`
ReplyTarget string `json:"reply_target,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ID string `json:"id"`
ChatID string `json:"chat_id"`
BotID string `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID string `json:"channel_config_id,omitempty"`
ConversationID string `json:"conversation_id"`
ThreadID string `json:"thread_id,omitempty"`
ConversationType string `json:"conversation_type,omitempty"`
ReplyTarget string `json:"reply_target,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// ResolveConversationResult is returned by ResolveConversation.
@@ -29,14 +30,15 @@ type ResolveConversationResult struct {
// CreateInput is the input for creating a route.
type CreateInput struct {
ChatID string
BotID string
Platform string
ChannelConfigID string
ConversationID string
ThreadID string
ReplyTarget string
Metadata map[string]any
ChatID string
BotID string
Platform string
ChannelConfigID string
ConversationID string
ThreadID string
ConversationType string
ReplyTarget string
Metadata map[string]any
}
// ResolveInput is the input for route-to-conversation resolution.
+2
View File
@@ -122,6 +122,7 @@ type gatewayIdentity struct {
ChannelIdentityID string `json:"channelIdentityId"`
DisplayName string `json:"displayName"`
CurrentPlatform string `json:"currentPlatform,omitempty"`
ConversationType string `json:"conversationType,omitempty"`
SessionToken string `json:"sessionToken,omitempty"`
}
@@ -270,6 +271,7 @@ func (r *Resolver) resolve(ctx context.Context, req conversation.ChatRequest) (r
ChannelIdentityID: strings.TrimSpace(req.SourceChannelIdentityID),
DisplayName: r.resolveDisplayName(ctx, req),
CurrentPlatform: req.CurrentChannel,
ConversationType: strings.TrimSpace(req.ConversationType),
SessionToken: req.ChatToken,
},
Attachments: []any{},
+1
View File
@@ -203,6 +203,7 @@ type ChatRequest struct {
RouteID string `json:"-"`
ChatToken string `json:"-"`
ExternalMessageID string `json:"-"`
ConversationType string `json:"-"`
UserMessagePersisted bool `json:"-"`
Query string `json:"query"`
+70 -55
View File
@@ -13,7 +13,7 @@ import (
const createChatRoute = `-- name: CreateChatRoute :one
INSERT INTO bot_channel_routes (
bot_id, channel_type, channel_config_id, external_conversation_id, external_thread_id, default_reply_target, metadata
bot_id, channel_type, channel_config_id, external_conversation_id, external_thread_id, conversation_type, default_reply_target, metadata
)
VALUES (
$1,
@@ -22,16 +22,18 @@ VALUES (
$4,
$5::text,
$6::text,
$7
$7::text,
$8
)
RETURNING
id,
$8::uuid AS chat_id,
$9::uuid AS chat_id,
bot_id,
channel_type AS platform,
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -39,28 +41,30 @@ RETURNING
`
type CreateChatRouteParams struct {
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
ChatID pgtype.UUID `json:"chat_id"`
}
type CreateChatRouteRow struct {
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) CreateChatRoute(ctx context.Context, arg CreateChatRouteParams) (CreateChatRouteRow, error) {
@@ -70,6 +74,7 @@ func (q *Queries) CreateChatRoute(ctx context.Context, arg CreateChatRouteParams
arg.ChannelConfigID,
arg.ConversationID,
arg.ThreadID,
arg.ConversationType,
arg.ReplyTarget,
arg.Metadata,
arg.ChatID,
@@ -83,6 +88,7 @@ func (q *Queries) CreateChatRoute(ctx context.Context, arg CreateChatRouteParams
&i.ChannelConfigID,
&i.ConversationID,
&i.ThreadID,
&i.ConversationType,
&i.ReplyTarget,
&i.Metadata,
&i.CreatedAt,
@@ -110,6 +116,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -130,17 +137,18 @@ type FindChatRouteParams struct {
}
type FindChatRouteRow struct {
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) FindChatRoute(ctx context.Context, arg FindChatRouteParams) (FindChatRouteRow, error) {
@@ -159,6 +167,7 @@ func (q *Queries) FindChatRoute(ctx context.Context, arg FindChatRouteParams) (F
&i.ChannelConfigID,
&i.ConversationID,
&i.ThreadID,
&i.ConversationType,
&i.ReplyTarget,
&i.Metadata,
&i.CreatedAt,
@@ -176,6 +185,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -185,17 +195,18 @@ WHERE id = $1
`
type GetChatRouteByIDRow struct {
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) GetChatRouteByID(ctx context.Context, id pgtype.UUID) (GetChatRouteByIDRow, error) {
@@ -209,6 +220,7 @@ func (q *Queries) GetChatRouteByID(ctx context.Context, id pgtype.UUID) (GetChat
&i.ChannelConfigID,
&i.ConversationID,
&i.ThreadID,
&i.ConversationType,
&i.ReplyTarget,
&i.Metadata,
&i.CreatedAt,
@@ -226,6 +238,7 @@ SELECT
channel_config_id,
external_conversation_id AS conversation_id,
external_thread_id AS thread_id,
conversation_type,
default_reply_target AS reply_target,
metadata,
created_at,
@@ -236,17 +249,18 @@ ORDER BY created_at ASC
`
type ListChatRoutesRow struct {
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
ChatID pgtype.UUID `json:"chat_id"`
BotID pgtype.UUID `json:"bot_id"`
Platform string `json:"platform"`
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ConversationID string `json:"conversation_id"`
ThreadID pgtype.Text `json:"thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
ReplyTarget pgtype.Text `json:"reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) ListChatRoutes(ctx context.Context, chatID pgtype.UUID) ([]ListChatRoutesRow, error) {
@@ -266,6 +280,7 @@ func (q *Queries) ListChatRoutes(ctx context.Context, chatID pgtype.UUID) ([]Lis
&i.ChannelConfigID,
&i.ConversationID,
&i.ThreadID,
&i.ConversationType,
&i.ReplyTarget,
&i.Metadata,
&i.CreatedAt,
+1
View File
@@ -49,6 +49,7 @@ type BotChannelRoute struct {
ChannelConfigID pgtype.UUID `json:"channel_config_id"`
ExternalConversationID string `json:"external_conversation_id"`
ExternalThreadID pgtype.Text `json:"external_thread_id"`
ConversationType pgtype.Text `json:"conversation_type"`
DefaultReplyTarget pgtype.Text `json:"default_reply_target"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
+12 -6
View File
@@ -98,6 +98,9 @@ func (h *MessageHandler) SendMessage(c echo.Context) error {
if strings.TrimSpace(req.CurrentChannel) == "" {
req.CurrentChannel = "web"
}
if strings.TrimSpace(req.ConversationType) == "" {
req.ConversationType = "direct"
}
if len(req.Channels) == 0 {
req.Channels = []string{req.CurrentChannel}
}
@@ -145,6 +148,9 @@ func (h *MessageHandler) StreamMessage(c echo.Context) error {
if strings.TrimSpace(req.CurrentChannel) == "" {
req.CurrentChannel = "web"
}
if strings.TrimSpace(req.ConversationType) == "" {
req.ConversationType = "direct"
}
if len(req.Channels) == 0 {
req.Channels = []string{req.CurrentChannel}
}
@@ -198,12 +204,12 @@ func (h *MessageHandler) StreamMessage(c echo.Context) error {
h.logger.Error("conversation stream failed", slog.Any("error", err))
if processingState == "started" {
processingState = "failed"
if writeErr := writeSSEJSON(writer, flusher, map[string]string{
"type": "processing_failed",
"error": err.Error(),
}); writeErr != nil {
h.logger.Warn("write SSE processing_failed event failed", slog.Any("error", writeErr))
}
if writeErr := writeSSEJSON(writer, flusher, map[string]string{
"type": "processing_failed",
"error": err.Error(),
}); writeErr != nil {
h.logger.Warn("write SSE processing_failed event failed", slog.Any("error", writeErr))
}
}
errData := map[string]string{
"type": "error",