From d02cfde952705402c5b905a46206db4fcd8f2e11 Mon Sep 17 00:00:00 2001 From: whllwsyh Date: Sun, 14 Jun 2026 05:23:52 +0800 Subject: [PATCH 1/2] feat(config): add GET /api/models/config-yaml/:name endpoint Adds a new REST endpoint that returns the raw YAML and parsed JSON view of an installed model config file. This is used by the MCP httpapi.Client for get_model_config, and by the React model editor when it wants a clean disk-read view (not the in-memory loader copy which has SetDefaults applied). - New GetConfigEndpoint in config_meta.go - Register route in routes/localai.go - Uses modeladmin.ConfigService.GetConfig for disk-read view Part of the split PR series discussed in #10317. --- core/http/endpoints/localai/config_meta.go | 30 ++++++++++++++++++++++ core/http/routes/localai.go | 4 +++ 2 files changed, 34 insertions(+) diff --git a/core/http/endpoints/localai/config_meta.go b/core/http/endpoints/localai/config_meta.go index 7456c7f60719..933a26730e2b 100644 --- a/core/http/endpoints/localai/config_meta.go +++ b/core/http/endpoints/localai/config_meta.go @@ -143,6 +143,36 @@ func AutocompleteEndpoint(cl *config.ModelConfigLoader, ml *model.ModelLoader, a } } +// GetConfigEndpoint returns the YAML + JSON view for an installed model. +// Used by the MCP httpapi.Client for get_model_config, and by the React +// model editor when it wants a clean disk-read view (not the in-memory +// loader copy which has SetDefaults applied). +// @Summary Read a model configuration from disk +// @Description Returns the raw YAML and parsed JSON view of an installed model's config file +// @Tags config +// @Produce json +// @Param name path string true "Model name" +// @Success 200 {object} map[string]any "{name, yaml, json}" +// @Router /api/models/config-yaml/{name} [get] +func GetConfigEndpoint(cl *config.ModelConfigLoader, appConfig *config.ApplicationConfig) echo.HandlerFunc { + svc := modeladmin.NewConfigService(cl, appConfig) + return func(c echo.Context) error { + modelName := c.Param("name") + if decoded, err := url.PathUnescape(modelName); err == nil { + modelName = decoded + } + view, err := svc.GetConfig(c.Request().Context(), modelName) + if err != nil { + return c.JSON(httpStatusForModelAdminError(err), map[string]any{"error": err.Error()}) + } + return c.JSON(http.StatusOK, map[string]any{ + "name": view.Name, + "yaml": view.YAML, + "json": view.JSON, + }) + } +} + // PatchConfigEndpoint handles PATCH requests to partially update a model config // using nested JSON merge. // @Summary Partially update a model configuration diff --git a/core/http/routes/localai.go b/core/http/routes/localai.go index 96baceaf8e44..d50eb8b4110d 100644 --- a/core/http/routes/localai.go +++ b/core/http/routes/localai.go @@ -92,6 +92,10 @@ func RegisterLocalAIRoutes(router *echo.Echo, router.POST("/models/reload", localai.ReloadModelsEndpoint(cl, appConfig), adminMiddleware) } + // JSON read-back of an installed model's YAML config (used by the + // standalone MCP server so it can call get_model_config over REST). + router.GET("/api/models/config-yaml/:name", localai.GetConfigEndpoint(cl, appConfig), adminMiddleware) + detectionHandler := localai.DetectionEndpoint(cl, ml, appConfig) router.POST("/v1/detection", detectionHandler, From 0a4f0d29fc7d9fdd9dd78913fd010681d78e388f Mon Sep 17 00:00:00 2001 From: ghshhf Date: Sun, 14 Jun 2026 05:45:41 +0800 Subject: [PATCH 2/2] fix(ci): skip security scan on forks to avoid SARIF upload permission error The Security Scan workflow was failing on fork PRs because the workflow does not have permission to upload SARIF files to the GitHub Security tab when running from a fork. This change adds '!github.repository.fork' checks to all steps to prevent the workflow from running on fork repositories. Fixes #10318 --- .github/workflows/secscan.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/secscan.yaml b/.github/workflows/secscan.yaml index bb381567baa5..c09f30867db8 100644 --- a/.github/workflows/secscan.yaml +++ b/.github/workflows/secscan.yaml @@ -15,15 +15,15 @@ jobs: steps: - name: Checkout Source uses: actions/checkout@v6 - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} - name: Run Gosec Security Scanner - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} uses: securego/gosec@v2.27.1 with: # we let the report trigger content trigger a failure using the GitHub Security features. args: '-no-fail -fmt sarif -out results.sarif ./...' - name: Upload SARIF file - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} uses: github/codeql-action/upload-sarif@v4 with: # Path to SARIF file relative to the root of the repository