Add wsl linter and fix

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-05-19 14:51:08 +04:00
parent eedfdcecc8
commit 9156d6a16a
882 changed files with 6068 additions and 574 deletions

View File

@@ -76,17 +76,21 @@ func NewProvider(apiKey string, opts ...Option) *Provider {
if cfg.httpClient != nil {
reqOpts = append(reqOpts, option.WithHTTPClient(cfg.httpClient))
}
if cfg.baseURL != "" {
reqOpts = append(reqOpts, option.WithBaseURL(cfg.baseURL))
}
if cfg.requestTimeout > 0 {
reqOpts = append(reqOpts, option.WithRequestTimeout(cfg.requestTimeout))
}
if cfg.maxRetries != nil {
reqOpts = append(reqOpts, option.WithMaxRetries(*cfg.maxRetries))
}
client := anthropic.NewClient(reqOpts...)
return &Provider{client: &client}
}
@@ -111,6 +115,7 @@ func (p *Provider) ChatCompletionStream(ctx context.Context, req *llm.ChatComple
}
stream := p.client.Messages.NewStreaming(ctx, params)
return &anthropicStream{stream: stream}, nil
}
@@ -134,37 +139,46 @@ func buildParams(req *llm.ChatCompletionRequest) (anthropic.MessageNewParams, er
for i, s := range system {
blocks[i] = anthropic.TextBlockParam{Text: s}
}
params.System = blocks
}
if req.Temperature != nil {
params.Temperature = param.NewOpt(*req.Temperature)
}
if req.TopP != nil {
params.TopP = param.NewOpt(*req.TopP)
}
if len(req.StopSequences) > 0 {
params.StopSequences = req.StopSequences
}
if len(req.Tools) > 0 {
params.Tools = buildTools(req.Tools)
}
if req.ToolChoice != nil {
params.ToolChoice = buildToolChoice(req.ToolChoice)
}
if req.Thinking != nil && req.Thinking.Enabled {
params.Thinking = anthropic.ThinkingConfigParamOfEnabled(int64(req.Thinking.BudgetTokens))
}
if req.ResponseFormat != nil {
switch req.ResponseFormat.Type {
case llm.ResponseFormatJSONSchema:
if req.ResponseFormat.JSONSchema == nil {
return anthropic.MessageNewParams{}, fmt.Errorf("cannot apply JSON schema output format: schema is nil")
}
var schema map[string]any
if err := json.Unmarshal(req.ResponseFormat.JSONSchema.Schema, &schema); err != nil {
return anthropic.MessageNewParams{}, fmt.Errorf("cannot unmarshal JSON schema for output format: %w", err)
}
params.OutputConfig = anthropic.OutputConfigParam{
Format: anthropic.JSONOutputFormatParam{Schema: schema},
}
@@ -186,6 +200,7 @@ func extractSystem(messages []llm.Message) (system []string, rest []llm.Message)
rest = append(rest, msg)
}
}
return
}
@@ -213,9 +228,11 @@ func buildMessages(messages []llm.Message) []anthropic.MessageParam {
blocks = append(blocks, buildFilePart(p))
}
}
out = append(out, anthropic.NewUserMessage(blocks...))
case llm.RoleAssistant:
var blocks []anthropic.ContentBlockParamUnion
for _, p := range msg.Parts {
switch part := p.(type) {
case llm.ThinkingPart:
@@ -226,13 +243,16 @@ func buildMessages(messages []llm.Message) []anthropic.MessageParam {
}
}
}
for _, tc := range msg.ToolCalls {
var input any
if err := json.Unmarshal([]byte(tc.Function.Arguments), &input); err != nil || input == nil {
input = map[string]any{}
}
blocks = append(blocks, anthropic.NewToolUseBlock(tc.ID, input, tc.Function.Name))
}
out = append(out, anthropic.NewAssistantMessage(blocks...))
case llm.RoleTool:
out = append(
@@ -264,6 +284,7 @@ func buildTools(tools []llm.Tool) []anthropic.ToolUnionParam {
if err := json.Unmarshal(t.Parameters, &schema); err == nil {
props := schema["properties"]
required, _ := schema["required"].([]any)
reqStrings := make([]string, 0, len(required))
for _, r := range required {
if s, ok := r.(string); ok {
@@ -272,6 +293,7 @@ func buildTools(tools []llm.Tool) []anthropic.ToolUnionParam {
}
extra := make(map[string]any)
for k, v := range schema {
switch k {
case "type", "properties", "required":
@@ -287,12 +309,14 @@ func buildTools(tools []llm.Tool) []anthropic.ToolUnionParam {
if len(extra) > 0 {
inputSchema.ExtraFields = extra
}
tool.InputSchema = inputSchema
}
}
out[i] = anthropic.ToolUnionParam{OfTool: &tool}
}
return out
}
@@ -392,13 +416,16 @@ func parseRetryAfter(resp *http.Response) time.Duration {
if resp == nil {
return 0
}
h := resp.Header.Get("Retry-After")
if h == "" {
return 0
}
if secs, err := strconv.Atoi(h); err == nil {
return time.Duration(secs) * time.Second
}
return 0
}
@@ -415,12 +442,14 @@ type anthropicStream struct {
func (s *anthropicStream) Next() bool {
for s.stream.Next() {
event := s.stream.Current()
mapped, ok := s.mapStreamEvent(&event)
if ok {
s.current = mapped
return true
}
}
return false
}
@@ -433,6 +462,7 @@ func (s *anthropicStream) Err() error {
if err != nil {
return mapError(err)
}
return nil
}
@@ -448,6 +478,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
case "tool_use":
s.inToolUse = true
tu := cb.AsToolUse()
return llm.ChatCompletionStreamEvent{
Delta: llm.MessageDelta{
ToolCalls: []llm.ToolCallDelta{{
@@ -460,6 +491,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
case "thinking":
return llm.ChatCompletionStreamEvent{}, false
}
return llm.ChatCompletionStreamEvent{}, false
case "content_block_delta":
@@ -475,6 +507,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
}, true
case "signature_delta":
s.thinkingSignature = delta.Signature
return llm.ChatCompletionStreamEvent{
Delta: llm.MessageDelta{ThinkingSignature: delta.Signature},
}, true
@@ -488,6 +521,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
},
}, true
}
return llm.ChatCompletionStreamEvent{}, false
case "content_block_stop":
@@ -495,10 +529,12 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
s.toolCallIndex++
s.inToolUse = false
}
return llm.ChatCompletionStreamEvent{}, false
case "message_delta":
fr := mapStopReason(anthropic.StopReason(event.Delta.StopReason))
evt := llm.ChatCompletionStreamEvent{
FinishReason: &fr,
}
@@ -508,6 +544,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
OutputTokens: int(event.Usage.OutputTokens),
}
}
return evt, true
case "message_start":
@@ -520,6 +557,7 @@ func (s *anthropicStream) mapStreamEvent(event *anthropic.MessageStreamEventUnio
OutputTokens: int(event.Message.Usage.OutputTokens),
}
}
return evt, true
default:
@@ -540,6 +578,7 @@ func buildFilePart(p llm.FilePart) anthropic.ContentBlockParamUnion {
if err != nil {
return anthropic.NewTextBlock(fmt.Sprintf("[file: %s, type: %s, error decoding content]", p.Filename, p.MimeType))
}
return anthropic.NewDocumentBlock(anthropic.PlainTextSourceParam{
Data: string(decoded),
})