This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git


The following commit(s) were added to refs/heads/master by this push:
     new f614bad  fix(agent): offer an agent every model its provider serves
f614bad is described below

commit f614badf524496dd1c80a483fbc0a9d0756e977c
Author: Yang Luo <[email protected]>
AuthorDate: Sun Aug 30 23:50:28 2026 +0800

    fix(agent): offer an agent every model its provider serves
---
 agentprovider/dsh.go          |  6 +++++-
 agentprovider/opencode.go     |  6 +++++-
 agentprovider/provider.go     | 25 +++++++++++++++++++++++--
 controllers/agent_provider.go |  1 +
 4 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/agentprovider/dsh.go b/agentprovider/dsh.go
index 62bc2b1..ab594d6 100644
--- a/agentprovider/dsh.go
+++ b/agentprovider/dsh.go
@@ -284,12 +284,16 @@ func (dshWriter) check(endpoint Endpoint) error {
 // route is the llm-pi-ai profile Gateway writes. dsh ships no catalog for this
 // route, so the profile carries the whole provider: protocol, endpoint, 
models.
 func (dshWriter) route(endpoint Endpoint) dshRouteConfig {
+       models := []dshRouteModel{}
+       for _, model := range endpoint.catalog() {
+               models = append(models, dshRouteModel{Id: model})
+       }
        return dshRouteConfig{
                DisplayName: "Casbin Gateway",
                ApiKeyEnv:   dshCredentialRef,
                Api:         dshProtocol,
                BaseURL:     endpoint.BaseUrl,
-               Models:      []dshRouteModel{{Id: endpoint.Model}},
+               Models:      models,
        }
 }
 
diff --git a/agentprovider/opencode.go b/agentprovider/opencode.go
index cb182c0..f7807f2 100644
--- a/agentprovider/opencode.go
+++ b/agentprovider/opencode.go
@@ -203,6 +203,10 @@ func (opencodeWriter) check(endpoint Endpoint) error {
 // catalog for a provider it does not know, so the entry carries the whole of
 // it: the SDK package, the endpoint, the key and the models.
 func (opencodeWriter) provider(endpoint Endpoint) map[string]any {
+       models := map[string]any{}
+       for _, model := range endpoint.catalog() {
+               models[model] = map[string]any{"name": model}
+       }
        return map[string]any{
                "name": "Casbin Gateway",
                "npm":  opencodeNpm,
@@ -210,7 +214,7 @@ func (opencodeWriter) provider(endpoint Endpoint) 
map[string]any {
                        "baseURL": endpoint.BaseUrl,
                        "apiKey":  endpoint.ApiKey,
                },
-               "models": map[string]any{endpoint.Model: map[string]any{"name": 
endpoint.Model}},
+               "models": models,
        }
 }
 
diff --git a/agentprovider/provider.go b/agentprovider/provider.go
index 451f4c4..0f899c8 100644
--- a/agentprovider/provider.go
+++ b/agentprovider/provider.go
@@ -52,8 +52,13 @@ type Endpoint struct {
        Protocol string `json:"protocol"`
        BaseUrl  string `json:"baseUrl"`
        ApiKey   string `json:"apiKey"`
-       Model    string `json:"model"`
-       Mode     string `json:"mode"`
+       // Model is the one the agent starts on, the first the provider lists.
+       Model string `json:"model"`
+       // Models is every model the provider serves. An agent whose 
configuration
+       // carries the catalog itself is written all of them, so its own picker 
can
+       // switch between them without Gateway writing the file again.
+       Models []string `json:"models"`
+       Mode   string   `json:"mode"`
        // ServesResponsesApi reports whether BaseUrl answers on the OpenAI 
Responses
        // API, which is all Codex speaks. The gateway always does, since it
        // translates; a provider's own upstream usually stops at chat 
completions.
@@ -310,6 +315,22 @@ func pointsAtGateway(value writer, target Target) bool {
        return err == nil && strings.Contains(current, "/v1/agents/")
 }
 
+// catalog is the models to write into an agent that carries its own list. The
+// bound default comes first, and a duplicate is dropped so the agent's picker
+// does not show one twice.
+func (endpoint Endpoint) catalog() []string {
+       models := []string{}
+       seen := map[string]bool{}
+       for _, model := range append([]string{endpoint.Model}, 
endpoint.Models...) {
+               if model == "" || seen[model] {
+                       continue
+               }
+               seen[model] = true
+               models = append(models, model)
+       }
+       return models
+}
+
 func emptyAs(value string, fallback string) string {
        if value == "" {
                return fallback
diff --git a/controllers/agent_provider.go b/controllers/agent_provider.go
index 575f2d3..db46ec4 100644
--- a/controllers/agent_provider.go
+++ b/controllers/agent_provider.go
@@ -160,6 +160,7 @@ func agentEndpoint(agentId string) (agentprovider.Endpoint, 
error) {
        endpoint.Protocol = object.ProviderProtocol(provider)
        if len(provider.Models) > 0 {
                endpoint.Model = provider.Models[0]
+               endpoint.Models = provider.Models
        }
 
        if endpoint.Mode == object.ModeDirect {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to