mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
feat(web,api): provider selection and model form foundation (#2831)
* feat: improve model configuration workflows
Add model catalog browsing, provider registry with form validation,
model fetch/test dialogs, and enhanced model management UI.
- Add model catalog API and catalog-dialog component for browsing saved models
- Add provider-registry with auto-populated form fields per provider
- Add provider-combobox, fetch-models-dialog, test-model-dialog components
- Add model-validation for provider-aware model ID validation
- Add command and popover UI components
- Enhance edit-model-sheet with tool schema transform support
- Add anthropic to protocolMetaByName for correct default API base
- Apply NormalizeBaseURL to anthropic provider for consistent URL handling
- Add i18n keys for new model management features (en/zh)
* fix(web): prevent auto-fetch when API key is missing in fetch models dialog
When a provider requires an API key but none is set, the dialog now shows
the warning without triggering a doomed fetch attempt. Fetch is deferred
until the user provides a key.
* fix(web): add credential warning for catalog imports from remote providers
When importing models from a catalog entry whose provider requires an API
key, a yellow warning banner now informs users that credentials will need
to be configured after import.
* feat(web,api): test connection with real connectivity verification and unsaved form values
Add POST /api/models/test-inline endpoint that performs actual network
probes (GET /models) instead of just checking config. Frontend Test
Connection now uses current form values (not saved state) and is
available in both Add and Edit model flows.
* style(web): apply linter formatting across model config components
Normalize quote style, import ordering, and class name ordering as
reported by the project linter.
* fix(web,api): fix edit test connection false negative and gate fetch for unsupported providers
- handleTestInlineModel now accepts optional model_index to fall back to stored credentials when api_key is empty, fixing false negatives when testing edited models
- Add supportsFetch to provider registry and FETCHABLE_PROVIDER_KEYS derived set
- Gate Fetch Models button to only show for OpenAI-compatible and Ollama providers
- Add backend guard in handleFetchModels to reject unsupported providers with clear error
* fix: address review feedback on model config workflow
- Send explicit {} for empty extra_body/custom_headers fields so the
backend clears stored values instead of preserving them
- Merge backend provider_options with frontend PROVIDERS registry so
the provider picker reflects backend-supported providers and policy
fields (create_allowed, default_auth_method, auth_method_locked)
- Render provider combobox popover inside the sheet scroll container
to fix wheel events scrolling the sheet instead of the provider list
* feat(web,api): add provider selection, model form foundation, and validation
Split from PR #2752 (part 1 of 3).
Backend:
- CRUD model endpoints (list/add/update/delete/set-default)
- Provider metadata with default API bases and model provider options
- Model ID validation and normalization
- Anthropic default API base normalization
Frontend:
- Provider registry with metadata, labels, icons, and aliases
- Provider combobox with backend option merging
- Model field validation with provider-aware checks
- Redesigned add/edit model sheets with provider selection
- Dynamic imports for fetch/catalog/test dialogs (coming in PR2/PR3)
- i18n support for model configuration UI
This commit is contained in:
@@ -747,6 +747,21 @@ func (c *ModelConfig) Validate() error {
|
||||
if _, err := providercommon.NormalizeToolSchemaTransform(c.ToolSchemaTransform); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reject whitespace in model identifier
|
||||
if strings.ContainsAny(c.Model, " \t\n\r") {
|
||||
return fmt.Errorf("model identifier contains whitespace")
|
||||
}
|
||||
|
||||
// Reject leading slash
|
||||
if strings.HasPrefix(c.Model, "/") {
|
||||
return fmt.Errorf("model identifier must not start with /")
|
||||
}
|
||||
|
||||
// Reject consecutive slashes
|
||||
if strings.Contains(c.Model, "//") {
|
||||
return fmt.Errorf("model identifier must not contain //")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
anthropicmessages "github.com/sipeed/picoclaw/pkg/providers/anthropic_messages"
|
||||
"github.com/sipeed/picoclaw/pkg/providers/azure"
|
||||
"github.com/sipeed/picoclaw/pkg/providers/bedrock"
|
||||
"github.com/sipeed/picoclaw/pkg/providers/common"
|
||||
)
|
||||
|
||||
type protocolMeta struct {
|
||||
@@ -60,6 +61,8 @@ var protocolMetaByName = map[string]protocolMeta{
|
||||
"longcat": {defaultAPIBase: "https://api.longcat.chat/openai"},
|
||||
"modelscope": {defaultAPIBase: "https://api-inference.modelscope.cn/v1"},
|
||||
"mimo": {defaultAPIBase: "https://api.xiaomimimo.com/v1"},
|
||||
"anthropic": {defaultAPIBase: "https://api.anthropic.com/v1"},
|
||||
"anthropic-messages": {defaultAPIBase: "https://api.anthropic.com/v1"},
|
||||
}
|
||||
|
||||
// createClaudeAuthProvider creates a Claude provider using OAuth credentials from auth store.
|
||||
@@ -318,10 +321,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
|
||||
return finalizeProviderFromConfig(provider, modelID, cfg)
|
||||
}
|
||||
// Use API key with HTTP API
|
||||
apiBase := cfg.APIBase
|
||||
if apiBase == "" {
|
||||
apiBase = "https://api.anthropic.com/v1"
|
||||
}
|
||||
apiBase := common.NormalizeBaseURL(cfg.APIBase, "https://api.anthropic.com/v1", true)
|
||||
if cfg.APIKey() == "" {
|
||||
return nil, "", fmt.Errorf("api_key is required for anthropic protocol (model: %s)", cfg.Model)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user