Relaxed CLI requirements when defaults are specified in the profile or application defaults
This commit is contained in:
@@ -40,11 +40,11 @@ type OpenAICompatibleClient struct {
|
||||
}
|
||||
|
||||
func NewOpenAICompatibleClient(cfg OpenAICompatibleConfig) (*OpenAICompatibleClient, error) {
|
||||
if strings.TrimSpace(cfg.BaseURL) == "" {
|
||||
return nil, fmt.Errorf("%w: base URL is required", ErrInvalidConfig)
|
||||
}
|
||||
if _, err := url.ParseRequestURI(cfg.BaseURL); err != nil {
|
||||
return nil, fmt.Errorf("%w: invalid base URL: %v", ErrInvalidConfig, err)
|
||||
baseURL := strings.TrimSpace(cfg.BaseURL)
|
||||
if baseURL != "" {
|
||||
if _, err := url.ParseRequestURI(baseURL); err != nil {
|
||||
return nil, fmt.Errorf("%w: invalid base URL: %v", ErrInvalidConfig, err)
|
||||
}
|
||||
}
|
||||
|
||||
timeout := cfg.Timeout
|
||||
@@ -63,7 +63,7 @@ func NewOpenAICompatibleClient(cfg OpenAICompatibleConfig) (*OpenAICompatibleCli
|
||||
}
|
||||
|
||||
return &OpenAICompatibleClient{
|
||||
baseURL: strings.TrimRight(cfg.BaseURL, "/"),
|
||||
baseURL: strings.TrimRight(baseURL, "/"),
|
||||
apiKey: cfg.APIKey,
|
||||
defaultModel: cfg.Model,
|
||||
timeout: timeout,
|
||||
@@ -88,6 +88,9 @@ func (c *OpenAICompatibleClient) Generate(ctx context.Context, req domain.Genera
|
||||
if endpoint == "" {
|
||||
endpoint = c.baseURL
|
||||
}
|
||||
if endpoint == "" {
|
||||
return nil, fmt.Errorf("%w: endpoint is required", ErrInvalidRequest)
|
||||
}
|
||||
endpoint = strings.TrimRight(endpoint, "/") + "/chat/completions"
|
||||
|
||||
wireReq := openAIChatRequest{
|
||||
|
||||
@@ -336,3 +336,45 @@ func TestOpenAICompatibleClientNegativeTimeoutRejected(t *testing.T) {
|
||||
t.Fatalf("expected ErrInvalidRequest, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleClientAllowsEmptyConfiguredBaseURL(t *testing.T) {
|
||||
client, err := NewOpenAICompatibleClient(OpenAICompatibleConfig{
|
||||
BaseURL: "",
|
||||
Model: "m",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("expected empty configured base URL to be allowed, got %v", err)
|
||||
}
|
||||
|
||||
_, err = client.Generate(context.Background(), domain.GenerateRequest{
|
||||
Prompt: domain.RenderedPrompt{Messages: []domain.RenderedMessage{{Role: "user", Content: "hi"}}},
|
||||
Target: domain.ModelTarget{Endpoint: "http://localhost:9999/v1"},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected request failure due to unreachable endpoint")
|
||||
}
|
||||
if !errors.Is(err, ErrRequestFailed) {
|
||||
t.Fatalf("expected ErrRequestFailed with request endpoint override, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleClientRequiresEndpointWhenUnsetEverywhere(t *testing.T) {
|
||||
client, err := NewOpenAICompatibleClient(OpenAICompatibleConfig{
|
||||
BaseURL: "",
|
||||
Model: "m",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = client.Generate(context.Background(), domain.GenerateRequest{
|
||||
Prompt: domain.RenderedPrompt{Messages: []domain.RenderedMessage{{Role: "user", Content: "hi"}}},
|
||||
Target: domain.ModelTarget{},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected endpoint-required error")
|
||||
}
|
||||
if !errors.Is(err, ErrInvalidRequest) {
|
||||
t.Fatalf("expected ErrInvalidRequest, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user