fix(channel): Add welcome message configuration and update related processing logic
This commit is contained in:
parent
81e1a2d948
commit
43014cd36e
4 changed files with 67 additions and 12 deletions
|
|
@ -162,7 +162,8 @@
|
||||||
"webhook_host": "0.0.0.0",
|
"webhook_host": "0.0.0.0",
|
||||||
"webhook_port": 18791,
|
"webhook_port": 18791,
|
||||||
"webhook_path": "/webhook/wecom-aibot",
|
"webhook_path": "/webhook/wecom-aibot",
|
||||||
"max_steps": 10
|
"max_steps": 10,
|
||||||
|
"welcome_message": "Hello! I'm your AI assistant. How can I help you today?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"providers": {
|
"providers": {
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,9 @@ type WeComAIBotMessage struct {
|
||||||
} `json:"msg_item"`
|
} `json:"msg_item"`
|
||||||
} `json:"mixed,omitempty"`
|
} `json:"mixed,omitempty"`
|
||||||
// event field
|
// event field
|
||||||
Event string `json:"event,omitempty"`
|
Event *struct {
|
||||||
|
EventType string `json:"eventtype"`
|
||||||
|
} `json:"event,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WeComAIBotStreamResponse represents the streaming response format
|
// WeComAIBotStreamResponse represents the streaming response format
|
||||||
|
|
@ -423,7 +425,7 @@ func (c *WeComAIBotChannel) processMessage(ctx context.Context, msg WeComAIBotMe
|
||||||
}{
|
}{
|
||||||
ID: c.generateStreamID(),
|
ID: c.generateStreamID(),
|
||||||
Finish: true,
|
Finish: true,
|
||||||
Content: "暂不支持该消息类型",
|
Content: "Unsupported message type: " + msg.MsgType,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -545,6 +547,7 @@ func (c *WeComAIBotChannel) handleStreamMessage(ctx context.Context, msg WeComAI
|
||||||
|
|
||||||
// handleImageMessage handles image messages
|
// handleImageMessage handles image messages
|
||||||
func (c *WeComAIBotChannel) handleImageMessage(ctx context.Context, msg WeComAIBotMessage, timestamp, nonce string) string {
|
func (c *WeComAIBotChannel) handleImageMessage(ctx context.Context, msg WeComAIBotMessage, timestamp, nonce string) string {
|
||||||
|
logger.WarnC("wecom_aibot", "Image message type not yet fully implemented")
|
||||||
if msg.Image == nil {
|
if msg.Image == nil {
|
||||||
logger.ErrorC("wecom_aibot", "Image message missing image field")
|
logger.ErrorC("wecom_aibot", "Image message missing image field")
|
||||||
return c.encryptEmptyResponse(timestamp, nonce)
|
return c.encryptEmptyResponse(timestamp, nonce)
|
||||||
|
|
@ -553,7 +556,7 @@ func (c *WeComAIBotChannel) handleImageMessage(ctx context.Context, msg WeComAIB
|
||||||
imageURL := msg.Image.URL
|
imageURL := msg.Image.URL
|
||||||
|
|
||||||
// Download and decrypt image
|
// Download and decrypt image
|
||||||
imageData, err := c.downloadAndDecryptImage(ctx, imageURL)
|
_, err := c.downloadAndDecryptImage(ctx, imageURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorCF("wecom_aibot", "Failed to process image", map[string]any{
|
logger.ErrorCF("wecom_aibot", "Failed to process image", map[string]any{
|
||||||
"error": err,
|
"error": err,
|
||||||
|
|
@ -575,14 +578,35 @@ func (c *WeComAIBotChannel) handleImageMessage(ctx context.Context, msg WeComAIB
|
||||||
}{
|
}{
|
||||||
ID: c.generateStreamID(),
|
ID: c.generateStreamID(),
|
||||||
Finish: true,
|
Finish: true,
|
||||||
Content: fmt.Sprintf("图片处理失败: %v", err),
|
Content: fmt.Sprintf("Image received (URL: %s), but image messages are not yet supported", imageURL),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Echo back the image (simple demo behavior)
|
// Echo back the image (simple demo behavior)
|
||||||
streamID := c.generateStreamID()
|
// streamID := c.generateStreamID()
|
||||||
return c.encryptImageResponse(streamID, timestamp, nonce, imageData)
|
// return c.encryptImageResponse(streamID, timestamp, nonce, imageData)
|
||||||
|
|
||||||
|
// For now, just acknowledge receipt without echoing the image
|
||||||
|
return c.encryptResponse("", timestamp, nonce, WeComAIBotStreamResponse{
|
||||||
|
MsgType: "stream",
|
||||||
|
Stream: struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Finish bool `json:"finish"`
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
MsgItem []struct {
|
||||||
|
MsgType string `json:"msgtype"`
|
||||||
|
Image *struct {
|
||||||
|
Base64 string `json:"base64"`
|
||||||
|
MD5 string `json:"md5"`
|
||||||
|
} `json:"image,omitempty"`
|
||||||
|
} `json:"msg_item,omitempty"`
|
||||||
|
}{
|
||||||
|
ID: c.generateStreamID(),
|
||||||
|
Finish: true,
|
||||||
|
Content: fmt.Sprintf("Image received (URL: %s), but image messages are not yet supported", imageURL),
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleMixedMessage handles mixed (text + image) messages
|
// handleMixedMessage handles mixed (text + image) messages
|
||||||
|
|
@ -604,17 +628,45 @@ func (c *WeComAIBotChannel) handleMixedMessage(ctx context.Context, msg WeComAIB
|
||||||
}{
|
}{
|
||||||
ID: c.generateStreamID(),
|
ID: c.generateStreamID(),
|
||||||
Finish: true,
|
Finish: true,
|
||||||
Content: "暂不支持图文混排消息",
|
Content: "Mixed message type is not yet supported",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleEventMessage handles event messages
|
// handleEventMessage handles event messages
|
||||||
func (c *WeComAIBotChannel) handleEventMessage(ctx context.Context, msg WeComAIBotMessage, timestamp, nonce string) string {
|
func (c *WeComAIBotChannel) handleEventMessage(ctx context.Context, msg WeComAIBotMessage, timestamp, nonce string) string {
|
||||||
|
eventType := ""
|
||||||
|
if msg.Event != nil {
|
||||||
|
eventType = msg.Event.EventType
|
||||||
|
}
|
||||||
logger.DebugCF("wecom_aibot", "Received event", map[string]any{
|
logger.DebugCF("wecom_aibot", "Received event", map[string]any{
|
||||||
"event": msg.Event,
|
"event_type": eventType,
|
||||||
})
|
})
|
||||||
// Return empty response for events
|
|
||||||
|
// Send welcome message when user opens the chat window
|
||||||
|
if eventType == "enter_chat" && c.config.WelcomeMessage != "" {
|
||||||
|
streamID := c.generateStreamID()
|
||||||
|
return c.encryptResponse(streamID, timestamp, nonce, WeComAIBotStreamResponse{
|
||||||
|
MsgType: "stream",
|
||||||
|
Stream: struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Finish bool `json:"finish"`
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
MsgItem []struct {
|
||||||
|
MsgType string `json:"msgtype"`
|
||||||
|
Image *struct {
|
||||||
|
Base64 string `json:"base64"`
|
||||||
|
MD5 string `json:"md5"`
|
||||||
|
} `json:"image,omitempty"`
|
||||||
|
} `json:"msg_item,omitempty"`
|
||||||
|
}{
|
||||||
|
ID: streamID,
|
||||||
|
Finish: true,
|
||||||
|
Content: c.config.WelcomeMessage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return c.encryptEmptyResponse(timestamp, nonce)
|
return c.encryptEmptyResponse(timestamp, nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -862,7 +914,7 @@ func (c *WeComAIBotChannel) encryptMessage(plaintext, receiveid string) (string,
|
||||||
|
|
||||||
// Generate 16-byte random string
|
// Generate 16-byte random string
|
||||||
randomBytes := make([]byte, 16)
|
randomBytes := make([]byte, 16)
|
||||||
for i := 0; i < 16; i++ {
|
for i := range 16 {
|
||||||
n, err := rand.Int(rand.Reader, big.NewInt(10))
|
n, err := rand.Int(rand.Reader, big.NewInt(10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to generate random: %w", err)
|
return "", fmt.Errorf("failed to generate random: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -370,6 +370,7 @@ type WeComAIBotConfig struct {
|
||||||
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_ALLOW_FROM"`
|
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_ALLOW_FROM"`
|
||||||
ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_REPLY_TIMEOUT"`
|
ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_REPLY_TIMEOUT"`
|
||||||
MaxSteps int `json:"max_steps" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_MAX_STEPS"` // Maximum streaming steps
|
MaxSteps int `json:"max_steps" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_MAX_STEPS"` // Maximum streaming steps
|
||||||
|
WelcomeMessage string `json:"welcome_message" env:"PICOCLAW_CHANNELS_WECOM_AIBOT_WELCOME_MESSAGE"` // Sent on enter_chat event; empty = no welcome
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicoConfig struct {
|
type PicoConfig struct {
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ func DefaultConfig() *Config {
|
||||||
AllowFrom: FlexibleStringSlice{},
|
AllowFrom: FlexibleStringSlice{},
|
||||||
ReplyTimeout: 5,
|
ReplyTimeout: 5,
|
||||||
MaxSteps: 10,
|
MaxSteps: 10,
|
||||||
|
WelcomeMessage: "Hello! I'm your AI assistant. How can I help you today?",
|
||||||
},
|
},
|
||||||
Pico: PicoConfig{
|
Pico: PicoConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue