103 lines
3.0 KiB
Go
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)
|
|
}
|