Files
GovAI/server/pkg/dify/conversation.go
T
2026-06-15 23:48:37 +08:00

103 lines
3.0 KiB
Go

package dify
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"strings"
)
// ChatStream sends a chat message and returns a reader for SSE events.
// Caller is responsible for closing the returned io.ReadCloser.
func (c *Client) ChatStream(ctx context.Context, apiKey string, req *ChatRequest) (io.ReadCloser, error) {
req.ResponseMode = "streaming"
resp, err := c.do(ctx, "POST", "/chat-messages", apiKey, req)
if err != nil {
return nil, err
}
return resp.Body, nil
}
// ChatBlocking sends a chat message and waits for the complete response.
func (c *Client) ChatBlocking(ctx context.Context, apiKey string, req *ChatRequest) (*ChatStreamEvent, error) {
req.ResponseMode = "blocking"
var result ChatStreamEvent
if err := c.doJSON(ctx, "POST", "/chat-messages", apiKey, req, &result); err != nil {
return nil, err
}
return &result, nil
}
// ParseSSEStream parses a Dify SSE stream and calls handler for each event.
func ParseSSEStream(reader io.Reader, handler func(event ChatStreamEvent) error) error {
scanner := bufio.NewScanner(reader)
scanner.Buffer(make([]byte, 64*1024), 256*1024)
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "data: ") {
continue
}
data := strings.TrimPrefix(line, "data: ")
if data == "[DONE]" {
break
}
var event ChatStreamEvent
if err := json.Unmarshal([]byte(data), &event); err != nil {
continue
}
if err := handler(event); err != nil {
return err
}
}
return scanner.Err()
}
// ListConversations returns the user's conversation list for an app.
func (c *Client) ListConversations(ctx context.Context, apiKey, user string, limit int, firstID string) (*ConversationListResponse, error) {
path := fmt.Sprintf("/conversations?user=%s&limit=%d", user, limit)
if firstID != "" {
path += "&first_id=" + firstID
}
var result ConversationListResponse
if err := c.doJSON(ctx, "GET", path, apiKey, nil, &result); err != nil {
return nil, err
}
return &result, nil
}
// ListMessages returns messages in a conversation.
func (c *Client) ListMessages(ctx context.Context, apiKey, user, conversationID string, limit int, firstID string) (*MessageListResponse, error) {
path := fmt.Sprintf("/messages?user=%s&conversation_id=%s&limit=%d", user, conversationID, limit)
if firstID != "" {
path += "&first_id=" + firstID
}
var result MessageListResponse
if err := c.doJSON(ctx, "GET", path, apiKey, nil, &result); err != nil {
return nil, err
}
return &result, nil
}
// DeleteConversation deletes a conversation.
func (c *Client) DeleteConversation(ctx context.Context, apiKey, user, conversationID string) error {
body := map[string]string{"user": user}
return c.doJSON(ctx, "DELETE", "/conversations/"+conversationID, apiKey, body, nil)
}
// SubmitFeedback submits feedback for a message.
func (c *Client) SubmitFeedback(ctx context.Context, apiKey, messageID string, req *FeedbackRequest) error {
return c.doJSON(ctx, "POST", "/messages/"+messageID+"/feedbacks", apiKey, req, nil)
}