thread-master/apps/backend/internal/module/ai/client.go

48 lines
1.5 KiB
Go
Raw Permalink Normal View History

2026-07-13 01:15:30 +00:00
package ai
import (
"context"
"fmt"
"strings"
)
// Client is AI provider transport (real HTTP or fake).
type Client interface {
Complete(ctx context.Context, apiKey, model, prompt string) (string, error)
// CompleteStream 串流 deltaonDelta 可為 nil。回傳完整正文。
CompleteStream(ctx context.Context, apiKey, model, prompt string, onDelta func(chunk string) error) (string, error)
ListModels(ctx context.Context, apiKey string) ([]string, error)
}
// FakeClient for tests / when no real key path needed.
type FakeClient struct {
Fail bool
Models []string
}
func (f *FakeClient) Complete(ctx context.Context, apiKey, model, prompt string) (string, error) {
if f.Fail || apiKey == "" {
return "", fmt.Errorf("ai call failed: no key or forced fail")
}
_ = SystemPromptForLanguage(ResponseLanguageFrom(ctx)) // ensure always defined for real clients
if len(prompt) > 200 {
prompt = prompt[:200]
}
return fmt.Sprintf("[%s] %s", model, strings.TrimSpace(prompt)), nil
}
func (f *FakeClient) ListModels(_ context.Context, apiKey string) ([]string, error) {
if f.Fail || apiKey == "" {
return nil, fmt.Errorf("list models failed: no key or forced fail")
}
if len(f.Models) > 0 {
return append([]string(nil), f.Models...), nil
}
return []string{"grok-3", "grok-2", "grok-beta"}, nil
}
// ModelsForProvider — static catalog (fallback when live list fails).
func ModelsForProvider(provider string) []string {
return FallbackModels(provider)
}