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 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,