Files
ds2api/internal/httpapi/openai/history/current_input_file.go
2026-04-30 01:24:53 +07:00

92 lines
2.7 KiB
Go

package history
import (
"context"
"errors"
"fmt"
"strings"
"ds2api/internal/auth"
dsclient "ds2api/internal/deepseek/client"
"ds2api/internal/httpapi/openai/shared"
"ds2api/internal/promptcompat"
)
const (
currentInputFilename = promptcompat.CurrentInputContextFilename
currentInputContentType = "text/plain; charset=utf-8"
currentInputPurpose = "assistants"
)
func (s Service) ApplyCurrentInputFile(ctx context.Context, a *auth.RequestAuth, stdReq promptcompat.StandardRequest) (promptcompat.StandardRequest, error) {
if s.DS == nil || s.Store == nil || a == nil || !s.Store.CurrentInputFileEnabled() {
return stdReq, nil
}
threshold := s.Store.CurrentInputFileMinChars()
index, text := latestUserInputForFile(stdReq.Messages)
if index < 0 {
return stdReq, nil
}
if len([]rune(text)) < threshold {
return stdReq, nil
}
fileText := promptcompat.BuildOpenAICurrentInputContextTranscript(stdReq.Messages)
if strings.TrimSpace(fileText) == "" {
return stdReq, errors.New("current user input file produced empty transcript")
}
result, err := s.DS.UploadFile(ctx, a, dsclient.UploadFileRequest{
Filename: currentInputFilename,
ContentType: currentInputContentType,
Purpose: currentInputPurpose,
Data: []byte(fileText),
}, 3)
if err != nil {
return stdReq, fmt.Errorf("upload current user input file: %w", err)
}
fileID := strings.TrimSpace(result.ID)
if fileID == "" {
return stdReq, errors.New("upload current user input file returned empty file id")
}
messages := []any{
map[string]any{
"role": "user",
"content": currentInputFilePrompt(),
},
}
stdReq.Messages = messages
stdReq.HistoryText = fileText
stdReq.CurrentInputFileApplied = true
stdReq.RefFileIDs = prependUniqueRefFileID(stdReq.RefFileIDs, fileID)
stdReq.FinalPrompt, stdReq.ToolNames = promptcompat.BuildOpenAIPrompt(messages, stdReq.ToolsRaw, "", stdReq.ToolChoice, stdReq.Thinking)
// Token accounting must reflect the actual downstream context:
// the uploaded history.txt file content + the neutral live prompt.
stdReq.PromptTokenText = fileText + "\n" + stdReq.FinalPrompt
return stdReq, nil
}
func latestUserInputForFile(messages []any) (int, string) {
for i := len(messages) - 1; i >= 0; i-- {
msg, ok := messages[i].(map[string]any)
if !ok {
continue
}
role := strings.ToLower(strings.TrimSpace(shared.AsString(msg["role"])))
if role != "user" {
continue
}
text := promptcompat.NormalizeOpenAIContentForPrompt(msg["content"])
if strings.TrimSpace(text) == "" {
return -1, ""
}
return i, text
}
return -1, ""
}
func currentInputFilePrompt() string {
return "The current request and prior conversation context have already been provided. Answer the latest user request directly."
}