From 79f0e5ece8966014a860521ca77bb43a2e406ac6 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Thu, 16 Apr 2026 07:47:48 -0700 Subject: [PATCH 1/8] Use Nanobot's new config format + model provider dialects (#6246) * Write .nanobot/nanobot.yaml llmProviders * Simplify docker volume/container inits with runInitContainer * Update some naming to make it clear it is MCP config only * Use Nanobot types when building config * Dynamically build the nanobot.yaml for selected model * Derive Dialect from provider meta * Fix name shadowing * Update go.mod using remote branch * Generate * Fix default proxy for ChatCompletions and add tests * Fix provider config reload with symbolic link * Improve function naming * Improve function naming and other minor changes * Improve ensureCredentials refresh logic * Add Dialect to ModelManifest * regenerate * Always run link for docker * Revert use of nanobottypes * PR comments * Move all config setup to nanobotagent.go * fix boolean condition per copilot comment * Fix error retry check --- apiclient/types/model.go | 1 + apiclient/types/modelprovider.go | 3 + go.mod | 2 + go.sum | 4 +- pkg/api/handlers/nanobotagent.go | 3 +- .../handlers/nanobotagent/nanobotagent.go | 224 +++++++++++++--- .../nanobotagent/nanobotagent_test.go | 249 +++++++++++++++++- .../handlers/toolreference/toolreference.go | 9 + pkg/mcp/backend.go | 14 +- pkg/mcp/docker.go | 180 +++++-------- pkg/mcp/kubernetes.go | 9 +- .../openapi/generated/openapi_generated.go | 13 + 12 files changed, 538 insertions(+), 173 deletions(-) diff --git a/apiclient/types/model.go b/apiclient/types/model.go index 4f21f46b29..3fa8412f66 100644 --- a/apiclient/types/model.go +++ b/apiclient/types/model.go @@ -14,6 +14,7 @@ type ModelManifest struct { Alias string `json:"alias,omitempty"` Active bool `json:"active"` Usage ModelUsage `json:"usage"` + Dialect string `json:"dialect,omitempty"` } type ModelList List[Model] diff --git a/apiclient/types/modelprovider.go b/apiclient/types/modelprovider.go index 0c58695662..29f093cd89 100644 --- a/apiclient/types/modelprovider.go +++ b/apiclient/types/modelprovider.go @@ -5,6 +5,9 @@ type CommonProviderMetadata struct { IconDark string `json:"iconDark,omitempty"` Description string `json:"description,omitempty"` Link string `json:"link,omitempty"` + // Dialect specifies the LLM API format used by this provider + // (e.g. "AnthropicMessages", "OpenAIChatCompletions", "OpenAIResponses"). + Dialect string `json:"dialect,omitempty"` } type CommonProviderStatus struct { diff --git a/go.mod b/go.mod index 8a00c362e1..cfd692e013 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ replace ( github.com/obot-platform/obot/logger => ./logger ) +replace github.com/nanobot-ai/nanobot => github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c + require ( cloud.google.com/go/storage v1.43.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 diff --git a/go.sum b/go.sum index 48e01c0d81..389585bc08 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,8 @@ github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/bombsimon/logrusr/v4 v4.1.0 h1:uZNPbwusB0eUXlO8hIUwStE6Lr5bLN6IgYgG+75kuh4= github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8= +github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c h1:0XulKTIDELtp3KS+nIqub+rOJ5bve1LOhFewzE218Gg= +github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c/go.mod h1:6Yi07gQdKON69TMEIVIkPjuNL7R+Iyy6kJ3CUck5Qeg= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -546,8 +548,6 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nanobot-ai/nanobot v0.0.68 h1:N3OcLEqHMQ/F9CdSM77UDAPtViMPprDxwib6LzkIf9w= -github.com/nanobot-ai/nanobot v0.0.68/go.mod h1:QRUCktmw9QyBxt9YR2PKyfnh9R1/OcqOigfND5Dreuw= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= diff --git a/pkg/api/handlers/nanobotagent.go b/pkg/api/handlers/nanobotagent.go index 53d42dfc59..a470dd0513 100644 --- a/pkg/api/handlers/nanobotagent.go +++ b/pkg/api/handlers/nanobotagent.go @@ -211,7 +211,8 @@ func (h *NanobotAgentHandler) Launch(req api.Context) error { break } var errHTTP *types.ErrHTTP - if !errors.As(err, &errHTTP) || errHTTP.Code != http.StatusBadRequest || !strings.Contains(errHTTP.Message, "NANOBOT_ENV_FILE") { + if !errors.As(err, &errHTTP) || errHTTP.Code != http.StatusBadRequest || + (!strings.Contains(errHTTP.Message, "NANOBOT_ENV_FILE") && !strings.Contains(errHTTP.Message, "NANOBOT_CONFIG_PATH")) { return err } select { diff --git a/pkg/controller/handlers/nanobotagent/nanobotagent.go b/pkg/controller/handlers/nanobotagent/nanobotagent.go index e2c9244461..6be01fcbfc 100644 --- a/pkg/controller/handlers/nanobotagent/nanobotagent.go +++ b/pkg/controller/handlers/nanobotagent/nanobotagent.go @@ -11,6 +11,7 @@ import ( "time" "github.com/gptscript-ai/go-gptscript" + nanobottypes "github.com/nanobot-ai/nanobot/pkg/types" "github.com/obot-platform/nah/pkg/backend" "github.com/obot-platform/nah/pkg/name" "github.com/obot-platform/nah/pkg/router" @@ -27,6 +28,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kclient "sigs.k8s.io/controller-runtime/pkg/client" + sigsyaml "sigs.k8s.io/yaml" ) const ( @@ -110,6 +112,17 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro File: true, DynamicFile: true, }, + { + MCPHeader: types.MCPHeader{ + Name: "NANOBOT_CONFIG_PATH", + Description: "Provider config YAML for Nanobot", + Key: "NANOBOT_CONFIG_PATH", + Sensitive: true, + Required: true, + }, + File: true, + DynamicFile: true, + }, } currentArgs := existing.Spec.Manifest.ContainerizedConfig.Args @@ -124,7 +137,7 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro } } - if len(existing.Spec.Manifest.Env) != len(expectedEnv) || existing.Spec.Manifest.Env[0] != expectedEnv[0] { + if !slices.Equal(existing.Spec.Manifest.Env, expectedEnv) { needsUpdate = true } @@ -149,7 +162,7 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro } // Create new MCPServer - args := []string{"run"} + args := []string{"run", "--state", ".nanobot/state/nanobot.db"} if agent.Spec.DefaultAgent != "" { args = append(args, "--agent", agent.Spec.DefaultAgent) } @@ -186,6 +199,17 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro File: true, DynamicFile: true, }, + { + MCPHeader: types.MCPHeader{ + Name: "NANOBOT_CONFIG_PATH", + Description: "Provider config YAML for Nanobot", + Key: "NANOBOT_CONFIG_PATH", + Sensitive: true, + Required: true, + }, + File: true, + DynamicFile: true, + }, }, }, }, @@ -209,6 +233,23 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, resp router.Response, agent *v1.NanobotAgent, mcpServerName string) error { credCtx := fmt.Sprintf("%s-%s", agent.Spec.UserID, mcpServerName) + llmModel, err := resolveModel(ctx, req.Client, req.Namespace, types.DefaultModelAliasTypeLLM) + if err != nil { + return err + } + llmProvider, llmDefault := h.parseModelProvider(llmModel) + + miniModel, err := resolveModel(ctx, req.Client, req.Namespace, types.DefaultModelAliasTypeLLMMini) + if err != nil { + return err + } + miniProvider, miniDefault := h.parseModelProvider(miniModel) + + providerYAML, err := buildNanobotProviderConfigYAML(llmProvider, miniProvider) + if err != nil { + return fmt.Errorf("failed to build nanobot provider config: %w", err) + } + // Check if credential exists and if the token needs refreshing var needsRefresh bool cred, err := h.gptClient.RevealCredential(ctx, []string{credCtx}, mcpServerName) @@ -222,8 +263,11 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res needsRefresh = true log.Debugf("Nanobot credential missing, creating: agent=%s mcpServer=%s", agent.Name, mcpServerName) } else { - // Credential exists, check if token needs refreshing - if token := credEnvFileVars["OPENAI_API_KEY"]; token != "" { + // Credential exists, check if token needs refreshing. + // Use the configured provider's API key env var to find the token. + llmEnvVarName := strings.TrimSuffix(strings.TrimPrefix(llmProvider.APIKey, "${"), "}") + token := credEnvFileVars[llmEnvVarName] + if token != "" { tokenCtx, err := h.tokenService.DecodeToken(ctx, token) if err != nil { // Token is invalid, needs refresh @@ -247,21 +291,15 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res } } - llmModel, err := resolveModel(ctx, req.Client, req.Namespace, types.DefaultModelAliasTypeLLM) - if err != nil { - return err - } - miniModel, err := resolveModel(ctx, req.Client, req.Namespace, types.DefaultModelAliasTypeLLMMini) - if err != nil { - return err - } - - if !needsRefresh && credEnvFileVars["NANOBOT_DEFAULT_MODEL"] == llmModel && credEnvFileVars["NANOBOT_DEFAULT_MINI_MODEL"] == miniModel { + if !needsRefresh && + credEnvFileVars["NANOBOT_DEFAULT_MODEL"] == llmDefault && + credEnvFileVars["NANOBOT_DEFAULT_MINI_MODEL"] == miniDefault && + cred.Env["NANOBOT_CONFIG_PATH"] == providerYAML { // Credentials are up to date return nil } - log.Debugf("Refreshing nanobot credentials: agent=%s mcpServer=%s model=%s miniModel=%s", agent.Name, mcpServerName, llmModel, miniModel) + log.Debugf("Refreshing nanobot credentials: agent=%s mcpServer=%s model=%s miniModel=%s", agent.Name, mcpServerName, llmDefault, miniDefault) // Generate a new token that expires in 12 hours now := time.Now() @@ -313,26 +351,34 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res return fmt.Errorf("failed to create API key: %w", err) } - // Create or update the credential with the new token and API key + envFileLines := []string{ + fmt.Sprintf("OBOT_URL=%s", h.serverURL), + fmt.Sprintf("MCP_API_KEY=%s", apiKeyResp.Key), + fmt.Sprintf("MCP_API_KEY_ID=%d", apiKeyResp.ID), + fmt.Sprintf("MCP_API_KEY_ID_PREV=%s", credEnvFileVars["MCP_API_KEY_ID"]), + fmt.Sprintf("MCP_SERVER_SEARCH_URL=%s", system.MCPConnectURL(h.serverURL, system.ObotMCPServerName)), + fmt.Sprintf("MCP_SERVER_SEARCH_API_KEY=%s", apiKeyResp.Key), + fmt.Sprintf("NANOBOT_DEFAULT_MODEL=%s", llmDefault), + fmt.Sprintf("NANOBOT_DEFAULT_MINI_MODEL=%s", miniDefault), + } + seenProviders := make(map[string]struct{}, 2) + for _, p := range []nanobotLLMProvider{llmProvider, miniProvider} { + if _, ok := seenProviders[p.Name]; ok { + continue + } + seenProviders[p.Name] = struct{}{} + envVarName := strings.TrimSuffix(strings.TrimPrefix(p.APIKey, "${"), "}") + envFileLines = append(envFileLines, fmt.Sprintf("%s=%s", envVarName, token)) + } + + // Create or update the credential with the new token, API key, and provider config. if err := h.gptClient.CreateCredential(ctx, gptscript.Credential{ Context: credCtx, ToolName: mcpServerName, Type: gptscript.CredentialTypeTool, Env: map[string]string{ - "NANOBOT_ENV_FILE": strings.Join([]string{ - fmt.Sprintf("OBOT_URL=%s", h.serverURL), - fmt.Sprintf("ANTHROPIC_BASE_URL=%s/api/llm-proxy/anthropic", h.serverURL), - fmt.Sprintf("OPENAI_BASE_URL=%s/api/llm-proxy/openai", h.serverURL), - fmt.Sprintf("ANTHROPIC_API_KEY=%s", token), - fmt.Sprintf("OPENAI_API_KEY=%s", token), - fmt.Sprintf("MCP_API_KEY=%s", apiKeyResp.Key), - fmt.Sprintf("MCP_API_KEY_ID=%d", apiKeyResp.ID), - fmt.Sprintf("MCP_API_KEY_ID_PREV=%s", credEnvFileVars["MCP_API_KEY_ID"]), - fmt.Sprintf("MCP_SERVER_SEARCH_URL=%s", system.MCPConnectURL(h.serverURL, system.ObotMCPServerName)), - fmt.Sprintf("MCP_SERVER_SEARCH_API_KEY=%s", apiKeyResp.Key), - fmt.Sprintf("NANOBOT_DEFAULT_MODEL=%s", llmModel), - fmt.Sprintf("NANOBOT_DEFAULT_MINI_MODEL=%s", miniModel), - }, "\n"), + "NANOBOT_ENV_FILE": strings.Join(envFileLines, "\n"), + "NANOBOT_CONFIG_PATH": providerYAML, }, }); err != nil { return fmt.Errorf("failed to create credential: %w", err) @@ -355,26 +401,110 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res return nil } -func getModelForAlias(ctx context.Context, client kclient.Client, namespace string, aliasName types.DefaultModelAliasType) (string, error) { +// resolvedLLMModel pairs the resolved target model name with its configured provider reference +// and the dialect declared by that provider (if any). +type resolvedLLMModel struct { + TargetModel string + ModelProvider string // e.g. "openai-model-provider", "anthropic-model-provider" + ProviderDialect nanobottypes.Dialect // from ProviderMeta.Dialect; empty if not declared +} + +// nanobotLLMProvider describes how a single LLM provider should be configured in nanobot's YAML. +type nanobotLLMProvider struct { + Name string // key in llmProviders map (e.g. "openai", "anthropic") + Dialect nanobottypes.Dialect + APIKey string // env var reference derived from Name, e.g. "${OPENAI_MODEL_PROVIDER_API_KEY}" + BaseURL string // actual Obot proxy URL +} + +// parseModelProvider returns the nanobot provider config and the fully-qualified +// model name (provider/model) for a resolved model. +// +// If the provider has declared a dialect via ProviderMeta.Dialect, that dialect +// is used and the base URL is derived from it. Otherwise the known built-in +// providers (openai, anthropic) supply both; everything else falls back to +// OpenResponses via the generic /api/llm-proxy dispatch. +func (h *Handler) parseModelProvider(model resolvedLLMModel) (nanobotLLMProvider, string) { + name := model.ModelProvider + envVarName := strings.ToUpper(strings.ReplaceAll(name, "-", "_")) + "_API_KEY" + + dialect := model.ProviderDialect + if dialect == "" { + // No declared dialect — fall back to per-provider defaults. + switch model.ModelProvider { + case system.AnthropicModelProviderTool: + dialect = nanobottypes.DialectAnthropicMessages + case system.OpenAIModelProviderTool: + dialect = nanobottypes.DialectOpenAIResponses + default: + dialect = nanobottypes.DialectOpenResponses + } + } + + var baseURL string + switch dialect { + case nanobottypes.DialectAnthropicMessages: + baseURL = h.serverURL + "/api/llm-proxy/anthropic" + case nanobottypes.DialectOpenAIResponses: + baseURL = h.serverURL + "/api/llm-proxy/openai" + default: + baseURL = h.serverURL + "/api/llm-proxy" + } + + p := nanobotLLMProvider{ + Name: name, + Dialect: dialect, + APIKey: fmt.Sprintf("${%s}", envVarName), + BaseURL: baseURL, + } + return p, fmt.Sprintf("%s/%s", p.Name, model.TargetModel) +} + +// buildNanobotProviderConfigYAML generates a nanobot Config YAML containing only the +// providers required by the given LLM and mini-LLM models. +func buildNanobotProviderConfigYAML(providers ...nanobotLLMProvider) (string, error) { + llmProviders := make(map[string]nanobottypes.LLMProvider, len(providers)) + for _, p := range providers { + if _, exists := llmProviders[p.Name]; exists { + continue + } + llmProviders[p.Name] = nanobottypes.LLMProvider{ + Dialect: p.Dialect, + APIKey: p.APIKey, + BaseURL: p.BaseURL, + } + } + data, err := sigsyaml.Marshal(nanobottypes.Config{LLMProviders: llmProviders}) + if err != nil { + return "", err + } + return string(data), nil +} + +func getModelForAlias(ctx context.Context, client kclient.Client, namespace string, aliasName types.DefaultModelAliasType) (resolvedLLMModel, error) { llmModel, err := alias.GetFromScope(ctx, client, "Model", namespace, string(aliasName)) if err != nil { - return "", fmt.Errorf("failed to get default model alias %v: %w", aliasName, err) + return resolvedLLMModel{}, fmt.Errorf("failed to get default model alias %v: %w", aliasName, err) } modelAlias, ok := llmModel.(*v1.DefaultModelAlias) if !ok { - return "", fmt.Errorf("alias %v is not of type Alias", aliasName) + return resolvedLLMModel{}, fmt.Errorf("alias %v is not of type Alias", aliasName) } var model v1.Model if err := alias.Get(ctx, client, &model, namespace, modelAlias.Spec.Manifest.Model); err != nil { - return "", err + return resolvedLLMModel{}, err } - return model.Spec.Manifest.TargetModel, nil + return resolvedLLMModel{ + TargetModel: model.Spec.Manifest.TargetModel, + ModelProvider: model.Spec.Manifest.ModelProvider, + ProviderDialect: nanobottypes.Dialect(model.Spec.Manifest.Dialect), + }, nil } -// resolveModel returns a concrete model name for a default alias. +// resolveModel returns a resolved model and its provider for a default alias. // // It prefers an explicitly configured alias target when one exists. If the // alias is unset or cannot be resolved, it falls back to active LLM models in @@ -382,14 +512,14 @@ func getModelForAlias(ctx context.Context, client kclient.Client, namespace stri // for that alias. The llm-mini alias falls back to the resolved llm model when // no preferred mini model is available. All other aliases fall back to the // first active LLM model available. -func resolveModel(ctx context.Context, client kclient.Client, namespace string, aliasName types.DefaultModelAliasType) (string, error) { - if model, err := getModelForAlias(ctx, client, namespace, aliasName); err == nil && strings.TrimSpace(model) != "" { +func resolveModel(ctx context.Context, client kclient.Client, namespace string, aliasName types.DefaultModelAliasType) (resolvedLLMModel, error) { + if model, err := getModelForAlias(ctx, client, namespace, aliasName); err == nil && strings.TrimSpace(model.TargetModel) != "" { return model, nil } models, err := listActiveLLMModels(ctx, client, namespace) if err != nil { - return "", err + return resolvedLLMModel{}, err } return chooseModel(ctx, client, namespace, models, aliasName) @@ -422,12 +552,16 @@ func listActiveLLMModels(ctx context.Context, client kclient.Client, namespace s return result, nil } -func chooseModel(ctx context.Context, client kclient.Client, namespace string, models []v1.Model, aliasName types.DefaultModelAliasType) (string, error) { +func chooseModel(ctx context.Context, client kclient.Client, namespace string, models []v1.Model, aliasName types.DefaultModelAliasType) (resolvedLLMModel, error) { preferred := preferredModelsForAlias(aliasName) for _, preferredName := range preferred { for _, model := range models { if model.Spec.Manifest.TargetModel == preferredName || model.Spec.Manifest.Name == preferredName { - return model.Spec.Manifest.TargetModel, nil + return resolvedLLMModel{ + TargetModel: model.Spec.Manifest.TargetModel, + ModelProvider: model.Spec.Manifest.ModelProvider, + ProviderDialect: nanobottypes.Dialect(model.Spec.Manifest.Dialect), + }, nil } } } @@ -437,10 +571,14 @@ func chooseModel(ctx context.Context, client kclient.Client, namespace string, m } if len(models) > 0 { - return models[0].Spec.Manifest.TargetModel, nil + return resolvedLLMModel{ + TargetModel: models[0].Spec.Manifest.TargetModel, + ModelProvider: models[0].Spec.Manifest.ModelProvider, + ProviderDialect: nanobottypes.Dialect(models[0].Spec.Manifest.Dialect), + }, nil } - return "", fmt.Errorf("failed to resolve default model for alias %s: no active llm models available", aliasName) + return resolvedLLMModel{}, fmt.Errorf("failed to resolve default model for alias %s: no active llm models available", aliasName) } func preferredModelsForAlias(aliasName types.DefaultModelAliasType) []string { diff --git a/pkg/controller/handlers/nanobotagent/nanobotagent_test.go b/pkg/controller/handlers/nanobotagent/nanobotagent_test.go index 17a12f66eb..fc25a9d0b9 100644 --- a/pkg/controller/handlers/nanobotagent/nanobotagent_test.go +++ b/pkg/controller/handlers/nanobotagent/nanobotagent_test.go @@ -4,11 +4,14 @@ import ( "context" "testing" + nanobottypes "github.com/nanobot-ai/nanobot/pkg/types" "github.com/obot-platform/obot/apiclient/types" v1 "github.com/obot-platform/obot/pkg/storage/apis/obot.obot.ai/v1" storagescheme "github.com/obot-platform/obot/pkg/storage/scheme" + "github.com/obot-platform/obot/pkg/system" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client/fake" + sigsyaml "sigs.k8s.io/yaml" ) func TestChooseModelPrefersKnownNames(t *testing.T) { @@ -40,8 +43,8 @@ func TestChooseModelPrefersKnownNames(t *testing.T) { t.Fatalf("expected model, got error: %v", err) } - if model != "gpt-5.4" { - t.Fatalf("expected gpt-5.4, got %q", model) + if model.TargetModel != "gpt-5.4" { + t.Fatalf("expected gpt-5.4, got %q", model.TargetModel) } } @@ -64,8 +67,8 @@ func TestChooseModelFallsBackToFirstActiveModel(t *testing.T) { t.Fatalf("expected model, got error: %v", err) } - if model != "model-a" { - t.Fatalf("expected model-a, got %q", model) + if model.TargetModel != "model-a" { + t.Fatalf("expected model-a, got %q", model.TargetModel) } } @@ -98,8 +101,238 @@ func TestChooseModelPrefersSuggestedOrder(t *testing.T) { t.Fatalf("expected model, got error: %v", err) } - if model != "gpt-5.4" { - t.Fatalf("expected gpt-5.4, got %q", model) + if model.TargetModel != "gpt-5.4" { + t.Fatalf("expected gpt-5.4, got %q", model.TargetModel) + } +} + +func TestNanobotParseModelProviderDeclaredDialectDrivesURL(t *testing.T) { + h := &Handler{serverURL: "https://obot.example.com"} + + for _, tc := range []struct { + dialect nanobottypes.Dialect + wantBaseURL string + }{ + {nanobottypes.DialectAnthropicMessages, "https://obot.example.com/api/llm-proxy/anthropic"}, + {nanobottypes.DialectOpenAIResponses, "https://obot.example.com/api/llm-proxy/openai"}, + {nanobottypes.DialectOpenAIChatCompletions, "https://obot.example.com/api/llm-proxy"}, + {nanobottypes.DialectOpenResponses, "https://obot.example.com/api/llm-proxy"}, + } { + model := resolvedLLMModel{ + TargetModel: "some-model", + ModelProvider: "custom-model-provider", + ProviderDialect: tc.dialect, + } + p, _ := h.parseModelProvider(model) + if p.BaseURL != tc.wantBaseURL { + t.Errorf("dialect %s: baseURL = %q, want %q", tc.dialect, p.BaseURL, tc.wantBaseURL) + } + if p.Dialect != tc.dialect { + t.Errorf("dialect %s: provider dialect = %q, want same", tc.dialect, p.Dialect) + } + } +} + +func TestNanobotParseModelProviderBuiltinFallbacks(t *testing.T) { + h := &Handler{serverURL: "https://obot.example.com"} + + for _, tc := range []struct { + modelProvider string + wantDialect nanobottypes.Dialect + wantBaseURL string + }{ + {system.OpenAIModelProviderTool, nanobottypes.DialectOpenAIResponses, "https://obot.example.com/api/llm-proxy/openai"}, + {system.AnthropicModelProviderTool, nanobottypes.DialectAnthropicMessages, "https://obot.example.com/api/llm-proxy/anthropic"}, + {"unknown-model-provider", nanobottypes.DialectOpenResponses, "https://obot.example.com/api/llm-proxy"}, + } { + model := resolvedLLMModel{TargetModel: "my-model", ModelProvider: tc.modelProvider} + p, qualifiedName := h.parseModelProvider(model) + if p.Dialect != tc.wantDialect { + t.Errorf("%s: dialect = %q, want %q", tc.modelProvider, p.Dialect, tc.wantDialect) + } + if p.BaseURL != tc.wantBaseURL { + t.Errorf("%s: baseURL = %q, want %q", tc.modelProvider, p.BaseURL, tc.wantBaseURL) + } + wantName := tc.modelProvider + "/my-model" + if qualifiedName != wantName { + t.Errorf("%s: qualified name = %q, want %q", tc.modelProvider, qualifiedName, wantName) + } + } +} + +func TestBuildNanobotProviderConfigYAMLSingleProvider(t *testing.T) { + p := nanobotLLMProvider{ + Name: "openai-model-provider", + Dialect: nanobottypes.DialectOpenAIResponses, + APIKey: "${OPENAI_MODEL_PROVIDER_API_KEY}", + BaseURL: "https://obot.example.com/api/llm-proxy/openai", + } + + yaml, err := buildNanobotProviderConfigYAML(p) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var cfg nanobottypes.Config + if err := sigsyaml.Unmarshal([]byte(yaml), &cfg); err != nil { + t.Fatalf("failed to parse output YAML: %v", err) + } + + if len(cfg.LLMProviders) != 1 { + t.Fatalf("expected 1 provider, got %d", len(cfg.LLMProviders)) + } + got := cfg.LLMProviders["openai-model-provider"] + if got.Dialect != nanobottypes.DialectOpenAIResponses { + t.Errorf("dialect = %q, want OpenAIResponses", got.Dialect) + } + if got.BaseURL != p.BaseURL { + t.Errorf("baseURL = %q, want %q", got.BaseURL, p.BaseURL) + } +} + +func TestBuildNanobotProviderConfigYAMLMultipleProviders(t *testing.T) { + openai := nanobotLLMProvider{ + Name: "openai-model-provider", + Dialect: nanobottypes.DialectOpenAIResponses, + APIKey: "${OPENAI_MODEL_PROVIDER_API_KEY}", + BaseURL: "https://obot.example.com/api/llm-proxy/openai", + } + anthropic := nanobotLLMProvider{ + Name: "anthropic-model-provider", + Dialect: nanobottypes.DialectAnthropicMessages, + APIKey: "${ANTHROPIC_MODEL_PROVIDER_API_KEY}", + BaseURL: "https://obot.example.com/api/llm-proxy/anthropic", + } + + yaml, err := buildNanobotProviderConfigYAML(openai, anthropic) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var cfg nanobottypes.Config + if err := sigsyaml.Unmarshal([]byte(yaml), &cfg); err != nil { + t.Fatalf("failed to parse output YAML: %v", err) + } + + if len(cfg.LLMProviders) != 2 { + t.Fatalf("expected 2 providers, got %d: %v", len(cfg.LLMProviders), cfg.LLMProviders) + } + if cfg.LLMProviders["openai-model-provider"].Dialect != nanobottypes.DialectOpenAIResponses { + t.Errorf("openai dialect = %q, want OpenAIResponses", cfg.LLMProviders["openai-model-provider"].Dialect) + } + if cfg.LLMProviders["anthropic-model-provider"].Dialect != nanobottypes.DialectAnthropicMessages { + t.Errorf("anthropic dialect = %q, want AnthropicMessages", cfg.LLMProviders["anthropic-model-provider"].Dialect) + } +} + +func TestBuildNanobotProviderConfigYAMLDeduplicates(t *testing.T) { + p := nanobotLLMProvider{ + Name: "openai-model-provider", + Dialect: nanobottypes.DialectOpenAIResponses, + APIKey: "${OPENAI_MODEL_PROVIDER_API_KEY}", + BaseURL: "https://obot.example.com/api/llm-proxy/openai", + } + + yaml, err := buildNanobotProviderConfigYAML(p, p) // same provider twice + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var cfg nanobottypes.Config + if err := sigsyaml.Unmarshal([]byte(yaml), &cfg); err != nil { + t.Fatalf("failed to parse output YAML: %v", err) + } + + if len(cfg.LLMProviders) != 1 { + t.Errorf("expected deduplication to 1 provider, got %d", len(cfg.LLMProviders)) + } +} + +func TestResolveModelCarriesProviderAndDialect(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(storagescheme.Scheme). + WithObjects( + &v1.DefaultModelAlias{ + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "DefaultModelAlias"}, + ObjectMeta: metav1.ObjectMeta{Name: "llm"}, + Spec: v1.DefaultModelAliasSpec{ + Manifest: types.DefaultModelAliasManifest{Alias: "llm", Model: "groq-llama"}, + }, + }, + &v1.Model{ + TypeMeta: metav1.TypeMeta{APIVersion: v1.SchemeGroupVersion.String(), Kind: "Model"}, + ObjectMeta: metav1.ObjectMeta{Name: "groq-llama"}, + Spec: v1.ModelSpec{ + Manifest: types.ModelManifest{ + Name: "groq-llama", + TargetModel: "llama-3.1-70b-versatile", + ModelProvider: "groq-model-provider", + Active: true, + Usage: types.ModelUsageLLM, + Dialect: string(nanobottypes.DialectOpenAIChatCompletions), + }, + }, + }, + ).Build() + + model, err := resolveModel(context.Background(), c, "", types.DefaultModelAliasTypeLLM) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if model.TargetModel != "llama-3.1-70b-versatile" { + t.Errorf("TargetModel = %q, want llama-3.1-70b-versatile", model.TargetModel) + } + if model.ModelProvider != "groq-model-provider" { + t.Errorf("ModelProvider = %q, want groq-model-provider", model.ModelProvider) + } + if model.ProviderDialect != nanobottypes.DialectOpenAIChatCompletions { + t.Errorf("ProviderDialect = %q, want OpenAIChatCompletions", model.ProviderDialect) + } +} + +// TestMultipleProvidersWhenLLMAndMiniDiffer verifies that when the default LLM and +// mini-LLM models are on different providers, both providers appear in the generated +// nanobot config YAML. +func TestMultipleProvidersWhenLLMAndMiniDiffer(t *testing.T) { + h := &Handler{serverURL: "https://obot.example.com"} + + llmModel := resolvedLLMModel{ + TargetModel: "claude-sonnet-4-6", + ModelProvider: system.AnthropicModelProviderTool, + } + miniModel := resolvedLLMModel{ + TargetModel: "gpt-4.1-mini", + ModelProvider: system.OpenAIModelProviderTool, + } + + llmProvider, llmDefault := h.parseModelProvider(llmModel) + miniProvider, miniDefault := h.parseModelProvider(miniModel) + + if llmDefault != system.AnthropicModelProviderTool+"/claude-sonnet-4-6" { + t.Errorf("llmDefault = %q, want %s/claude-sonnet-4-6", llmDefault, system.AnthropicModelProviderTool) + } + if miniDefault != system.OpenAIModelProviderTool+"/gpt-4.1-mini" { + t.Errorf("miniDefault = %q, want %s/gpt-4.1-mini", miniDefault, system.OpenAIModelProviderTool) + } + + yaml, err := buildNanobotProviderConfigYAML(llmProvider, miniProvider) + if err != nil { + t.Fatalf("buildNanobotProviderConfigYAML: %v", err) + } + + var cfg nanobottypes.Config + if err := sigsyaml.Unmarshal([]byte(yaml), &cfg); err != nil { + t.Fatalf("failed to parse output YAML: %v", err) + } + + if len(cfg.LLMProviders) != 2 { + t.Fatalf("expected 2 providers (one per model), got %d:\n%s", len(cfg.LLMProviders), yaml) + } + if _, ok := cfg.LLMProviders[system.AnthropicModelProviderTool]; !ok { + t.Errorf("anthropic-model-provider missing from YAML") + } + if _, ok := cfg.LLMProviders[system.OpenAIModelProviderTool]; !ok { + t.Errorf("openai-model-provider missing from YAML") } } @@ -160,7 +393,7 @@ func TestChooseModelMiniFallsBackToResolvedLLM(t *testing.T) { t.Fatalf("expected model, got error: %v", err) } - if model != "gpt-5.4" { - t.Fatalf("expected gpt-5.4, got %q", model) + if model.TargetModel != "gpt-5.4" { + t.Fatalf("expected gpt-5.4, got %q", model.TargetModel) } } diff --git a/pkg/controller/handlers/toolreference/toolreference.go b/pkg/controller/handlers/toolreference/toolreference.go index ad1b832a99..84b105f925 100644 --- a/pkg/controller/handlers/toolreference/toolreference.go +++ b/pkg/controller/handlers/toolreference/toolreference.go @@ -416,6 +416,14 @@ func (h *Handler) BackPopulateModels(req router.Request, _ router.Response) erro } } + var dialect string + if toolRef.Status.Tool != nil && toolRef.Status.Tool.Metadata["providerMeta"] != "" { + var meta types.CommonProviderMetadata + if err := json.Unmarshal([]byte(toolRef.Status.Tool.Metadata["providerMeta"]), &meta); err == nil { + dialect = meta.Dialect + } + } + availableModels, err := h.dispatcher.ModelsForProvider(req.Ctx, h.gptClient, req.Namespace, req.Name) if err != nil { // Don't error and retry because it will likely fail again. Log the error, and the user can re-sync manually. @@ -470,6 +478,7 @@ func (h *Handler) BackPopulateModels(req router.Request, _ router.Response) erro ModelProvider: toolRef.Name, Active: true, Usage: types.ModelUsage(model.Metadata["usage"]), + Dialect: dialect, }, }, }) diff --git a/pkg/mcp/backend.go b/pkg/mcp/backend.go index a822458e2b..aa2bb5f56b 100644 --- a/pkg/mcp/backend.go +++ b/pkg/mcp/backend.go @@ -174,7 +174,7 @@ func ensureServerReady(ctx context.Context, url string, server ServerConfig) err } } -func constructNanobotYAMLForCompositeServer(servers []ComponentServer) ([]byte, error) { +func constructMCPServerNanobotYAMLForComposite(servers []ComponentServer) ([]byte, error) { mcpServers := make(map[string]nanobotConfigMCPServer, len(servers)) names := make([]string, 0, len(servers)) replacer := strings.NewReplacer("/", "-", ":", "-", "?", "-") @@ -215,22 +215,22 @@ func constructNanobotYAMLForCompositeServer(servers []ComponentServer) ([]byte, return data, nil } -func constructNanobotYAMLForServer(name, url, command string, args []string, env, headers map[string][]byte, webhooks []Webhook) ([]byte, error) { +func constructMCPServerNanobotYAML(name, url, command string, args []string, env, headers map[string][]byte, webhooks []Webhook) ([]byte, error) { replacer := strings.NewReplacer("/", "-", ":", "-", "?", "-") webhookDefinitions := make(map[string][]string, len(webhooks)) mcpServers := make(map[string]nanobotConfigMCPServer, len(webhooks)+1) for _, webhook := range webhooks { - name := replacer.Replace(webhook.DisplayName) - if name == "" { - name = replacer.Replace(webhook.Name) + webhookName := replacer.Replace(webhook.DisplayName) + if webhookName == "" { + webhookName = replacer.Replace(webhook.Name) } - mcpServers[name] = nanobotConfigMCPServer{ + mcpServers[webhookName] = nanobotConfigMCPServer{ BaseURL: webhook.URL, } for _, def := range webhook.Definitions { - webhookDefinitions[def] = append(webhookDefinitions[def], fmt.Sprintf("%s/%s", name, webhookToolName)) + webhookDefinitions[def] = append(webhookDefinitions[def], fmt.Sprintf("%s/%s", webhookName, webhookToolName)) } } diff --git a/pkg/mcp/docker.go b/pkg/mcp/docker.go index 39a130e827..847e22e0d1 100644 --- a/pkg/mcp/docker.go +++ b/pkg/mcp/docker.go @@ -874,10 +874,9 @@ func (d *dockerBackend) createAndStartContainer(ctx context.Context, server Serv containerPort = defaultContainerPort - // Prepare nanobot configuration - nanobotVolumeName, err := d.prepareNanobotConfig(ctx, server, fileEnvVars, webhooks) + nanobotVolumeName, err := d.prepareMCPServerNanobotConfig(ctx, server, fileEnvVars, webhooks) if err != nil { - return "", 0, fmt.Errorf("failed to prepare nanobot config: %w", err) + return "", 0, fmt.Errorf("failed to prepare MCP server nanobot config: %w", err) } volumeMounts = append(volumeMounts, mount.Mount{ @@ -1183,6 +1182,56 @@ func (d *dockerBackend) createVolumeWithFiles(ctx context.Context, files []File, return volumeName, envVars, nil } +// runInitContainer pulls alpine:latest (if not present), runs a one-shot sh -c container +// with the given script and mounts, waits for it to exit, and returns any error. +func (d *dockerBackend) runInitContainer(ctx context.Context, namePrefix, script string, mounts []mount.Mount) error { + initImage := "alpine:latest" + if err := d.pullImage(ctx, initImage, true); err != nil { + return fmt.Errorf("failed to ensure init image exists: %w", err) + } + + networkingConfig := &network.NetworkingConfig{} + if d.network != "" { + networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{ + d.network: {}, + } + } + + resp, err := d.client.ContainerCreate(ctx, + &container.Config{ + Image: initImage, + Entrypoint: []string{"sh", "-c"}, + Cmd: []string{script}, + }, + &container.HostConfig{ + Mounts: mounts, + AutoRemove: true, + }, + networkingConfig, nil, + fmt.Sprintf("%s-%s", namePrefix, strings.ToLower(rand.Text()))) + if err != nil { + return fmt.Errorf("failed to create init container: %w", err) + } + + if err := d.client.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { + return fmt.Errorf("failed to start init container: %w", err) + } + + statusCh, errCh := d.client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) + select { + case err := <-errCh: + if err != nil && !cerrdefs.IsNotFound(err) { + return fmt.Errorf("error waiting for init container: %w", err) + } + case status := <-statusCh: + if status.StatusCode != 0 { + return fmt.Errorf("init container %s failed with exit code %d", namePrefix, status.StatusCode) + } + } + + return nil +} + func containerFiles(files []File, containerName string) (map[string]string, map[string]string) { fileContents := make(map[string]string, len(files)) envVars := make(map[string]string, len(files)) @@ -1233,11 +1282,6 @@ func fileEnvKeysHash(files []File) string { } func (d *dockerBackend) populateFilesVolume(ctx context.Context, volumeName, containerName string, fileContents map[string]string) error { - initImage := "alpine:latest" - if err := d.pullImage(ctx, initImage, true); err != nil { - return fmt.Errorf("failed to ensure init image exists: %w", err) - } - var script strings.Builder script.WriteString("#!/bin/sh\nset -e\n") script.WriteString("rm -f /files/*\n") @@ -1253,44 +1297,11 @@ func (d *dockerBackend) populateFilesVolume(ctx context.Context, volumeName, con fmt.Fprintf(&script, "cat > '%s' << 'EOF'\n%s\nEOF\n", containerPath, fileContents[filename]) } - initConfig := &container.Config{ - Image: initImage, - Entrypoint: []string{"sh", "-c"}, - Cmd: []string{script.String()}, - WorkingDir: "/", - } - - initHostConfig := &container.HostConfig{ - Mounts: []mount.Mount{{ - Type: mount.TypeVolume, - Source: volumeName, - Target: "/files", - }}, - AutoRemove: true, - } - - resp, err := d.client.ContainerCreate(ctx, initConfig, initHostConfig, &network.NetworkingConfig{}, nil, fmt.Sprintf("%s-init-%s", containerName, strings.ToLower(rand.Text()))) - if err != nil { - return fmt.Errorf("failed to create init container: %w", err) - } - - if err := d.client.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { - return fmt.Errorf("failed to start init container: %w", err) - } - - statusCh, errCh := d.client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) - select { - case err := <-errCh: - if err != nil && !cerrdefs.IsNotFound(err) { - return fmt.Errorf("error waiting for init container: %w", err) - } - case status := <-statusCh: - if status.StatusCode != 0 { - return fmt.Errorf("init container failed with exit code %d", status.StatusCode) - } - } - - return nil + return d.runInitContainer(ctx, containerName+"-init", script.String(), []mount.Mount{{ + Type: mount.TypeVolume, + Source: volumeName, + Target: "/files", + }}) } func (d *dockerBackend) pullImage(ctx context.Context, imageName string, ifNotExists bool) error { @@ -1325,8 +1336,9 @@ func (d *dockerBackend) pullImage(ctx context.Context, imageName string, ifNotEx return nil } -// prepareNanobotConfig creates a volume with nanobot YAML configuration for UVX/NPX runtimes -func (d *dockerBackend) prepareNanobotConfig(ctx context.Context, server ServerConfig, envVars map[string]string, webhooks []Webhook) (string, error) { +// prepareMCPServerNanobotConfig creates a volume containing the nanobot.yaml that configures +// how nanobot proxies to the underlying MCP server (used for UVX/NPX/remote/composite runtimes). +func (d *dockerBackend) prepareMCPServerNanobotConfig(ctx context.Context, server ServerConfig, envVars map[string]string, webhooks []Webhook) (string, error) { // Create all environment variables map allEnvVars := make(map[string][]byte, len(server.Env)+len(envVars)) headers := make(map[string][]byte, len(server.Headers)) @@ -1353,83 +1365,35 @@ func (d *dockerBackend) prepareNanobotConfig(ctx context.Context, server ServerC err error ) if server.Runtime == otypes.RuntimeComposite { - nanobotYAML, err = constructNanobotYAMLForCompositeServer(server.Components) + nanobotYAML, err = constructMCPServerNanobotYAMLForComposite(server.Components) } else { - nanobotYAML, err = constructNanobotYAMLForServer(server.MCPServerDisplayName, server.URL, server.Command, server.Args, allEnvVars, headers, webhooks) + nanobotYAML, err = constructMCPServerNanobotYAML(server.MCPServerDisplayName, server.URL, server.Command, server.Args, allEnvVars, headers, webhooks) } if err != nil { return "", fmt.Errorf("failed to construct nanobot YAML: %w", err) } - volumeName := server.MCPServerName + "-nanobot-config" - // Create volume for nanobot config + volumeName := server.MCPServerName + "-mcp-server-nanobot-config" _, err = d.client.VolumeCreate(ctx, volume.CreateOptions{ Labels: map[string]string{ "mcp.server.id": server.MCPServerName, - "mcp.purpose": "nanobot-config", + "mcp.purpose": "mcp-server-nanobot-config", }, Name: volumeName, }) if err != nil && !cerrdefs.IsAlreadyExists(err) { - return "", fmt.Errorf("failed to create nanobot config volume: %w", err) - } - - // Create init container to populate the volume with nanobot config - initImage := "alpine:latest" - if err = d.pullImage(ctx, initImage, true); err != nil { - return "", fmt.Errorf("failed to ensure init image exists: %w", err) + return "", fmt.Errorf("failed to create MCP server nanobot config volume: %w", err) } - // Create script to write nanobot config script := fmt.Sprintf("cat > /config/nanobot.yaml << 'EOF'\n%s\nEOF\n", nanobotYAML) - - // Create and run init container - initConfig := &container.Config{ - Image: initImage, - Entrypoint: []string{"sh", "-c"}, - Cmd: []string{script}, - } - - initHostConfig := &container.HostConfig{ - Mounts: []mount.Mount{ - { - Type: mount.TypeVolume, - Source: volumeName, - Target: "/config", - }, + if err = d.runInitContainer(ctx, server.MCPServerName+"-nanobot-init", script, []mount.Mount{ + { + Type: mount.TypeVolume, + Source: volumeName, + Target: "/config", }, - AutoRemove: true, - } - - // Configure network (same as main containers) - initNetworkingConfig := &network.NetworkingConfig{} - if d.network != "" { - initNetworkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{ - d.network: {}, - } - } - - resp, err := d.client.ContainerCreate(ctx, initConfig, initHostConfig, initNetworkingConfig, nil, fmt.Sprintf("%s-nanobot-init-%s", server.MCPServerName, strings.ToLower(rand.Text()))) - if err != nil { - return "", fmt.Errorf("failed to create nanobot init container: %w", err) - } - - // Start and wait for init container to complete - if err := d.client.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil { - return "", fmt.Errorf("failed to start init container: %w", err) - } - - // Wait for init container to complete - statusCh, errCh := d.client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) - select { - case err := <-errCh: - if err != nil && !cerrdefs.IsNotFound(err) { - return "", fmt.Errorf("error waiting for nanobot init container: %w", err) - } - case status := <-statusCh: - if status.StatusCode != 0 { - return "", fmt.Errorf("nanobot init container failed with exit code %d", status.StatusCode) - } + }); err != nil { + return "", err } return volumeName, nil diff --git a/pkg/mcp/kubernetes.go b/pkg/mcp/kubernetes.go index 6acdd52356..95c04c92fd 100644 --- a/pkg/mcp/kubernetes.go +++ b/pkg/mcp/kubernetes.go @@ -545,7 +545,7 @@ func (k *kubernetesBackend) k8sObjects(ctx context.Context, server ServerConfig, if server.NanobotAgentName == "" { // If this is anything other than a remote runtime, then we need to add a special shim container. // The remote runtime will just be the shim and is deployed as the "real" container. - nanobotFileString, err := constructNanobotYAMLForServer( + nanobotFileString, err := constructMCPServerNanobotYAML( server.MCPServerDisplayName+" Shim", fmt.Sprintf("http://localhost:%d/%s", port, strings.TrimPrefix(server.ContainerPath, "/")), "", @@ -805,13 +805,14 @@ func (k *kubernetesBackend) k8sObjects(ctx context.Context, server ServerConfig, objs = append(objs, dep) if server.Runtime != types.RuntimeContainerized { - // Setup the nanobot config file and add it to the last container in the deployment. + // Setup the MCP server nanobot config (nanobot.yaml that configures how nanobot proxies + // to the underlying MCP server) and mount it into the last container in the deployment. var nanobotFileString []byte if server.Runtime == types.RuntimeComposite { - nanobotFileString, err = constructNanobotYAMLForCompositeServer(server.Components) + nanobotFileString, err = constructMCPServerNanobotYAMLForComposite(server.Components) annotations["nanobot-composite-file-rev"] = hash.Digest(nanobotFileString) } else { - nanobotFileString, err = constructNanobotYAMLForServer(server.MCPServerDisplayName, server.URL, server.Command, server.Args, secretEnvData, headerData, webhooks) + nanobotFileString, err = constructMCPServerNanobotYAML(server.MCPServerDisplayName, server.URL, server.Command, server.Args, secretEnvData, headerData, webhooks) } if err != nil { return nil, fmt.Errorf("failed to construct nanobot.yaml: %w", err) diff --git a/pkg/storage/openapi/generated/openapi_generated.go b/pkg/storage/openapi/generated/openapi_generated.go index c1552fce0b..8389335d69 100644 --- a/pkg/storage/openapi/generated/openapi_generated.go +++ b/pkg/storage/openapi/generated/openapi_generated.go @@ -2098,6 +2098,13 @@ func schema_obot_platform_obot_apiclient_types_CommonProviderMetadata(ref common Format: "", }, }, + "dialect": { + SchemaProps: spec.SchemaProps{ + Description: "Dialect specifies the LLM API format used by this provider (e.g. \"AnthropicMessages\", \"OpenAIChatCompletions\", \"OpenAIResponses\").", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, @@ -6948,6 +6955,12 @@ func schema_obot_platform_obot_apiclient_types_ModelManifest(ref common.Referenc Format: "", }, }, + "dialect": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"active", "usage"}, }, From 8ed845929062969143bb2a1125dea578a6a525a6 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Thu, 16 Apr 2026 16:35:33 -0700 Subject: [PATCH 2/8] Add Bifrost provider dialect and enable model providers in UI (#6358) * Add Bifrost provider dialect * Enable bedrock provider in UI * Enable Ollama in UI * Enable Azure, AzureEntra in UI * Update docs * Update Nanobot branch * Improve docs for Azure Entra * fix go mod issue * Resolve PR comments * fix go mod * Improve Ollama networking doc for linux users --- docs/docs/configuration/model-providers.md | 69 +++--- go.mod | 96 ++++---- go.sum | 212 +++++++++--------- .../handlers/nanobotagent/nanobotagent.go | 2 + .../nanobotagent/nanobotagent_test.go | 1 + .../server/dispatcher/availablemodels.go | 5 +- ui/user/src/lib/constants.ts | 9 +- ui/user/src/lib/sort.ts | 4 + .../routes/admin/model-providers/+page.svelte | 9 +- 9 files changed, 231 insertions(+), 176 deletions(-) diff --git a/docs/docs/configuration/model-providers.md b/docs/docs/configuration/model-providers.md index bbe8d51156..95cc8d06ba 100644 --- a/docs/docs/configuration/model-providers.md +++ b/docs/docs/configuration/model-providers.md @@ -17,7 +17,7 @@ Obot supports a variety of model providers, including: - Google **Enterprise** -- [Azure OpenAI / Microsoft Foundry](#azure-openai-enterprise-only) +- [Azure OpenAI / Microsoft Foundry](#azure-enterprise-only) - Amazon Bedrock - Google Vertex (Gemini models) @@ -71,40 +71,59 @@ Setting a default model here does not automatically grant users access to it. Us ### Instructions for configuring specific providers -#### Azure OpenAI (Enterprise only) +#### Azure (Enterprise only) -The Azure OpenAI model provider supports legacy Azure OpenAI resources. Microsoft Foundry works with API key authentication as well. - -This model provider supports two forms of authentication: API keys and Microsoft Entra. +Obot supports two Azure providers, each with a different authentication method. ##### API Key Authentication -In the Azure OpenAI or Microsoft Foundry UI, you can find your API key after you have set up at least one deployment, as well as your endpoint URL. -Both of these values are required when you configure this model provider in Obot. +Use the **Azure** provider for API key-based authentication. -Additionally, you must manually specify the names of all of your deployments, as the API key does not provide the ability to list them. -The format is `name:type`, for example, `gpt-5.2:reasoning-llm`. The supported types are `llm`, `reasoning-llm`, `text-embedding`, and `image-generation`. -If no type is specified, Obot will assume the type is `llm`. +In the Azure portal, find your API key and endpoint URL after setting up at least one deployment — both are required. -If the type specified is `llm` or none at all, and the deployment name starts with the name of a known reasoning model (such as `o3` or `gpt-5`), Obot -will automatically treat it as a reasoning model. +You must also specify deployment names. The format is a comma-separated list of deployment names, optionally as `model:deployment` pairs (e.g. `gpt-4o,gpt-4o-mini` or `gpt-4o:my-gpt4o,gpt-4o-mini:my-mini`). -##### Microsoft Entra Authentication +You can also optionally specify the API version (defaults to `2025-01-01-preview`). -:::important -At this time, Microsoft Entra authentication is only supported for Azure OpenAI deployments and not for the newer Microsoft Foundry deployments. -::: +##### Microsoft Entra ID Authentication + +Use the **Azure (Entra ID)** provider for service principal authentication via Microsoft Entra ID. Deployments are discovered automatically from the Azure Management API. + +###### 1. Create a service principal + +```bash +az ad sp create-for-rbac --name "" \ + --role "Cognitive Services OpenAI User" \ + --scopes /subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts/ +``` + +This outputs the `appId` (Client ID), `password` (Client Secret), and `tenant` (Tenant ID) needed below. + +###### 2. Find your resource details + +```bash +az cognitiveservices account show \ + --name \ + --resource-group \ + --query "{endpoint:properties.endpoint, id:id}" +``` -Instead of using an API key, you can set up a Microsoft Entra app registration as a service principal to use Azure OpenAI. +###### 3. Configure the provider -Obot requires the Client ID, Client Secret, and Tenant ID of the Entra app, as well as the Endpoint URL, Subscription ID, and Resource Group from Azure OpenAI/Microsoft Foundry. +Obot requires: +- **Azure Endpoint** — your Azure OpenAI endpoint URL (`https://.openai.azure.com`) +- **Client ID** — the Entra app's application (client) ID +- **Client Secret** — the Entra app's client secret +- **Tenant ID** — the Entra app's tenant ID +- **Subscription ID** — the Azure subscription ID containing the Cognitive Services account +- **Resource Group** — the resource group containing the Cognitive Services account +- **Account Name** — the Cognitive Services account name -You do NOT need to manually specify your deployment names, as the Entra app's credentials will be sufficient to list them. +You can also optionally specify the API version (defaults to `2025-01-01-preview`). -After you have created your Entra app registration, you need to go to your Azure OpenAI resource in the Azure portal and add a new role assignment for the app registration, as a service principal. -It needs to have the `Cognitive Services OpenAI User` role. +The service principal requires at minimum the `Cognitive Services OpenAI User` or `Cognitive Services User` role on the account to read deployments. Deployments are discovered automatically — each deployment's base model name becomes the model ID exposed to Obot. -See the [Microsoft docs](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/role-based-access-control?view=foundry-classic#add-role-assignment-to-an-azure-openai-resource) for more details. +See the [Microsoft docs](https://learn.microsoft.com/en-us/azure/foundry/foundry-models/how-to/configure-entra-id) for more details. #### Ollama @@ -112,10 +131,10 @@ See the [Microsoft docs](https://learn.microsoft.com/en-us/azure/ai-foundry/open 1. **Expose Ollama to the network** - By default, Ollama only binds to `127.0.0.1:11434`. Since Obot runs in a container, `localhost` addresses resolve to Obot's container, not your host. Set `OLLAMA_HOST=0.0.0.0` before starting Ollama, then use your host's IP address in the endpoint URL. -2. **Use the OpenAI-compatible endpoint** - The endpoint must include the `/v1/` path: +2. **Set the Ollama host** ``` - http://:11434/v1/ + http://:11434 ``` - Using `http://:11434/` without `/v1/` will result in validation errors. + - If you are running Obot in Docker, you should use `http://host.docker.internal:11434`. For linux users, run Obot in Docker with this additional flag `--add-host=host.docker.internal:host-gateway` or use an alternative method of allowing the container to access the host network See [Ollama's FAQ](https://docs.ollama.com/faq) for platform-specific instructions on setting `OLLAMA_HOST`. diff --git a/go.mod b/go.mod index cfd692e013..0caa78290d 100644 --- a/go.mod +++ b/go.mod @@ -5,22 +5,22 @@ go 1.26.2 replace ( github.com/obot-platform/obot/apiclient => ./apiclient github.com/obot-platform/obot/logger => ./logger -) -replace github.com/nanobot-ai/nanobot => github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 +) require ( - cloud.google.com/go/storage v1.43.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 + cloud.google.com/go/storage v1.56.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3 github.com/MicahParks/jwkset v0.11.0 github.com/adhocore/gronx v1.19.5 github.com/adrg/xdg v0.5.3 - github.com/aws/aws-sdk-go-v2 v1.39.4 - github.com/aws/aws-sdk-go-v2/config v1.31.15 + github.com/aws/aws-sdk-go-v2 v1.41.3 + github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15 - github.com/aws/aws-sdk-go-v2/service/s3 v1.88.7 + github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0 github.com/containerd/errdefs v1.0.0 github.com/docker/go-connections v0.6.0 github.com/fatih/color v1.18.0 @@ -38,7 +38,7 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de github.com/moby/moby/api v1.52.0-alpha.1 github.com/moby/moby/client v0.1.0-alpha.0 - github.com/nanobot-ai/nanobot v0.0.68 + github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287 github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 github.com/obot-platform/kinm v0.0.0-20260310205725-afa1a058aa7a github.com/obot-platform/nah v0.0.0-20260310205713-8137b9b71aeb @@ -52,7 +52,7 @@ require ( github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 go.opentelemetry.io/otel v1.43.0 go.opentelemetry.io/otel/log v0.19.0 go.opentelemetry.io/otel/sdk v1.43.0 @@ -64,7 +64,7 @@ require ( golang.org/x/oauth2 v0.35.0 golang.org/x/sync v0.20.0 golang.org/x/term v0.41.0 - google.golang.org/api v0.197.0 + google.golang.org/api v0.247.0 google.golang.org/genai v1.0.0 gorm.io/datatypes v1.2.7 gorm.io/driver/postgres v1.6.0 @@ -80,20 +80,36 @@ require ( sigs.k8s.io/yaml v1.6.0 ) +require ( + cel.dev/expr v0.25.1 // indirect + cloud.google.com/go/monitoring v1.24.2 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 // indirect + github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect +) + require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect - cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.9.3 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.16.4 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect - cloud.google.com/go/iam v1.2.0 // indirect + cloud.google.com/go/iam v1.5.2 // indirect dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/AlecAivazis/survey/v2 v2.3.7 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect @@ -103,21 +119,21 @@ require ( github.com/andybalholm/brotli v1.2.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.18.19 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.29.8 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 - github.com/aws/smithy-go v1.23.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.11 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 + github.com/aws/smithy-go v1.24.2 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -179,10 +195,10 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 // indirect - github.com/google/s2a-go v0.1.8 // indirect + github.com/google/s2a-go v0.1.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect + github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect @@ -204,14 +220,13 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/compress v1.18.2 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.3.0 // indirect - github.com/mailru/easyjson v0.9.0 // indirect + github.com/mailru/easyjson v0.9.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect @@ -276,10 +291,9 @@ require ( go.etcd.io/etcd/api/v3 v3.5.14 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.68.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect @@ -301,9 +315,9 @@ require ( golang.org/x/net v0.52.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect - golang.org/x/time v0.11.0 // indirect + golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.42.0 // indirect - google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect google.golang.org/grpc v1.80.0 // indirect diff --git a/go.sum b/go.sum index 389585bc08..50c7a8ca82 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -15,27 +17,33 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= -cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.16.4 h1:fXOAIQmkApVvcIn7Pc2+5J8QTMVbUGLscnSVNl11su8= +cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/iam v1.2.0 h1:kZKMKVNk/IsSSc/udOb83K0hL/Yh/Gcqpz+oAkoIFN8= -cloud.google.com/go/iam v1.2.0/go.mod h1:zITGuWgsLZxd8OwAlX+eMFgZDXzBm7icj1PVTYG766Q= -cloud.google.com/go/longrunning v0.6.0 h1:mM1ZmaNsQsnb+5n1DNPeL0KwQd9jQRqSqSDEkBZr+aI= -cloud.google.com/go/longrunning v0.6.0/go.mod h1:uHzSZqW89h7/pasCWNYdUpwGz3PcVWhrWupreVPYLts= +cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8= +cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE= +cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= +cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= +cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE= +cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY= +cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM= +cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= -cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= +cloud.google.com/go/storage v1.56.0 h1:iixmq2Fse2tqxMbWhLWC9HfBj1qdxqAmiK8/eqtsLxI= +cloud.google.com/go/storage v1.56.0/go.mod h1:Tpuj6t4NweCLzlNbw9Z9iwxEkrSem20AetIeH/shgVU= +cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4= +cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -43,10 +51,10 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 h1:KpMC6LFL7mqpExyMC9jVOYRiVhLmamjeZfRsUpB7l4s= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= @@ -57,12 +65,20 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3 h1:ZJJNFaQ86GVKQ9ehw github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3/go.mod h1:URuDvhmATVKqHBH9/0nOiNKk0+YcwfQ3WkK5PqHKxc8= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI= -github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 h1:+tu3HOoMXB7RXEINRVIpxJCT+KdYiI7LAEAUrOw3dIU= github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZdiDllfyYH5l5OkAaZtk7VkWe89bPJFmnDBNHxg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 h1:owcC2UnmsZycprQ5RfRgjydWhuoxg71LUfyiQdijZuM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0/go.mod h1:ZPpqegjbE99EPKsu3iUWV22A04wzGPcAY/ziSIQEEgs= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.53.0 h1:4LP6hvB4I5ouTbGgWtixJhgED6xdf67twf9PoY96Tbg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.53.0/go.mod h1:jUZ5LYlw40WMd07qxcQJD5M40aUxrfwqQX1g7zxYnrQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 h1:Ron4zCA/yk6U7WOBXhTJcDpsUBG9npumK6xw2auFltQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0/go.mod h1:cSgYe11MCNYunTnRXrKiR/tHc0eoKjICUuWpNZoVCOo= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= @@ -108,44 +124,46 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/aws/aws-sdk-go-v2 v1.39.4 h1:qTsQKcdQPHnfGYBBs+Btl8QwxJeoWcOcPcixK90mRhg= -github.com/aws/aws-sdk-go-v2 v1.39.4/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 h1:t9yYsydLYNBk9cJ73rgPhPWqOh/52fcWDQB5b1JsKSY= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2/go.mod h1:IusfVNTmiSN3t4rhxWFaBAqn+mcNdwKtPcV16eYdgko= -github.com/aws/aws-sdk-go-v2/config v1.31.15 h1:gE3M4xuNXfC/9bG4hyowGm/35uQTi7bUKeYs5e/6uvU= -github.com/aws/aws-sdk-go-v2/config v1.31.15/go.mod h1:HvnvGJoE2I95KAIW8kkWVPJ4XhdrlvwJpV6pEzFQa8o= -github.com/aws/aws-sdk-go-v2/credentials v1.18.19 h1:Jc1zzwkSY1QbkEcLujwqRTXOdvW8ppND3jRBb/VhBQc= -github.com/aws/aws-sdk-go-v2/credentials v1.18.19/go.mod h1:DIfQ9fAk5H0pGtnqfqkbSIzky82qYnGvh06ASQXXg6A= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 h1:X7X4YKb+c0rkI6d4uJ5tEMxXgCZ+jZ/D6mvkno8c8Uw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11/go.mod h1:EqM6vPZQsZHYvC4Cai35UDg/f5NCEU+vp0WfbVqVcZc= +github.com/aws/aws-sdk-go-v2 v1.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA= +github.com/aws/aws-sdk-go-v2 v1.41.3/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 h1:N4lRUXZpZ1KVEUn6hxtco/1d2lgYhNn1fHkkl8WhlyQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/config v1.32.11 h1:ftxI5sgz8jZkckuUHXfC/wMUc8u3fG1vQS0plr2F2Zs= +github.com/aws/aws-sdk-go-v2/config v1.32.11/go.mod h1:twF11+6ps9aNRKEDimksp923o44w/Thk9+8YIlzWMmo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.11 h1:NdV8cwCcAXrCWyxArt58BrvZJ9pZ9Fhf9w6Uh5W3Uyc= +github.com/aws/aws-sdk-go-v2/credentials v1.19.11/go.mod h1:30yY2zqkMPdrvxBqzI9xQCM+WrlrZKSOpSJEsylVU+8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 h1:INUvJxmhdEbVulJYHI061k4TVuS3jzzthNvjqvVvTKM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19/go.mod h1:FpZN2QISLdEBWkayloda+sZjVJL+e9Gl0k1SyTgcswU= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15 h1:OsZ2Sk84YUPJfi6BemhyMQyuR8/5tWu37WBMVUl8lJk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15/go.mod h1:CYZDjBMY+MyT+U+QmXw81GBiq+lhgM97kIMdDAJk+hg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 h1:7AANQZkF3ihM8fbdftpjhken0TP9sBzFbV/Ze/Y4HXA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11/go.mod h1:NTF4QCGkm6fzVwncpkFQqoquQyOolcyXfbpC98urj+c= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 h1:ShdtWUZT37LCAA4Mw2kJAJtzaszfSHFb5n25sdcv4YE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11/go.mod h1:7bUb2sSr2MZ3M/N+VyETLTQtInemHXb/Fl3s8CLzm0Y= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 h1:bKgSxk1TW//00PGQqYmrq83c+2myGidEclp+t9pPqVI= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11/go.mod h1:vrPYCQ6rFHL8jzQA8ppu3gWX18zxjLIDGTeqDxkBmSI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 h1:DGFpGybmutVsCuF6vSuLZ25Vh55E3VmsnJmFfjeBx4M= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2/go.mod h1:hm/wU1HDvXCFEDzOLorQnZZ/CVvPXvWEmHMSmqgQRuA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 h1:GpMf3z2KJa4RnJ0ew3Hac+hRFYLZ9DDjfgXjuW+pB54= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11/go.mod h1:6MZP3ZI4QQsgUCFTwMZA2V0sEriNQ8k2hmoHF3qjimQ= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 h1:weapBOuuFIBEQ9OX/NVW3tFQCvSutyjZYk/ga5jDLPo= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11/go.mod h1:3C1gN4FmIVLwYSh8etngUS+f1viY6nLCDVtZmrFbDy0= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.7 h1:Wer3W0GuaedWT7dv/PiWNZGSQFSTcBY2rZpbiUp5xcA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.7/go.mod h1:UHKgcRSx8PVtvsc1Poxb/Co3PD3wL7P+f49P0+cWtuY= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.8 h1:M5nimZmugcZUO9wG7iVtROxPhiqyZX6ejS1lxlDPbTU= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.8/go.mod h1:mbef/pgKhtKRwrigPPs7SSSKZgytzP8PQ6P6JAAdqyM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 h1:S5GuJZpYxE0lKeMHKn+BRTz6PTFpgThyJ+5mYfux7BM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3/go.mod h1:X4OF+BTd7HIb3L+tc4UlWHVrpgwZZIVENU15pRDVTI0= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 h1:Ekml5vGg6sHSZLZJQJagefnVe6PmqC2oiRkBq4F7fU0= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.9/go.mod h1:/e15V+o1zFHWdH3u7lpI3rVBcxszktIKuHKCY2/py+k= -github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= -github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 h1:/sECfyq2JTifMI2JPyZ4bdRN77zJmr6SrS1eL3augIA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19/go.mod h1:dMf8A5oAqr9/oxOfLkC/c2LU/uMcALP0Rgn2BD5LWn0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJe6qZoRSJo0WfUhsMdUKhoODXE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 h1:CjMzUs78RDDv4ROu3JnJn/Ig1r6ZD7/T2DXLLRpejic= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16/go.mod h1:uVW4OLBqbJXSHJYA9svT9BluSvvwbzLQ2Crf6UPzR3c= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 h1:DIBqIrJ7hv+e4CmIk2z3pyKT+3B6qVMgRsawHiR3qso= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7/go.mod h1:vLm00xmBke75UmpNvOcZQ/Q30ZFjbczeLFqGx5urmGo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7suZk9UCJHE1Iw9GMZJJl0dAnKXXP1NaSDHwmw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 h1:NSbvS17MlI2lurYgXnCOLvCFX38sBW4eiVER7+kkgsU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16/go.mod h1:SwT8Tmqd4sA6G1qaGdzWCJN99bUmPGHfRwwq3G5Qb+A= +github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0 h1:SWTxh/EcUCDVqi/0s26V6pVUq0BBG7kx0tDTmF/hCgA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0/go.mod h1:79S2BdqCJpScXZA2y+cpZuocWsjGjJINyXnOsf5DTz8= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.12/go.mod h1:fEWYKTRGoZNl8tZ77i61/ccwOMJdGxwOhWCkp6TXAr0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 h1:EnUdUqRP1CNzt2DkV67tJx6XDN4xlfBFm+bzeNOQVb0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16/go.mod h1:Jic/xv0Rq/pFNCh3WwpH4BEqdbSAl+IyHro8LbibHD8= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 h1:XQTQTF75vnug2TXS8m7CVJfC2nniYPZnO1D4Np761Oo= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.8/go.mod h1:Xgx+PR1NUOjNmQY+tRMnouRp83JRM8pRMw/vCaVhPkI= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -164,8 +182,6 @@ github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/bombsimon/logrusr/v4 v4.1.0 h1:uZNPbwusB0eUXlO8hIUwStE6Lr5bLN6IgYgG+75kuh4= github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8= -github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c h1:0XulKTIDELtp3KS+nIqub+rOJ5bve1LOhFewzE218Gg= -github.com/calvinmclean/nanobot v0.0.0-20260408174919-d7f157a83d0c/go.mod h1:6Yi07gQdKON69TMEIVIkPjuNL7R+Iyy6kJ3CUck5Qeg= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -197,7 +213,6 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -248,12 +263,13 @@ github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtz github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= @@ -288,6 +304,8 @@ github.com/go-git/go-git/v5 v5.17.0 h1:AbyI4xf+7DsjINHMu35quAh4wJygKBKBuXVjV/pxe github.com/go-git/go-git/v5 v5.17.0/go.mod h1:f82C4YiLx+Lhi8eHxltLeGC5uBTXSFa6PC5WW9o4SjI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -336,13 +354,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -357,8 +368,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -378,19 +387,18 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ= github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= -github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= +github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= @@ -472,14 +480,15 @@ github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXw github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -499,8 +508,8 @@ github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8= +github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -548,6 +557,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287 h1:SrRyhgsl+7ZSNM1S4IPBecrDsCQPgeF321Bk4pT5kvc= +github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287/go.mod h1:ZcDQi+Hh3zlX9ygBtGq4kNmb8MPerMRI8iKyot5DuoE= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= @@ -655,6 +666,8 @@ github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wx github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= @@ -737,18 +750,18 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.68.0 h1:w3zlHYETbDwXyWHZlyyR58ZC39XGi8rAhkBgUgJ9d5w= go.opentelemetry.io/contrib/bridges/prometheus v0.68.0/go.mod h1:GR/mClR2nn7vE8RLwxKjoBNg+QtgdDhRzxVa93koy5o= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 h1:0D3GFvELGIwQGfC6agLsbrEYSGWZTRTxIXxcQUqrOuk= go.opentelemetry.io/contrib/exporters/autoexport v0.68.0/go.mod h1:DM2NV7Zb8CcGeVPt6glouY0FAiwZQ/iqgcWExhgWeN8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= @@ -857,7 +870,6 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -936,8 +948,8 @@ golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -988,8 +1000,8 @@ google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= -google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= +google.golang.org/api v0.247.0 h1:tSd/e0QrUlLsrwMKmkbQhYVa109qIintOls2Wh6bngc= +google.golang.org/api v0.247.0/go.mod h1:r1qZOPmxXffXg6xS5uhx16Fa/UFY8QU/K4bfKrnvovM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1010,9 +1022,8 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d h1:/aDRtSZJjyLQzm75d+a1wOJaqyKBMvIAfeQmoa3ORiI= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:etfGUgejTiadZAUaEP14NP97xi1RGeawqkjDARA/UOs= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= @@ -1021,22 +1032,11 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/controller/handlers/nanobotagent/nanobotagent.go b/pkg/controller/handlers/nanobotagent/nanobotagent.go index 6be01fcbfc..3cea7e8915 100644 --- a/pkg/controller/handlers/nanobotagent/nanobotagent.go +++ b/pkg/controller/handlers/nanobotagent/nanobotagent.go @@ -447,6 +447,8 @@ func (h *Handler) parseModelProvider(model resolvedLLMModel) (nanobotLLMProvider baseURL = h.serverURL + "/api/llm-proxy/anthropic" case nanobottypes.DialectOpenAIResponses: baseURL = h.serverURL + "/api/llm-proxy/openai" + case nanobottypes.DialectBifrostRequest: + fallthrough // same as default default: baseURL = h.serverURL + "/api/llm-proxy" } diff --git a/pkg/controller/handlers/nanobotagent/nanobotagent_test.go b/pkg/controller/handlers/nanobotagent/nanobotagent_test.go index fc25a9d0b9..6e450a58b1 100644 --- a/pkg/controller/handlers/nanobotagent/nanobotagent_test.go +++ b/pkg/controller/handlers/nanobotagent/nanobotagent_test.go @@ -117,6 +117,7 @@ func TestNanobotParseModelProviderDeclaredDialectDrivesURL(t *testing.T) { {nanobottypes.DialectOpenAIResponses, "https://obot.example.com/api/llm-proxy/openai"}, {nanobottypes.DialectOpenAIChatCompletions, "https://obot.example.com/api/llm-proxy"}, {nanobottypes.DialectOpenResponses, "https://obot.example.com/api/llm-proxy"}, + {nanobottypes.DialectBifrostRequest, "https://obot.example.com/api/llm-proxy"}, } { model := resolvedLLMModel{ TargetModel: "some-model", diff --git a/pkg/gateway/server/dispatcher/availablemodels.go b/pkg/gateway/server/dispatcher/availablemodels.go index 11b3524a95..2b414386e4 100644 --- a/pkg/gateway/server/dispatcher/availablemodels.go +++ b/pkg/gateway/server/dispatcher/availablemodels.go @@ -21,7 +21,10 @@ func (d *Dispatcher) ModelsForProviderWithEnv(ctx context.Context, gptClient *gp return nil, fmt.Errorf("failed to get URL for model provider %q: %w", modelProviderName, err) } - r, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String()+"/v1/models", nil) + if u.Path == "" || u.Path == "/" { + u.Path = "/v1" + } + r, err := http.NewRequestWithContext(ctx, http.MethodGet, u.JoinPath("models").String(), nil) if err != nil { return nil, fmt.Errorf("failed to create request to model provider %q: %w", modelProviderName, err) } diff --git a/ui/user/src/lib/constants.ts b/ui/user/src/lib/constants.ts index 07902f9744..9e947598a7 100644 --- a/ui/user/src/lib/constants.ts +++ b/ui/user/src/lib/constants.ts @@ -52,12 +52,17 @@ export const CommonModelProviderIds = { XAI: 'xai-model-provider', DEEPSEEK: 'deepseek-model-provider', GEMINI_VERTEX: 'gemini-vertex-model-provider', - GENERIC_OPENAI: 'generic-openai-model-provider' + GENERIC_OPENAI: 'generic-openai-model-provider', + AZURE: 'azure-model-provider', + AZURE_ENTRA: 'azure-entra-model-provider' }; export const RecommendedModelProviders = [ CommonModelProviderIds.OPENAI, - CommonModelProviderIds.AZURE_OPENAI + CommonModelProviderIds.ANTHROPIC, + CommonModelProviderIds.AMAZON_BEDROCK, + CommonModelProviderIds.AZURE, + CommonModelProviderIds.AZURE_ENTRA ]; export const PROJECT_MCP_SERVER_NAME = 'MCP Servers'; diff --git a/ui/user/src/lib/sort.ts b/ui/user/src/lib/sort.ts index 2b15e8f2f6..90473083b1 100644 --- a/ui/user/src/lib/sort.ts +++ b/ui/user/src/lib/sort.ts @@ -52,6 +52,8 @@ export const sortModelProviders = (modelProviders: ModelProvider[], isLegacyDisa CommonModelProviderIds.OPENAI, CommonModelProviderIds.ANTHROPIC, CommonModelProviderIds.AZURE_OPENAI, + CommonModelProviderIds.AZURE, + CommonModelProviderIds.AZURE_ENTRA, CommonModelProviderIds.AMAZON_BEDROCK, CommonModelProviderIds.ANTHROPIC_BEDROCK, CommonModelProviderIds.XAI, @@ -65,6 +67,8 @@ export const sortModelProviders = (modelProviders: ModelProvider[], isLegacyDisa : [ CommonModelProviderIds.OPENAI, CommonModelProviderIds.AZURE_OPENAI, + CommonModelProviderIds.AZURE, + CommonModelProviderIds.AZURE_ENTRA, CommonModelProviderIds.ANTHROPIC, CommonModelProviderIds.AMAZON_BEDROCK, CommonModelProviderIds.ANTHROPIC_BEDROCK, diff --git a/ui/user/src/routes/admin/model-providers/+page.svelte b/ui/user/src/routes/admin/model-providers/+page.svelte index 9c0535edbf..74b5ce6815 100644 --- a/ui/user/src/routes/admin/model-providers/+page.svelte +++ b/ui/user/src/routes/admin/model-providers/+page.svelte @@ -42,7 +42,14 @@ ); let isAdminReadonly = $derived(profile.current.isAdminReadonly?.()); let isLegacyDisabled = $derived(version.current.disableLegacyChat); - const nanobotIntegratedModels = [CommonModelProviderIds.OPENAI, CommonModelProviderIds.ANTHROPIC]; + const nanobotIntegratedModels = [ + CommonModelProviderIds.OPENAI, + CommonModelProviderIds.ANTHROPIC, + CommonModelProviderIds.AMAZON_BEDROCK, + CommonModelProviderIds.AZURE, + CommonModelProviderIds.AZURE_ENTRA, + CommonModelProviderIds.OLLAMA + ]; const defaultModelAliases = $derived(defaultModelAliasesStore.current); initModels([]); From 6cbf77ef469b2b08773d512d6ea92e4ddfb519b5 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Fri, 17 Apr 2026 15:11:56 -0700 Subject: [PATCH 3/8] Remaining changes: message policies, dependencies, etc. WIP deps Rename NANOBOT_CONFIG_PATH => NANOBOT_CONFIG Fix MessagePolicy for Bifrost Extract and reuse message policies code Include env in BackPopulateModels - This allows the Azure provider to get updated deployments Update kinm + nah improve docs lint generate Improve URL handling --- docs/docs/configuration/model-providers.md | 2 +- go.mod | 87 ++++--- go.sum | 220 +++++++++--------- pkg/api/handlers/nanobotagent.go | 2 +- .../handlers/nanobotagent/nanobotagent.go | 14 +- .../handlers/toolreference/toolreference.go | 4 +- pkg/gateway/server/llmproxy.go | 165 +++++++------ pkg/messagepolicy/evaluate.go | 126 ++++++++-- .../openapi/generated/openapi_generated.go | 49 +++- 9 files changed, 411 insertions(+), 258 deletions(-) diff --git a/docs/docs/configuration/model-providers.md b/docs/docs/configuration/model-providers.md index 95cc8d06ba..09b058dcad 100644 --- a/docs/docs/configuration/model-providers.md +++ b/docs/docs/configuration/model-providers.md @@ -73,7 +73,7 @@ Setting a default model here does not automatically grant users access to it. Us #### Azure (Enterprise only) -Obot supports two Azure providers, each with a different authentication method. +Obot supports two Azure providers, each with a different authentication method. These are compatible with both Azure OpenAI deployments and Foundry deployments. ##### API Key Authentication diff --git a/go.mod b/go.mod index 0caa78290d..28c95b1ca5 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,6 @@ go 1.26.2 replace ( github.com/obot-platform/obot/apiclient => ./apiclient github.com/obot-platform/obot/logger => ./logger - - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 ) require ( @@ -17,7 +15,7 @@ require ( github.com/MicahParks/jwkset v0.11.0 github.com/adhocore/gronx v1.19.5 github.com/adrg/xdg v0.5.3 - github.com/aws/aws-sdk-go-v2 v1.41.3 + github.com/aws/aws-sdk-go-v2 v1.41.5 github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15 github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0 @@ -38,10 +36,10 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de github.com/moby/moby/api v1.52.0-alpha.1 github.com/moby/moby/client v0.1.0-alpha.0 - github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287 + github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 - github.com/obot-platform/kinm v0.0.0-20260310205725-afa1a058aa7a - github.com/obot-platform/nah v0.0.0-20260310205713-8137b9b71aeb + github.com/obot-platform/kinm v0.0.0-20260420174234-eec2cd66c333 + github.com/obot-platform/nah v0.0.0-20260420174246-bea1b9e01234 github.com/obot-platform/obot/apiclient v0.0.0-20250813183905-ade719c1e8bf github.com/obot-platform/obot/logger v0.0.0-20241217130503-4004a5c69f32 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c @@ -61,7 +59,7 @@ require ( golang.org/x/crypto v0.49.0 golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 golang.org/x/mod v0.33.0 - golang.org/x/oauth2 v0.35.0 + golang.org/x/oauth2 v0.36.0 golang.org/x/sync v0.20.0 golang.org/x/term v0.41.0 google.golang.org/api v0.247.0 @@ -69,14 +67,14 @@ require ( gorm.io/datatypes v1.2.7 gorm.io/driver/postgres v1.6.0 gorm.io/gorm v1.30.1 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/apiserver v0.31.1 - k8s.io/client-go v0.31.1 - k8s.io/component-base v0.31.1 - k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 - k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 - sigs.k8s.io/controller-runtime v0.19.0 + k8s.io/api v0.34.7 + k8s.io/apimachinery v0.34.7 + k8s.io/apiserver v0.34.7 + k8s.io/client-go v0.34.7 + k8s.io/component-base v0.34.7 + k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f + k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b + sigs.k8s.io/controller-runtime v0.22.5 sigs.k8s.io/yaml v1.6.0 ) @@ -86,14 +84,18 @@ require ( github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/google/btree v1.1.3 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) require ( @@ -118,21 +120,20 @@ require ( github.com/alecthomas/chroma/v2 v2.15.0 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.11 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 github.com/aws/smithy-go v1.24.2 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect @@ -168,12 +169,12 @@ require ( github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/ebitengine/purego v0.8.2 // indirect - github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/fxamacker/cbor/v2 v2.8.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/getkin/kin-openapi v0.132.0 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/glebarez/sqlite v1.11.0 // indirect @@ -190,10 +191,9 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/cel-go v0.20.1 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/cel-go v0.26.0 // indirect + github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -201,13 +201,12 @@ require ( github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/css v1.0.1 // indirect - github.com/gorilla/websocket v1.5.3 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86 // indirect github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -238,7 +237,7 @@ require ( github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.16.0 // indirect @@ -249,7 +248,6 @@ require ( github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/obot-platform/mcp-oauth-proxy v0.0.3-0.20260106135339-3745d9b14a30 // indirect github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77 // indirect - github.com/onsi/ginkgo/v2 v2.20.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect @@ -274,7 +272,7 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/pflag v1.0.7 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/stoewer/go-strcase v1.2.0 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect github.com/tetratelabs/wazero v1.9.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -288,9 +286,9 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/goldmark v1.7.13 // indirect github.com/yuin/goldmark-emoji v1.0.4 // indirect - go.etcd.io/etcd/api/v3 v3.5.14 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect - go.etcd.io/etcd/client/v3 v3.5.14 // indirect + go.etcd.io/etcd/api/v3 v3.6.4 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect + go.etcd.io/etcd/client/v3 v3.6.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.68.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect @@ -309,7 +307,7 @@ require ( go.opentelemetry.io/otel/trace v1.43.0 // indirect go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/net v0.52.0 // indirect @@ -330,14 +328,13 @@ require ( gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.6.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kms v0.31.1 // indirect - k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 // indirect + k8s.io/kms v0.34.7 // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect modernc.org/libc v1.66.7 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect modernc.org/sqlite v1.38.2 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect sigs.k8s.io/controller-tools v0.16.4 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index 50c7a8ca82..9d909a16aa 100644 --- a/go.sum +++ b/go.sum @@ -121,47 +121,45 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/aws/aws-sdk-go-v2 v1.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA= -github.com/aws/aws-sdk-go-v2 v1.41.3/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 h1:N4lRUXZpZ1KVEUn6hxtco/1d2lgYhNn1fHkkl8WhlyQ= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= +github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= github.com/aws/aws-sdk-go-v2/config v1.32.11 h1:ftxI5sgz8jZkckuUHXfC/wMUc8u3fG1vQS0plr2F2Zs= github.com/aws/aws-sdk-go-v2/config v1.32.11/go.mod h1:twF11+6ps9aNRKEDimksp923o44w/Thk9+8YIlzWMmo= -github.com/aws/aws-sdk-go-v2/credentials v1.19.11 h1:NdV8cwCcAXrCWyxArt58BrvZJ9pZ9Fhf9w6Uh5W3Uyc= -github.com/aws/aws-sdk-go-v2/credentials v1.19.11/go.mod h1:30yY2zqkMPdrvxBqzI9xQCM+WrlrZKSOpSJEsylVU+8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 h1:INUvJxmhdEbVulJYHI061k4TVuS3jzzthNvjqvVvTKM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19/go.mod h1:FpZN2QISLdEBWkayloda+sZjVJL+e9Gl0k1SyTgcswU= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15 h1:OsZ2Sk84YUPJfi6BemhyMQyuR8/5tWu37WBMVUl8lJk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.15/go.mod h1:CYZDjBMY+MyT+U+QmXw81GBiq+lhgM97kIMdDAJk+hg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 h1:/sECfyq2JTifMI2JPyZ4bdRN77zJmr6SrS1eL3augIA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19/go.mod h1:dMf8A5oAqr9/oxOfLkC/c2LU/uMcALP0Rgn2BD5LWn0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJe6qZoRSJo0WfUhsMdUKhoODXE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 h1:CjMzUs78RDDv4ROu3JnJn/Ig1r6ZD7/T2DXLLRpejic= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16/go.mod h1:uVW4OLBqbJXSHJYA9svT9BluSvvwbzLQ2Crf6UPzR3c= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 h1:DIBqIrJ7hv+e4CmIk2z3pyKT+3B6qVMgRsawHiR3qso= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7/go.mod h1:vLm00xmBke75UmpNvOcZQ/Q30ZFjbczeLFqGx5urmGo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7suZk9UCJHE1Iw9GMZJJl0dAnKXXP1NaSDHwmw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 h1:NSbvS17MlI2lurYgXnCOLvCFX38sBW4eiVER7+kkgsU= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16/go.mod h1:SwT8Tmqd4sA6G1qaGdzWCJN99bUmPGHfRwwq3G5Qb+A= github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0 h1:SWTxh/EcUCDVqi/0s26V6pVUq0BBG7kx0tDTmF/hCgA= github.com/aws/aws-sdk-go-v2/service/s3 v1.94.0/go.mod h1:79S2BdqCJpScXZA2y+cpZuocWsjGjJINyXnOsf5DTz8= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.12/go.mod h1:fEWYKTRGoZNl8tZ77i61/ccwOMJdGxwOhWCkp6TXAr0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 h1:EnUdUqRP1CNzt2DkV67tJx6XDN4xlfBFm+bzeNOQVb0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16/go.mod h1:Jic/xv0Rq/pFNCh3WwpH4BEqdbSAl+IyHro8LbibHD8= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 h1:XQTQTF75vnug2TXS8m7CVJfC2nniYPZnO1D4Np761Oo= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.8/go.mod h1:Xgx+PR1NUOjNmQY+tRMnouRp83JRM8pRMw/vCaVhPkI= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= @@ -259,8 +257,8 @@ github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= -github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -282,8 +280,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= -github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gen2brain/webp v0.5.4 h1:edPfjyt9vU9A+VMQCg7uKz/A2Jjle+yP20ZPqZH3l6s= github.com/gen2brain/webp v0.5.4/go.mod h1:kEFkGdK1wG9ePKj9ylcLUrMQfqevXGTpVq1S8lZL0j4= github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= @@ -332,8 +330,6 @@ github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnD github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -358,18 +354,17 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= -github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -405,8 +400,8 @@ github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= -github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86 h1:m9yLtIEd0z1ia8qFjq3u0Ozb6QKwidyL856JLJp6nbA= github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86/go.mod h1:lK3K5EZx4dyT24UG3yCt0wmspkYqrj4D/8kxdN3relk= github.com/gptscript-ai/chat-completion-client v0.0.0-20250224164718-139cb4507b1d h1:p5uqZufDIMQzAALblZFkr8fwbnZbFXbBCR1ZMAFylXk= @@ -421,12 +416,12 @@ github.com/gptscript-ai/gptscript v0.9.10-0.20260410155950-313cef63e154 h1:Z8lyB github.com/gptscript-ai/gptscript v0.9.10-0.20260410155950-313cef63e154/go.mod h1:xiAjomImv0MlyF1bJPNEAFTDIE+0B/9A+N1DmCfs9O8= github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9 h1:wQC8sKyeGA50WnCEG+Jo5FNRIkuX3HX8d3ubyWCCoI8= github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9/go.mod h1:iwHxuueg2paOak7zIg0ESBWx7A0wIHGopAratbgaPNY= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -443,8 +438,6 @@ github.com/hexops/valast v1.5.0/go.mod h1:Jcy1pNH7LNraVaAZDLyv21hHg2WBv9Nf9FL6fG github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -463,8 +456,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -547,8 +540,9 @@ github.com/moby/moby/client v0.1.0-alpha.0/go.mod h1:pVMvmGeD4P9tbgBtEHZKW993Qkj github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -557,8 +551,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287 h1:SrRyhgsl+7ZSNM1S4IPBecrDsCQPgeF321Bk4pT5kvc= -github.com/nanobot-ai/nanobot v0.0.66-0.20260416233023-56f525a03287/go.mod h1:ZcDQi+Hh3zlX9ygBtGq4kNmb8MPerMRI8iKyot5DuoE= +github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee h1:WdMwK6EPGP64+EgoORBJ1IFPvSZApcaoVYh+0Z4Zxh0= +github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee/go.mod h1:y9rGtxA+kJVmtj8RmoHSM6/P4KCwoEtjL6MpARPuJnQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= @@ -571,20 +565,20 @@ github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//J github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= -github.com/obot-platform/kinm v0.0.0-20260310205725-afa1a058aa7a h1:Lc9akHuLyb5ByKcp2L/f4vkIP0jkBVv/OiWUmUrFPr0= -github.com/obot-platform/kinm v0.0.0-20260310205725-afa1a058aa7a/go.mod h1:uIt/q4bSrRWxjnX9wGn9i+LfBvN04g0b/c4h5imPCOI= +github.com/obot-platform/kinm v0.0.0-20260420174234-eec2cd66c333 h1:KMqxyxZ+zBfZ1Bn57roS8cWG8ZNy7/Y3iKLeeqv9ZdE= +github.com/obot-platform/kinm v0.0.0-20260420174234-eec2cd66c333/go.mod h1:L1cbQ1k31Q9SKSrEG0ToNrXFGdNP03o0zHFTlbNP8WU= github.com/obot-platform/mcp-oauth-proxy v0.0.3-0.20260106135339-3745d9b14a30 h1:PbvvLXjoUHQGpQ4ZzV9Aj8n8y0evpZljPlpDu96lFC4= github.com/obot-platform/mcp-oauth-proxy v0.0.3-0.20260106135339-3745d9b14a30/go.mod h1:8I+MeGRPsv42hk7/MCSqWHvz4p7xvIR0CIh1GG3vtXM= -github.com/obot-platform/nah v0.0.0-20260310205713-8137b9b71aeb h1:H1fxxy3t+ZbPHtmvSYFTMg2cHwqIcYFtDr+rd9MPPVc= -github.com/obot-platform/nah v0.0.0-20260310205713-8137b9b71aeb/go.mod h1:AUP8EhWbz+tBQn1QMYcBY8EPFN8LFNZvKhOxpt4hafA= +github.com/obot-platform/nah v0.0.0-20260420174246-bea1b9e01234 h1:dZm1hwaTeXpxg476eNRqI9Rpxl4PAOm9AxX7iEAsfOQ= +github.com/obot-platform/nah v0.0.0-20260420174246-bea1b9e01234/go.mod h1:+dYHcGg+BgcdZ2+eo3XCxhJFNQjmaKNRgD2loOvcFN0= github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77 h1:3bMMZ1f+GPXFQ1uNaYbO/uECWvSfqEA+ZEXn1rFAT88= github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77/go.mod h1:8Hf+pH6thup1sPZPD+NLg7d6vbpsdilu9CPIeikvgMQ= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= -github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -670,8 +664,8 @@ github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMps github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -680,7 +674,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -715,8 +708,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= @@ -730,22 +723,20 @@ github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark-emoji v1.0.4 h1:vCwMkPZSNefSUnOW2ZKRUjBSD5Ok3W78IXhGxxAEF90= github.com/yuin/goldmark-emoji v1.0.4/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= -go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= -go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= -go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= -go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= -go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= -go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= -go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= -go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= -go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= +go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I= +go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM= +go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo= +go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk= +go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0= +go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI= +go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A= +go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo= +go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA= +go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE= +go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU= +go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg= +go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= +go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -758,8 +749,8 @@ go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK2 go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 h1:0D3GFvELGIwQGfC6agLsbrEYSGWZTRTxIXxcQUqrOuk= go.opentelemetry.io/contrib/exporters/autoexport v0.68.0/go.mod h1:DM2NV7Zb8CcGeVPt6glouY0FAiwZQ/iqgcWExhgWeN8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= @@ -806,8 +797,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -882,8 +873,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1057,7 +1048,6 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -1083,28 +1073,28 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= -k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c= -k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= -k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= -k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 h1:si3PfKm8dDYxgfbeA6orqrtLkvvIeH8UqffFJDl0bz4= -k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/api v0.34.7 h1:186BQYhLYaaU0jhC4/uC3s4cQ+YSk0BlazRnEldXiqY= +k8s.io/api v0.34.7/go.mod h1:2qet0m0IfHSwXp+RLnunTWADUjy6qaXDa4PdeUnTJ9s= +k8s.io/apiextensions-apiserver v0.34.3 h1:p10fGlkDY09eWKOTeUSioxwLukJnm+KuDZdrW71y40g= +k8s.io/apiextensions-apiserver v0.34.3/go.mod h1:aujxvqGFRdb/cmXYfcRTeppN7S2XV/t7WMEc64zB5A0= +k8s.io/apimachinery v0.34.7 h1:nkAtvxByvBFSyIyOTrFKcy6pgQ4G1NCKsypWArLdNSY= +k8s.io/apimachinery v0.34.7/go.mod h1:z7dd12Xd400CXIycE8nmn32xZhApV9zskHs0A5xeU/Q= +k8s.io/apiserver v0.34.7 h1:G0JG/NTBN+FDYxF9r15dmj7vA8Gn3QH06kg8un9N+6c= +k8s.io/apiserver v0.34.7/go.mod h1:7+me/mC1L/BRkb7MbUwUpppl/BNodyt28bgVmytocrs= +k8s.io/client-go v0.34.7 h1:zxksYcHi4DMv6HfjMbHTfcV3jYZh7BY3yH18maoRxsA= +k8s.io/client-go v0.34.7/go.mod h1:GS3K60t9FI20+l3cvB/EfDXyD+JoKr3suIjSGISQLDc= +k8s.io/component-base v0.34.7 h1:MbY8LBCV7+SFzXGdFTxmjCodpeg+lEBVOPBzmbKuD7I= +k8s.io/component-base v0.34.7/go.mod h1:8nuSOhmTwQ3lz79kDPXtLD7NviHYhAF8vAgX++NCgiY= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kms v0.31.1 h1:cGLyV3cIwb0ovpP/jtyIe2mEuQ/MkbhmeBF2IYCA9Io= -k8s.io/kms v0.31.1/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 h1:MErs8YA0abvOqJ8gIupA1Tz6PKXYUw34XsGlA7uSL1k= -k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094/go.mod h1:7ioBJr1A6igWjsR2fxq2EZ0mlMwYLejazSIc2bzMp2U= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kms v0.34.7 h1:H6cSQDEXbICeUYVsquZ5WF40pWv6v6xDlUJ6cy0Fdww= +k8s.io/kms v0.34.7/go.mod h1:sBByaFjIDNm8oPQXjREzXISZSx60On//fhvnAVhuL5g= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc/v4 v4.26.3 h1:yEN8dzrkRFnn4PUUKXLYIqVf2PJYAEjMTFjO3BDGc3I= modernc.org/cc/v4 v4.26.3/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= @@ -1138,15 +1128,17 @@ pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.22.5 h1:v3nfSUMowX/2WMp27J9slwGFyAt7IV0YwBxAkrUr0GE= +sigs.k8s.io/controller-runtime v0.22.5/go.mod h1:pc5SoYWnWI6I+cBHYYdZ7B6YHZVY5xNfll88JB+vniI= sigs.k8s.io/controller-tools v0.16.4 h1:VXmar78eDXbx1by/H09ikEq1hiq3bqInxuV3lMr3GmQ= sigs.k8s.io/controller-tools v0.16.4/go.mod h1:kcsZyYMXiOFuBhofSPtkB90zTSxVRxVVyvtKQcx3q1A= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/pkg/api/handlers/nanobotagent.go b/pkg/api/handlers/nanobotagent.go index a470dd0513..117b54dba6 100644 --- a/pkg/api/handlers/nanobotagent.go +++ b/pkg/api/handlers/nanobotagent.go @@ -212,7 +212,7 @@ func (h *NanobotAgentHandler) Launch(req api.Context) error { } var errHTTP *types.ErrHTTP if !errors.As(err, &errHTTP) || errHTTP.Code != http.StatusBadRequest || - (!strings.Contains(errHTTP.Message, "NANOBOT_ENV_FILE") && !strings.Contains(errHTTP.Message, "NANOBOT_CONFIG_PATH")) { + (!strings.Contains(errHTTP.Message, "NANOBOT_ENV_FILE") && !strings.Contains(errHTTP.Message, "NANOBOT_CONFIG")) { return err } select { diff --git a/pkg/controller/handlers/nanobotagent/nanobotagent.go b/pkg/controller/handlers/nanobotagent/nanobotagent.go index 3cea7e8915..a0299cdcf7 100644 --- a/pkg/controller/handlers/nanobotagent/nanobotagent.go +++ b/pkg/controller/handlers/nanobotagent/nanobotagent.go @@ -114,9 +114,9 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro }, { MCPHeader: types.MCPHeader{ - Name: "NANOBOT_CONFIG_PATH", + Name: "NANOBOT_CONFIG", Description: "Provider config YAML for Nanobot", - Key: "NANOBOT_CONFIG_PATH", + Key: "NANOBOT_CONFIG", Sensitive: true, Required: true, }, @@ -201,9 +201,9 @@ func (h *Handler) EnsureMCPServer(req router.Request, resp router.Response) erro }, { MCPHeader: types.MCPHeader{ - Name: "NANOBOT_CONFIG_PATH", + Name: "NANOBOT_CONFIG", Description: "Provider config YAML for Nanobot", - Key: "NANOBOT_CONFIG_PATH", + Key: "NANOBOT_CONFIG", Sensitive: true, Required: true, }, @@ -294,7 +294,7 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res if !needsRefresh && credEnvFileVars["NANOBOT_DEFAULT_MODEL"] == llmDefault && credEnvFileVars["NANOBOT_DEFAULT_MINI_MODEL"] == miniDefault && - cred.Env["NANOBOT_CONFIG_PATH"] == providerYAML { + cred.Env["NANOBOT_CONFIG"] == providerYAML { // Credentials are up to date return nil } @@ -377,8 +377,8 @@ func (h *Handler) ensureCredentials(ctx context.Context, req router.Request, res ToolName: mcpServerName, Type: gptscript.CredentialTypeTool, Env: map[string]string{ - "NANOBOT_ENV_FILE": strings.Join(envFileLines, "\n"), - "NANOBOT_CONFIG_PATH": providerYAML, + "NANOBOT_ENV_FILE": strings.Join(envFileLines, "\n"), + "NANOBOT_CONFIG": providerYAML, }, }); err != nil { return fmt.Errorf("failed to create credential: %w", err) diff --git a/pkg/controller/handlers/toolreference/toolreference.go b/pkg/controller/handlers/toolreference/toolreference.go index 84b105f925..efa19a0d23 100644 --- a/pkg/controller/handlers/toolreference/toolreference.go +++ b/pkg/controller/handlers/toolreference/toolreference.go @@ -397,6 +397,7 @@ func (h *Handler) BackPopulateModels(req router.Request, _ router.Response) erro if err != nil { return err } + var credEnv map[string]string if len(mps.RequiredConfigurationParameters) > 0 { cred, err := h.gptClient.RevealCredential(req.Ctx, []string{string(toolRef.UID), system.GenericModelProviderCredentialContext}, toolRef.Name) if err != nil { @@ -406,6 +407,7 @@ func (h *Handler) BackPopulateModels(req router.Request, _ router.Response) erro } return err } + credEnv = cred.Env mps, err = providers.ConvertModelProviderToolRef(*toolRef, cred.Env) if err != nil { return err @@ -424,7 +426,7 @@ func (h *Handler) BackPopulateModels(req router.Request, _ router.Response) erro } } - availableModels, err := h.dispatcher.ModelsForProvider(req.Ctx, h.gptClient, req.Namespace, req.Name) + availableModels, err := h.dispatcher.ModelsForProviderWithEnv(req.Ctx, h.gptClient, req.Namespace, req.Name, credEnv) if err != nil { // Don't error and retry because it will likely fail again. Log the error, and the user can re-sync manually. // Also, the toolRef.Status.Error field will bubble up to the user in the UI. diff --git a/pkg/gateway/server/llmproxy.go b/pkg/gateway/server/llmproxy.go index ae803bbede..ba8460fc70 100644 --- a/pkg/gateway/server/llmproxy.go +++ b/pkg/gateway/server/llmproxy.go @@ -142,6 +142,30 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { } body["model"] = model + + // Evaluate message policies. + var ( + outputPolicies []messagepolicy.ApplicablePolicy + conversationHistory []messagepolicy.ConversationMessage + inputPolicyReplacement string + ) + messagePolicyHelper := s.messagePolicyHelper + if shouldSkipMessagePolicyEnforcement(req.Request) { + messagePolicyHelper = nil + } + if messagePolicyHelper != nil && token.UserID != "" { + userInfo := &user.DefaultInfo{ + UID: token.UserID, + Groups: token.UserGroups, + } + outputPolicies, conversationHistory, inputPolicyReplacement, err = applyMessagePolicies( + req.Context(), messagePolicyHelper, userInfo, req.GatewayClient, body, token.ProjectID, token.ThreadID, + ) + if err != nil { + return err + } + } + b, err := json.Marshal(body) if err != nil { return err @@ -171,11 +195,17 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { (&httputil.ReverseProxy{ Director: llmTransformRequest(u, credEnv), ModifyResponse: (&responseModifier{ - userID: token.UserID, - runID: token.RunID, - model: model, - client: req.GatewayClient, - personalToken: personalToken, + userID: token.UserID, + runID: token.RunID, + model: model, + client: req.GatewayClient, + personalToken: personalToken, + projectID: token.ProjectID, + threadID: token.ThreadID, + inputPolicyReplacement: inputPolicyReplacement, + messagePolicyHelper: messagePolicyHelper, + outputPolicies: outputPolicies, + conversationHistory: conversationHistory, }).modifyResponse, }).ServeHTTP(req.ResponseWriter, req.Request) @@ -988,7 +1018,6 @@ func (l *llmProviderProxy) proxy(req api.Context) error { messagePolicyHelper = l.messagePolicyHelper outputPolicies []messagepolicy.ApplicablePolicy conversationHistory []messagepolicy.ConversationMessage - bodyModified bool inputPolicyReplacement string ) if shouldSkipMessagePolicyEnforcement(req.Request) { @@ -997,69 +1026,13 @@ func (l *llmProviderProxy) proxy(req api.Context) error { if messagePolicyHelper != nil && req.User.GetUID() != "" { var bodyMap map[string]any if err := json.Unmarshal(body, &bodyMap); err == nil { - // Evaluate user message against applicable input policies. - inputPolicies, err := messagePolicyHelper.GetApplicablePolicies(req.User, types2.PolicyDirectionUserMessage) - if err != nil { - return fmt.Errorf("failed to get applicable input policies: %w", err) - } - - if len(inputPolicies) > 0 { - rawMessages := extractRawMessages(bodyMap) - if len(rawMessages) > 0 { - history, lastUserMsg, lastUserIdx := parseMessagesFromBody(rawMessages) - // Only evaluate input policies when the user text message is the - // last message in the conversation. If there are messages after it - // (assistant responses, tool results, etc.), this is a tool-calling - // continuation and the user text has already been evaluated. - if lastUserIdx == len(rawMessages)-1 { - violations := messagePolicyHelper.EvaluateMessage(req.Context(), inputPolicies, history, lastUserMsg, types2.PolicyDirectionUserMessage) - if len(violations) > 0 { - // Log each violation (non-fatal on error). - blockedContent, _ := json.Marshal(map[string]string{"message": lastUserMsg}) - for _, v := range violations { - logViolation(req.Context(), req.GatewayClient, v, req.User.GetUID(), string(types2.PolicyDirectionUserMessage), blockedContent, "", "") - } - - var explanations []string - for _, v := range violations { - explanations = append(explanations, v.Explanation) - } - - // Message for the LLM: instruct it to respond with a - // short refusal so the user sees a clear denial. - llmReplacement := `Please respond to the user with exactly: "Sorry, I can't help with that."` - - // Message for the user: shown directly in the UI's - // "Policy Violation" box with the explanation. - // The [policy-violation] prefix is used by the frontend - // to detect and style this as a policy violation. - userReplacement := fmt.Sprintf( - "[policy-violation] %s", - strings.Join(explanations, "\n"), - ) - - if msgMap, ok := rawMessages[lastUserIdx].(map[string]any); ok { - msgMap["content"] = llmReplacement - bodyModified = true - inputPolicyReplacement = userReplacement - } - } - } - } - } - - // Check for output (tool-call) policies. - outputPolicies, err = messagePolicyHelper.GetApplicablePolicies(req.User, types2.PolicyDirectionToolCalls) + outputPolicies, conversationHistory, inputPolicyReplacement, err = applyMessagePolicies( + req.Context(), messagePolicyHelper, req.User, req.GatewayClient, bodyMap, "", "", + ) if err != nil { - return fmt.Errorf("failed to get applicable output policies: %w", err) - } - if len(outputPolicies) > 0 { - rawMessages := extractRawMessages(bodyMap) - conversationHistory, _, _ = parseMessagesFromBody(rawMessages) + return err } - - // Re-serialize the body if input policies modified it. - if bodyModified { + if inputPolicyReplacement != "" { b, err := json.Marshal(bodyMap) if err != nil { return fmt.Errorf("failed to marshal modified body: %w", err) @@ -1109,6 +1082,64 @@ func (l *llmProviderProxy) proxy(req api.Context) error { return nil } +// applyMessagePolicies evaluates input and output message policies against body, modifying +// it in-place if an input policy is violated (replacing the last user message with an LLM +// refusal). Returns the output policies to enforce on the response, the conversation history +// for output policy evaluation, the user-facing replacement text to surface via response +// header, and any error. +func applyMessagePolicies( + ctx context.Context, + helper *messagepolicy.Helper, + userInfo user.Info, + gatewayClient *client.Client, + body map[string]any, + projectID, threadID string, +) ([]messagepolicy.ApplicablePolicy, []messagepolicy.ConversationMessage, string, error) { + inputPolicies, err := helper.GetApplicablePolicies(userInfo, types2.PolicyDirectionUserMessage) + if err != nil { + return nil, nil, "", fmt.Errorf("failed to get applicable input policies: %w", err) + } + + var inputPolicyReplacement string + if len(inputPolicies) > 0 { + rawMessages := extractRawMessages(body) + if len(rawMessages) > 0 { + history, lastUserMsg, lastUserIdx := parseMessagesFromBody(rawMessages) + // Only evaluate when the user message is last in the conversation. If there are + // messages after it (assistant responses, tool results, etc.), this is a + // tool-calling continuation and the user text has already been evaluated. + if lastUserIdx == len(rawMessages)-1 { + violations := helper.EvaluateMessage(ctx, inputPolicies, history, lastUserMsg, types2.PolicyDirectionUserMessage) + if len(violations) > 0 { + blockedContent, _ := json.Marshal(map[string]string{"message": lastUserMsg}) + var explanations []string + for _, v := range violations { + logViolation(ctx, gatewayClient, v, userInfo.GetUID(), string(types2.PolicyDirectionUserMessage), blockedContent, projectID, threadID) + explanations = append(explanations, v.Explanation) + } + if msgMap, ok := rawMessages[lastUserIdx].(map[string]any); ok { + msgMap["content"] = `Please respond to the user with exactly: "Sorry, I can't help with that."` + inputPolicyReplacement = fmt.Sprintf("[policy-violation] %s", strings.Join(explanations, "\n")) + } + } + } + } + } + + outputPolicies, err := helper.GetApplicablePolicies(userInfo, types2.PolicyDirectionToolCalls) + if err != nil { + return nil, nil, "", fmt.Errorf("failed to get applicable output policies: %w", err) + } + + var conversationHistory []messagepolicy.ConversationMessage + if len(outputPolicies) > 0 { + rawMessages := extractRawMessages(body) + conversationHistory, _, _ = parseMessagesFromBody(rawMessages) + } + + return outputPolicies, conversationHistory, inputPolicyReplacement, nil +} + func shouldSkipMessagePolicyEnforcement(req *http.Request) bool { if req == nil { return false diff --git a/pkg/messagepolicy/evaluate.go b/pkg/messagepolicy/evaluate.go index bbed066dbe..700ec188a7 100644 --- a/pkg/messagepolicy/evaluate.go +++ b/pkg/messagepolicy/evaluate.go @@ -11,6 +11,7 @@ import ( "strings" "sync" + nanobottypes "github.com/nanobot-ai/nanobot/pkg/types" "github.com/obot-platform/obot/apiclient/types" "github.com/obot-platform/obot/pkg/alias" "github.com/obot-platform/obot/pkg/gateway/server/dispatcher" @@ -48,6 +49,7 @@ type resolvedModel struct { targetModel string providerURL string credHeaders map[string]string + dialect string } // EvaluateMessage runs all applicable policies against a message in parallel. @@ -186,8 +188,8 @@ func (h *Helper) resolveModelByAlias(ctx context.Context, aliasType types.Defaul credHeaders[fmt.Sprintf("X-Obot-%s", k)] = v } - // Mirror the path logic from dispatcher.TransformRequest: only add /v1 if the URL has no path. - if providerURL.Path == "" { + // only add /v1 if the URL has no path. + if providerURL.Path == "" || providerURL.Path == "/" { providerURL.Path = "/v1" } @@ -195,6 +197,7 @@ func (h *Helper) resolveModelByAlias(ctx context.Context, aliasType types.Defaul targetModel: model.Spec.Manifest.TargetModel, providerURL: providerURL.String(), credHeaders: credHeaders, + dialect: model.Spec.Manifest.Dialect, }, nil } @@ -212,10 +215,34 @@ type chatCompletionRequest struct { Stream bool `json:"stream"` } -// callLLM makes a streaming chat completion call to the resolved model provider. -// It uses streaming because that matches normal Obot request patterns through -// the model provider proxies. +// bifrostLLMRequest is a minimal Bifrost-compatible /v1/responses request body. +// The daemon overrides the Provider field internally, so it does not need to be set. +type bifrostLLMRequest struct { + Model string `json:"model"` + Input []bifrostMessage `json:"input"` + Params *bifrostParams `json:"params,omitempty"` +} + +type bifrostMessage struct { + Role string `json:"role"` + Content string `json:"content"` +} + +type bifrostParams struct { + Instructions string `json:"instructions,omitempty"` +} + +// callLLM makes a streaming LLM call to the resolved model provider, using the +// appropriate API format for the provider's dialect. func (h *Helper) callLLM(ctx context.Context, resolved *resolvedModel, messages []chatMessage) (string, error) { + if resolved.dialect == string(nanobottypes.DialectBifrostRequest) { + return h.callLLMBifrost(ctx, resolved, messages) + } + return h.callLLMChatCompletions(ctx, resolved, messages) +} + +// callLLMChatCompletions calls the provider using the OpenAI chat completions format. +func (h *Helper) callLLMChatCompletions(ctx context.Context, resolved *resolvedModel, messages []chatMessage) (string, error) { reqBody := chatCompletionRequest{ Model: resolved.targetModel, Messages: messages, @@ -230,17 +257,81 @@ func (h *Helper) callLLM(ctx context.Context, resolved *resolvedModel, messages reqURL := resolved.providerURL + "/chat/completions" log.Debugf("Making LLM call to model=%s url=%s", resolved.targetModel, reqURL) - req, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, bytes.NewReader(body)) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, bytes.NewReader(body)) + if err != nil { + return "", fmt.Errorf("failed to create request: %w", err) + } + + httpReq.Header.Set("Content-Type", "application/json") + for k, v := range resolved.credHeaders { + httpReq.Header.Set(k, v) + } + + resp, err := http.DefaultClient.Do(httpReq) + if err != nil { + log.Errorf("LLM call to model=%s failed: %v", resolved.targetModel, err) + return "", fmt.Errorf("LLM call failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + respBody, _ := io.ReadAll(resp.Body) + log.Errorf("LLM call to model=%s returned status %d: %s", resolved.targetModel, resp.StatusCode, string(respBody)) + return "", fmt.Errorf("LLM call returned status %d: %s", resp.StatusCode, string(respBody)) + } + + return readStreamingResponse(resp.Body, func(data string) gjson.Result { + return gjson.Get(data, "choices.0.delta.content") + }) +} + +// callLLMBifrost calls a Bifrost-dialect provider using the /v1/responses endpoint. +// The Bifrost daemon overrides the Provider field from its own configuration, so +// the client does not need to specify it. +func (h *Helper) callLLMBifrost(ctx context.Context, resolved *resolvedModel, messages []chatMessage) (string, error) { + var ( + systemPrompt string + input []bifrostMessage + ) + for _, m := range messages { + if m.Role == "system" { + systemPrompt = m.Content + } else { + input = append(input, bifrostMessage(m)) + } + } + + reqBody := bifrostLLMRequest{ + Model: resolved.targetModel, + Input: input, + } + if systemPrompt != "" { + reqBody.Params = &bifrostParams{Instructions: systemPrompt} + } + + body, err := json.Marshal(reqBody) + if err != nil { + return "", fmt.Errorf("failed to marshal bifrost request: %w", err) + } + + reqURL := strings.TrimSuffix(resolved.providerURL, "/") + if !strings.HasSuffix(reqURL, "/v1") { + reqURL += "/v1" + } + reqURL = reqURL + "/responses" + log.Debugf("Making LLM call to model=%s url=%s (bifrost)", resolved.targetModel, reqURL) + + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, bytes.NewReader(body)) if err != nil { return "", fmt.Errorf("failed to create request: %w", err) } - req.Header.Set("Content-Type", "application/json") + httpReq.Header.Set("Content-Type", "application/json") for k, v := range resolved.credHeaders { - req.Header.Set(k, v) + httpReq.Header.Set(k, v) } - resp, err := http.DefaultClient.Do(req) + resp, err := http.DefaultClient.Do(httpReq) if err != nil { log.Errorf("LLM call to model=%s failed: %v", resolved.targetModel, err) return "", fmt.Errorf("LLM call failed: %w", err) @@ -253,12 +344,17 @@ func (h *Helper) callLLM(ctx context.Context, resolved *resolvedModel, messages return "", fmt.Errorf("LLM call returned status %d: %s", resp.StatusCode, string(respBody)) } - return readStreamingResponse(resp.Body) + return readStreamingResponse(resp.Body, func(data string) gjson.Result { + if gjson.Get(data, "type").String() == "response.output_text.delta" { + return gjson.Get(data, "delta") + } + return gjson.Result{} + }) } -// readStreamingResponse reads an SSE stream of OpenAI chat completion chunks -// and accumulates the content delta text into a single string. -func readStreamingResponse(r io.Reader) (string, error) { +// readStreamingResponse reads a generic SSE stream, calling extractDelta for each data line. +// If the returned Result exists, its string value is appended to the output. +func readStreamingResponse(r io.Reader, extractDelta func(data string) gjson.Result) (string, error) { var content strings.Builder scanner := bufio.NewScanner(r) scanner.Buffer(make([]byte, 0, bufio.MaxScanTokenSize), 1024*1024) // 1MB max to handle large SSE data lines @@ -272,9 +368,7 @@ func readStreamingResponse(r io.Reader) (string, error) { if data == "[DONE]" { break } - - delta := gjson.Get(data, "choices.0.delta.content") - if delta.Exists() { + if delta := extractDelta(data); delta.Exists() { content.WriteString(delta.String()) } } diff --git a/pkg/storage/openapi/generated/openapi_generated.go b/pkg/storage/openapi/generated/openapi_generated.go index 8389335d69..19883521a7 100644 --- a/pkg/storage/openapi/generated/openapi_generated.go +++ b/pkg/storage/openapi/generated/openapi_generated.go @@ -24498,6 +24498,13 @@ func schema_pkg_apis_meta_v1_DeleteOptions(ref common.ReferenceCallback) common. }, }, }, + "ignoreStoreReadErrorWithClusterBreakingPotential": { + SchemaProps: spec.SchemaProps{ + Description: "if set to true, it will trigger an unsafe deletion of the resource in case the normal deletion flow fails with a corrupt object error. A resource is considered corrupt if it can not be retrieved from the underlying storage successfully because of a) its data can not be transformed e.g. decryption failure, or b) it fails to decode into an object. NOTE: unsafe deletion ignores finalizer constraints, skips precondition checks, and removes the object from the storage. WARNING: This may potentially break the cluster if the workload associated with the resource being unsafe-deleted relies on normal deletion flow. Use only if you REALLY know what you are doing. The default value is false, and the user must opt in to enable it", + Type: []string{"boolean"}, + Format: "", + }, + }, }, }, }, @@ -26405,16 +26412,46 @@ func schema_k8sio_apimachinery_pkg_version_Info(ref common.ReferenceCallback) co Properties: map[string]spec.Schema{ "major": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Major is the major version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "minor": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Minor is the minor version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMajor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMajor is the major version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMinor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMinor is the minor version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMajor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMajor is the major version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMinor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMinor is the minor version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", }, }, "gitVersion": { From 320a47b0d09e4abd60d0bcf13d531b40de89eade Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Tue, 21 Apr 2026 14:27:31 -0700 Subject: [PATCH 4/8] Update pkg/gateway/server/llmproxy.go Co-authored-by: Donnie Adams --- pkg/gateway/server/llmproxy.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/gateway/server/llmproxy.go b/pkg/gateway/server/llmproxy.go index ba8460fc70..ee6f10cee1 100644 --- a/pkg/gateway/server/llmproxy.go +++ b/pkg/gateway/server/llmproxy.go @@ -149,11 +149,7 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { conversationHistory []messagepolicy.ConversationMessage inputPolicyReplacement string ) - messagePolicyHelper := s.messagePolicyHelper - if shouldSkipMessagePolicyEnforcement(req.Request) { - messagePolicyHelper = nil - } - if messagePolicyHelper != nil && token.UserID != "" { + if s.messagePolicyHelper != nil && token.UserID != "" && !shouldSkipMessagePolicyEnforcement(req.Request) { userInfo := &user.DefaultInfo{ UID: token.UserID, Groups: token.UserGroups, From 0281a847ea192448702655318fa6424c25202282 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Tue, 21 Apr 2026 14:28:15 -0700 Subject: [PATCH 5/8] fix after suggestion applied --- pkg/gateway/server/llmproxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gateway/server/llmproxy.go b/pkg/gateway/server/llmproxy.go index ee6f10cee1..b0df1b1f41 100644 --- a/pkg/gateway/server/llmproxy.go +++ b/pkg/gateway/server/llmproxy.go @@ -155,7 +155,7 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { Groups: token.UserGroups, } outputPolicies, conversationHistory, inputPolicyReplacement, err = applyMessagePolicies( - req.Context(), messagePolicyHelper, userInfo, req.GatewayClient, body, token.ProjectID, token.ThreadID, + req.Context(), s.messagePolicyHelper, userInfo, req.GatewayClient, body, token.ProjectID, token.ThreadID, ) if err != nil { return err From cdbc20f06a0f1704909f33e55bffed126410a872 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Tue, 21 Apr 2026 14:36:43 -0700 Subject: [PATCH 6/8] Revert "Update pkg/gateway/server/llmproxy.go" This reverts commit 320a47b0d09e4abd60d0bcf13d531b40de89eade. --- pkg/gateway/server/llmproxy.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/gateway/server/llmproxy.go b/pkg/gateway/server/llmproxy.go index b0df1b1f41..750848fb1b 100644 --- a/pkg/gateway/server/llmproxy.go +++ b/pkg/gateway/server/llmproxy.go @@ -149,7 +149,11 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { conversationHistory []messagepolicy.ConversationMessage inputPolicyReplacement string ) - if s.messagePolicyHelper != nil && token.UserID != "" && !shouldSkipMessagePolicyEnforcement(req.Request) { + messagePolicyHelper := s.messagePolicyHelper + if shouldSkipMessagePolicyEnforcement(req.Request) { + messagePolicyHelper = nil + } + if messagePolicyHelper != nil && token.UserID != "" { userInfo := &user.DefaultInfo{ UID: token.UserID, Groups: token.UserGroups, From 86ab32655db0c93f6ca61f413129ac82802cd448 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Tue, 21 Apr 2026 14:36:52 -0700 Subject: [PATCH 7/8] Revert "fix after suggestion applied" This reverts commit 0281a847ea192448702655318fa6424c25202282. --- pkg/gateway/server/llmproxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gateway/server/llmproxy.go b/pkg/gateway/server/llmproxy.go index 750848fb1b..ba8460fc70 100644 --- a/pkg/gateway/server/llmproxy.go +++ b/pkg/gateway/server/llmproxy.go @@ -159,7 +159,7 @@ func (s *Server) dispatchLLMProxy(req api.Context) error { Groups: token.UserGroups, } outputPolicies, conversationHistory, inputPolicyReplacement, err = applyMessagePolicies( - req.Context(), s.messagePolicyHelper, userInfo, req.GatewayClient, body, token.ProjectID, token.ThreadID, + req.Context(), messagePolicyHelper, userInfo, req.GatewayClient, body, token.ProjectID, token.ThreadID, ) if err != nil { return err From f9408d90a25247ccfb75d15e6bbf455fa4115808 Mon Sep 17 00:00:00 2001 From: Calvin McLean Date: Wed, 22 Apr 2026 12:07:43 -0700 Subject: [PATCH 8/8] Update Nanobot --- docs/docs/configuration/server-configuration.md | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- pkg/mcp/loader.go | 2 +- pkg/services/config.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/configuration/server-configuration.md b/docs/docs/configuration/server-configuration.md index 92b1f880b8..0783b55806 100644 --- a/docs/docs/configuration/server-configuration.md +++ b/docs/docs/configuration/server-configuration.md @@ -44,8 +44,8 @@ The Obot server is configured via environment variables. The following configura | `OBOT_SERVER_AUDIT_LOGS_COMPRESS_FILE` | Controls whether or not to compress audit log files | `true` | | `OBOT_SERVER_AUDIT_LOGS_USE_PATH_STYLE` | Whether to use path style for S3 | - | | `OBOT_SERVER_MCPBASE_IMAGE` | Deploy MCP servers in the kubernetes cluster or using docker with this base image. | `ghcr.io/obot-platform/mcp-images/phat:v0.20.2` | -| `OBOT_SERVER_MCPREMOTE_SHIM_BASE_IMAGE` | Deploy MCP remote shim servers in the cluster using this base image. | `ghcr.io/nanobot-ai/nanobot:v0.0.68` | -| `OBOT_SERVER_NANOBOT_AGENT_IMAGE` | Deploy the Nanobot agent in the cluster using this image. | `ghcr.io/nanobot-ai/nanobot-agent:v0.0.68` | +| `OBOT_SERVER_MCPREMOTE_SHIM_BASE_IMAGE` | Deploy MCP remote shim servers in the cluster using this base image. | `ghcr.io/nanobot-ai/nanobot:v0.0.69` | +| `OBOT_SERVER_NANOBOT_AGENT_IMAGE` | Deploy the Nanobot agent in the cluster using this image. | `ghcr.io/nanobot-ai/nanobot-agent:v0.0.69` | | `OBOT_SERVER_MCPHTTPWEBHOOK_BASE_IMAGE` | Deploy MCP HTTP webhook servers in the cluster using this base image. | `ghcr.io/obot-platform/mcp-images/http-webhook-mcp-converter:v0.20.2` | | `OBOT_SERVER_MCPRUNTIME_BACKEND` | The runtime backend to use for running MCP servers: docker, kubernetes, or local. | `kubernetes` in the helm chart, `docker` otherwise | | `OBOT_SERVER_MCPCLUSTER_DOMAIN` | The cluster domain to use for MCP services. Only matters if `OBOT_SERVER_MCPBASE_IMAGE` is set. | `cluster.local` | diff --git a/go.mod b/go.mod index 28c95b1ca5..ebf3bbd27a 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de github.com/moby/moby/api v1.52.0-alpha.1 github.com/moby/moby/client v0.1.0-alpha.0 - github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee + github.com/nanobot-ai/nanobot v0.0.69 github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 github.com/obot-platform/kinm v0.0.0-20260420174234-eec2cd66c333 github.com/obot-platform/nah v0.0.0-20260420174246-bea1b9e01234 diff --git a/go.sum b/go.sum index 9d909a16aa..c75a4c6a85 100644 --- a/go.sum +++ b/go.sum @@ -551,8 +551,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee h1:WdMwK6EPGP64+EgoORBJ1IFPvSZApcaoVYh+0Z4Zxh0= -github.com/nanobot-ai/nanobot v0.0.68-0.20260417164855-9212c55c34ee/go.mod h1:y9rGtxA+kJVmtj8RmoHSM6/P4KCwoEtjL6MpARPuJnQ= +github.com/nanobot-ai/nanobot v0.0.69 h1:vOmvcTXFlJkxAKDQvugTHPRLxn0LNbO/Mw9yLhh34DA= +github.com/nanobot-ai/nanobot v0.0.69/go.mod h1:y9rGtxA+kJVmtj8RmoHSM6/P4KCwoEtjL6MpARPuJnQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= diff --git a/pkg/mcp/loader.go b/pkg/mcp/loader.go index ff628f8687..9101ec54d0 100644 --- a/pkg/mcp/loader.go +++ b/pkg/mcp/loader.go @@ -27,7 +27,7 @@ var log = logger.Package() type Options struct { MCPBaseImage string `usage:"The base image to use for MCP containers" default:"ghcr.io/obot-platform/mcp-images/phat:v0.20.2"` MCPHTTPWebhookBaseImage string `usage:"The base image to use for HTTP-based MCP webhook containers" default:"ghcr.io/obot-platform/mcp-images/http-webhook-mcp-converter:v0.20.2"` - MCPRemoteShimBaseImage string `usage:"The base image to use for MCP remote shim containers" default:"ghcr.io/nanobot-ai/nanobot:v0.0.68"` + MCPRemoteShimBaseImage string `usage:"The base image to use for MCP remote shim containers" default:"ghcr.io/nanobot-ai/nanobot:v0.0.69"` MCPNamespace string `usage:"The namespace to use for MCP containers" default:"obot-mcp"` MCPClusterDomain string `usage:"The cluster domain to use for MCP containers" default:"cluster.local"` DisallowLocalhostMCP bool `usage:"Allow MCP containers to run on localhost"` diff --git a/pkg/services/config.go b/pkg/services/config.go index 2d3df6b5c3..a617459005 100644 --- a/pkg/services/config.go +++ b/pkg/services/config.go @@ -125,7 +125,7 @@ type Config struct { NanobotIntegration bool `usage:"Enable Nanobot integration" default:"true"` EnableMessagePolicies bool `usage:"Enable message policies for LLM proxy content enforcement" default:"false"` MCPServerSearchImage string `usage:"Container image for the obot MCP server" default:"ghcr.io/obot-platform/obot-mcp-server:v0.1.1"` - NanobotAgentImage string `usage:"Container image for the Nanobot agent MCP server" default:"ghcr.io/nanobot-ai/nanobot-agent:v0.0.68"` + NanobotAgentImage string `usage:"Container image for the Nanobot agent MCP server" default:"ghcr.io/nanobot-ai/nanobot-agent:v0.0.69"` // Published artifact storage ArtifactStorageProvider string `usage:"Storage provider for published artifacts (s3, gcs, azure, custom)" name:"artifact-storage-provider" env:"OBOT_ARTIFACT_STORAGE_PROVIDER"`