mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-04 08:25:26 +08:00
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
154 lines
4.5 KiB
Go
154 lines
4.5 KiB
Go
package chat
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"ds2api/internal/auth"
|
|
"ds2api/internal/chathistory"
|
|
"ds2api/internal/httpapi/openai/files"
|
|
"ds2api/internal/httpapi/openai/history"
|
|
"ds2api/internal/httpapi/openai/shared"
|
|
"ds2api/internal/promptcompat"
|
|
"ds2api/internal/toolcall"
|
|
"ds2api/internal/toolstream"
|
|
)
|
|
|
|
const openAIGeneralMaxSize = shared.GeneralMaxSize
|
|
|
|
var writeJSON = shared.WriteJSON
|
|
|
|
type Handler struct {
|
|
Store shared.ConfigReader
|
|
Auth shared.AuthResolver
|
|
DS shared.DeepSeekCaller
|
|
ChatHistory *chathistory.Store
|
|
|
|
leaseMu sync.Mutex
|
|
streamLeases map[string]streamLease
|
|
}
|
|
|
|
type streamLease struct {
|
|
Auth *auth.RequestAuth
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
func (h *Handler) compatStripReferenceMarkers() bool {
|
|
if h == nil {
|
|
return true
|
|
}
|
|
return shared.CompatStripReferenceMarkers(h.Store)
|
|
}
|
|
|
|
func (h *Handler) applyCurrentInputFile(ctx context.Context, a *auth.RequestAuth, stdReq promptcompat.StandardRequest) (promptcompat.StandardRequest, error) {
|
|
if h == nil {
|
|
return stdReq, nil
|
|
}
|
|
stdReq = shared.ApplyThinkingInjection(h.Store, stdReq)
|
|
svc := history.Service{Store: h.Store, DS: h.DS}
|
|
out, err := svc.ApplyCurrentInputFile(ctx, a, stdReq)
|
|
if err != nil || out.CurrentInputFileApplied {
|
|
return out, err
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (h *Handler) preprocessInlineFileInputs(ctx context.Context, a *auth.RequestAuth, req map[string]any) error {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
return (&files.Handler{Store: h.Store, Auth: h.Auth, DS: h.DS, ChatHistory: h.ChatHistory}).PreprocessInlineFileInputs(ctx, a, req)
|
|
}
|
|
|
|
func (h *Handler) toolcallFeatureMatchEnabled() bool {
|
|
if h == nil {
|
|
return shared.ToolcallFeatureMatchEnabled(nil)
|
|
}
|
|
return shared.ToolcallFeatureMatchEnabled(h.Store)
|
|
}
|
|
|
|
func (h *Handler) toolcallEarlyEmitHighConfidence() bool {
|
|
if h == nil {
|
|
return shared.ToolcallEarlyEmitHighConfidence(nil)
|
|
}
|
|
return shared.ToolcallEarlyEmitHighConfidence(h.Store)
|
|
}
|
|
|
|
func writeOpenAIError(w http.ResponseWriter, status int, message string) {
|
|
shared.WriteOpenAIError(w, status, message)
|
|
}
|
|
|
|
func openAIErrorType(status int) string {
|
|
return shared.OpenAIErrorType(status)
|
|
}
|
|
|
|
func writeOpenAIInlineFileError(w http.ResponseWriter, err error) {
|
|
files.WriteInlineFileError(w, err)
|
|
}
|
|
|
|
func mapCurrentInputFileError(err error) (int, string) {
|
|
return history.MapError(err)
|
|
}
|
|
|
|
func requestTraceID(r *http.Request) string {
|
|
return shared.RequestTraceID(r)
|
|
}
|
|
|
|
func asString(v any) string {
|
|
return shared.AsString(v)
|
|
}
|
|
|
|
func cleanVisibleOutput(text string, stripReferenceMarkers bool) string {
|
|
return shared.CleanVisibleOutput(text, stripReferenceMarkers)
|
|
}
|
|
|
|
func replaceCitationMarkersWithLinks(text string, links map[int]string) string {
|
|
return shared.ReplaceCitationMarkersWithLinks(text, links)
|
|
}
|
|
|
|
func shouldWriteUpstreamEmptyOutputError(text string) bool {
|
|
return shared.ShouldWriteUpstreamEmptyOutputError(text)
|
|
}
|
|
|
|
func upstreamEmptyOutputDetail(contentFilter bool, text, thinking string) (int, string, string) {
|
|
return shared.UpstreamEmptyOutputDetail(contentFilter, text, thinking)
|
|
}
|
|
|
|
func writeUpstreamEmptyOutputError(w http.ResponseWriter, text, thinking string, contentFilter bool) bool {
|
|
return shared.WriteUpstreamEmptyOutputError(w, text, thinking, contentFilter)
|
|
}
|
|
|
|
func emptyOutputRetryEnabled() bool {
|
|
return shared.EmptyOutputRetryEnabled()
|
|
}
|
|
|
|
func emptyOutputRetryMaxAttempts() int {
|
|
return shared.EmptyOutputRetryMaxAttempts()
|
|
}
|
|
|
|
func clonePayloadForEmptyOutputRetry(payload map[string]any, parentMessageID int) map[string]any {
|
|
return shared.ClonePayloadForEmptyOutputRetry(payload, parentMessageID)
|
|
}
|
|
|
|
func usagePromptWithEmptyOutputRetry(originalPrompt string, retryAttempts int) string {
|
|
return shared.UsagePromptWithEmptyOutputRetry(originalPrompt, retryAttempts)
|
|
}
|
|
|
|
func formatIncrementalStreamToolCallDeltas(deltas []toolstream.ToolCallDelta, ids map[int]string) []map[string]any {
|
|
return shared.FormatIncrementalStreamToolCallDeltas(deltas, ids)
|
|
}
|
|
|
|
func filterIncrementalToolCallDeltasByAllowed(deltas []toolstream.ToolCallDelta, seenNames map[int]string) []toolstream.ToolCallDelta {
|
|
return shared.FilterIncrementalToolCallDeltasByAllowed(deltas, seenNames)
|
|
}
|
|
|
|
func formatFinalStreamToolCallsWithStableIDs(calls []toolcall.ParsedToolCall, ids map[int]string, toolsRaw any) []map[string]any {
|
|
return shared.FormatFinalStreamToolCallsWithStableIDs(calls, ids, toolsRaw)
|
|
}
|
|
|
|
func detectAssistantToolCalls(text, exposedThinking, detectionThinking string, toolNames []string) toolcall.ToolCallParseResult {
|
|
return shared.DetectAssistantToolCalls(text, exposedThinking, detectionThinking, toolNames)
|
|
}
|