From 9df8433d8b44f404ddfcd1eb8d182b266806a376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 09:59:49 +0200 Subject: [PATCH 01/19] feat(icons): add XAI icon component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/components/icons/XAI.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ui/src/components/icons/XAI.tsx diff --git a/ui/src/components/icons/XAI.tsx b/ui/src/components/icons/XAI.tsx new file mode 100644 index 000000000..a99bc444e --- /dev/null +++ b/ui/src/components/icons/XAI.tsx @@ -0,0 +1,12 @@ +export function XAI({ className }: { className?: string }) { + return ( + + + + + ); +} From 4f426adca2541f29e958cd2bda1355ae42e57a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 10:05:00 +0200 Subject: [PATCH 02/19] docs(examples): add xai modelconfig example with grok-4-1-fast-reasoning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- examples/modelconfig-xai.yaml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 examples/modelconfig-xai.yaml diff --git a/examples/modelconfig-xai.yaml b/examples/modelconfig-xai.yaml new file mode 100644 index 000000000..28b961e99 --- /dev/null +++ b/examples/modelconfig-xai.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Secret +metadata: + name: xai-api-key + namespace: default +type: Opaque +stringData: + apiKey: your-xai-api-key-here +--- +apiVersion: kagent.dev/v1alpha2 +kind: ModelConfig +metadata: + name: grok-4-1-fast-reasoning + namespace: default +spec: + provider: XAI + model: grok-4-1-fast-reasoning + apiKeySecret: xai-api-key + apiKeySecretKey: apiKey + xAI: + temperature: "0.7" + maxTokens: 4096 + topP: "0.9" + tools: + - web_search + - x_search + - code_execution + liveSearchMode: auto From 042c219e7ce7af525bd5f64ec027c2567179214e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 10:12:03 +0200 Subject: [PATCH 03/19] feat(types): add XAI provider support with OpenAI-compatible configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/types/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui/src/types/index.ts b/ui/src/types/index.ts index 4a4dff7b4..3c67ee101 100644 --- a/ui/src/types/index.ts +++ b/ui/src/types/index.ts @@ -108,6 +108,12 @@ export interface AnthropicVertexAIConfigPayload { topK?: number; } +// XAI uses OpenAI-compatible API, so extend OpenAI config and add XAI-specific fields +export interface XAIConfigPayload extends OpenAIConfigPayload { + tools?: string[]; + liveSearchMode?: string; +} + export interface CreateModelConfigRequest { ref: string; provider: Pick; @@ -120,6 +126,7 @@ export interface CreateModelConfigRequest { gemini?: GeminiConfigPayload; geminiVertexAI?: GeminiVertexAIConfigPayload; anthropicVertexAI?: AnthropicVertexAIConfigPayload; + xAI?: XAIConfigPayload; } export interface UpdateModelConfigPayload { @@ -133,6 +140,7 @@ export interface UpdateModelConfigPayload { gemini?: GeminiConfigPayload; geminiVertexAI?: GeminiVertexAIConfigPayload; anthropicVertexAI?: AnthropicVertexAIConfigPayload; + xAI?: XAIConfigPayload; } /** From 2463b33ea7a063a8c84351649c1e06eb9bbfeb1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 10:16:44 +0200 Subject: [PATCH 04/19] feat(providers): add xAI model provider support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/lib/providers.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/src/lib/providers.ts b/ui/src/lib/providers.ts index 79246c174..f8ec0c3e5 100644 --- a/ui/src/lib/providers.ts +++ b/ui/src/lib/providers.ts @@ -1,6 +1,6 @@ -export type BackendModelProviderType = "OpenAI" | "AzureOpenAI" | "Anthropic" | "Ollama" | "Gemini" | "GeminiVertexAI" | "AnthropicVertexAI"; -export const modelProviders = ["OpenAI", "AzureOpenAI", "Anthropic", "Ollama", "Gemini", "GeminiVertexAI", "AnthropicVertexAI"] as const; +export type BackendModelProviderType = "OpenAI" | "AzureOpenAI" | "Anthropic" | "Ollama" | "Gemini" | "GeminiVertexAI" | "AnthropicVertexAI" | "XAI"; +export const modelProviders = ["OpenAI", "AzureOpenAI", "Anthropic", "Ollama", "Gemini", "GeminiVertexAI", "AnthropicVertexAI", "XAI"] as const; export type ModelProviderKey = typeof modelProviders[number]; @@ -62,6 +62,13 @@ export const PROVIDERS_INFO: { modelDocsLink: "https://cloud.google.com/vertex-ai/docs", help: "Configure your Google Cloud project and credentials for Vertex AI." }, + XAI: { + name: "xAI", + type: "XAI", + apiKeyLink: "https://console.x.ai", + modelDocsLink: "https://docs.x.ai/docs/models", + help: "Get your API key from xAI." + }, }; export const isValidProviderInfoKey = (key: string): key is ModelProviderKey => { @@ -87,4 +94,4 @@ export const getProviderFormKey = (providerType: BackendModelProviderType): Mode } } return undefined; -} \ No newline at end of file +} From 66c361ea070ba200f7ca63fdef07f71e667f4d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:22:41 +0200 Subject: [PATCH 05/19] feat(api): add XAI model provider support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/api/v1alpha1/modelconfig_types.go | 21 ++++++++++- go/api/v1alpha1/zz_generated.deepcopy.go | 40 +++++++++++++++++++++ go/api/v1alpha2/modelconfig_types.go | 21 ++++++++++- go/api/v1alpha2/zz_generated.deepcopy.go | 45 ++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/go/api/v1alpha1/modelconfig_types.go b/go/api/v1alpha1/modelconfig_types.go index b37f14b86..ea3f95d1e 100644 --- a/go/api/v1alpha1/modelconfig_types.go +++ b/go/api/v1alpha1/modelconfig_types.go @@ -25,7 +25,7 @@ const ( ) // ModelProvider represents the model provider type -// +kubebuilder:validation:Enum=Anthropic;OpenAI;AzureOpenAI;Ollama;Gemini;GeminiVertexAI;AnthropicVertexAI +// +kubebuilder:validation:Enum=Anthropic;OpenAI;AzureOpenAI;Ollama;Gemini;GeminiVertexAI;AnthropicVertexAI;XAI type ModelProvider string const ( @@ -36,6 +36,7 @@ const ( ModelProviderGemini ModelProvider = "Gemini" ModelProviderGeminiVertexAI ModelProvider = "GeminiVertexAI" ModelProviderAnthropicVertexAI ModelProvider = "AnthropicVertexAI" + ModelProviderXAI ModelProvider = "XAI" ) type BaseVertexAIConfig struct { @@ -202,6 +203,19 @@ type OllamaConfig struct { type GeminiConfig struct{} +// XAIConfig contains xAI-specific configuration options +type XAIConfig struct { + OpenAIConfig `json:",inline"` + + // Server-side tools to enable + // +optional + Tools []string `json:"tools,omitempty"` + + // Live search mode for real-time data retrieval + // +optional + LiveSearchMode string `json:"liveSearchMode,omitempty"` +} + // ModelConfigSpec defines the desired state of ModelConfig. // // +kubebuilder:validation:XValidation:message="provider.openAI must be nil if the provider is not OpenAI",rule="!(has(self.openAI) && self.provider != 'OpenAI')" @@ -211,6 +225,7 @@ type GeminiConfig struct{} // +kubebuilder:validation:XValidation:message="provider.gemini must be nil if the provider is not Gemini",rule="!(has(self.gemini) && self.provider != 'Gemini')" // +kubebuilder:validation:XValidation:message="provider.geminiVertexAI must be nil if the provider is not GeminiVertexAI",rule="!(has(self.geminiVertexAI) && self.provider != 'GeminiVertexAI')" // +kubebuilder:validation:XValidation:message="provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI",rule="!(has(self.anthropicVertexAI) && self.provider != 'AnthropicVertexAI')" +// +kubebuilder:validation:XValidation:message="provider.xAI must be nil if the provider is not XAI",rule="!(has(self.xAI) && self.provider != 'XAI')" type ModelConfigSpec struct { Model string `json:"model"` @@ -262,6 +277,10 @@ type ModelConfigSpec struct { // Anthropic-specific configuration // +optional AnthropicVertexAI *AnthropicVertexAIConfig `json:"anthropicVertexAI,omitempty"` + + // xAI-specific configuration + // +optional + XAI *XAIConfig `json:"xAI,omitempty"` } // Model Configurations diff --git a/go/api/v1alpha1/zz_generated.deepcopy.go b/go/api/v1alpha1/zz_generated.deepcopy.go index f887a5ff2..0295ee3fe 100644 --- a/go/api/v1alpha1/zz_generated.deepcopy.go +++ b/go/api/v1alpha1/zz_generated.deepcopy.go @@ -722,6 +722,11 @@ func (in *ModelConfigSpec) DeepCopyInto(out *ModelConfigSpec) { *out = new(AnthropicVertexAIConfig) (*in).DeepCopyInto(*out) } + if in.XAI != nil { + in, out := &in.XAI, &out.XAI + *out = new(XAIConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelConfigSpec. @@ -1111,3 +1116,38 @@ func (in *ValueSource) DeepCopy() *ValueSource { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XAIConfig) DeepCopyInto(out *XAIConfig) { + *out = *in + if in.Seed != nil { + in, out := &in.Seed, &out.Seed + *out = new(int) + **out = **in + } + if in.N != nil { + in, out := &in.N, &out.N + *out = new(int) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(int) + **out = **in + } + if in.Tools != nil { + in, out := &in.Tools, &out.Tools + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XAIConfig. +func (in *XAIConfig) DeepCopy() *XAIConfig { + if in == nil { + return nil + } + out := new(XAIConfig) + in.DeepCopyInto(out) + return out +} diff --git a/go/api/v1alpha2/modelconfig_types.go b/go/api/v1alpha2/modelconfig_types.go index c6ad1a453..770569d87 100644 --- a/go/api/v1alpha2/modelconfig_types.go +++ b/go/api/v1alpha2/modelconfig_types.go @@ -25,7 +25,7 @@ const ( ) // ModelProvider represents the model provider type -// +kubebuilder:validation:Enum=Anthropic;OpenAI;AzureOpenAI;Ollama;Gemini;GeminiVertexAI;AnthropicVertexAI +// +kubebuilder:validation:Enum=Anthropic;OpenAI;AzureOpenAI;Ollama;Gemini;GeminiVertexAI;AnthropicVertexAI;XAI type ModelProvider string const ( @@ -36,6 +36,7 @@ const ( ModelProviderGemini ModelProvider = "Gemini" ModelProviderGeminiVertexAI ModelProvider = "GeminiVertexAI" ModelProviderAnthropicVertexAI ModelProvider = "AnthropicVertexAI" + ModelProviderXAI ModelProvider = "XAI" ) type BaseVertexAIConfig struct { @@ -210,6 +211,19 @@ type OllamaConfig struct { type GeminiConfig struct{} +// XAIConfig contains xAI-specific configuration options +type XAIConfig struct { + OpenAIConfig `json:",inline"` + + // Server-side tools to enable + // +optional + Tools []string `json:"tools,omitempty"` + + // Live search mode for real-time data retrieval + // +optional + LiveSearchMode string `json:"liveSearchMode,omitempty"` +} + // TLSConfig contains TLS/SSL configuration options for model provider connections. // This enables agents to connect to internal LiteLLM gateways or other providers // that use self-signed certificates or custom certificate authorities. @@ -255,6 +269,7 @@ type TLSConfig struct { // +kubebuilder:validation:XValidation:message="provider.gemini must be nil if the provider is not Gemini",rule="!(has(self.gemini) && self.provider != 'Gemini')" // +kubebuilder:validation:XValidation:message="provider.geminiVertexAI must be nil if the provider is not GeminiVertexAI",rule="!(has(self.geminiVertexAI) && self.provider != 'GeminiVertexAI')" // +kubebuilder:validation:XValidation:message="provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI",rule="!(has(self.anthropicVertexAI) && self.provider != 'AnthropicVertexAI')" +// +kubebuilder:validation:XValidation:message="provider.xAI must be nil if the provider is not XAI",rule="!(has(self.xAI) && self.provider != 'XAI')" // +kubebuilder:validation:XValidation:message="apiKeySecret must be set if apiKeySecretKey is set",rule="!(has(self.apiKeySecretKey) && !has(self.apiKeySecret))" // +kubebuilder:validation:XValidation:message="apiKeySecretKey must be set if apiKeySecret is set",rule="!(has(self.apiKeySecret) && !has(self.apiKeySecretKey))" // +kubebuilder:validation:XValidation:message="caCertSecretKey requires caCertSecretRef",rule="!(has(self.tls) && has(self.tls.caCertSecretKey) && size(self.tls.caCertSecretKey) > 0 && (!has(self.tls.caCertSecretRef) || size(self.tls.caCertSecretRef) == 0))" @@ -306,6 +321,10 @@ type ModelConfigSpec struct { // +optional AnthropicVertexAI *AnthropicVertexAIConfig `json:"anthropicVertexAI,omitempty"` + // xAI-specific configuration + // +optional + XAI *XAIConfig `json:"xAI,omitempty"` + // TLS configuration for provider connections. // Enables agents to connect to internal LiteLLM gateways or other providers // that use self-signed certificates or custom certificate authorities. diff --git a/go/api/v1alpha2/zz_generated.deepcopy.go b/go/api/v1alpha2/zz_generated.deepcopy.go index 87e49ab21..f74dab185 100644 --- a/go/api/v1alpha2/zz_generated.deepcopy.go +++ b/go/api/v1alpha2/zz_generated.deepcopy.go @@ -554,6 +554,11 @@ func (in *ModelConfigSpec) DeepCopyInto(out *ModelConfigSpec) { *out = new(AnthropicVertexAIConfig) (*in).DeepCopyInto(*out) } + if in.XAI != nil { + in, out := &in.XAI, &out.XAI + *out = new(XAIConfig) + (*in).DeepCopyInto(*out) + } if in.TLS != nil { in, out := &in.TLS, &out.TLS *out = new(TLSConfig) @@ -979,3 +984,43 @@ func (in *ValueSource) DeepCopy() *ValueSource { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XAIConfig) DeepCopyInto(out *XAIConfig) { + *out = *in + if in.Seed != nil { + in, out := &in.Seed, &out.Seed + *out = new(int) + **out = **in + } + if in.N != nil { + in, out := &in.N, &out.N + *out = new(int) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(int) + **out = **in + } + if in.ReasoningEffort != nil { + in, out := &in.ReasoningEffort, &out.ReasoningEffort + *out = new(OpenAIReasoningEffort) + **out = **in + } + if in.Tools != nil { + in, out := &in.Tools, &out.Tools + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XAIConfig. +func (in *XAIConfig) DeepCopy() *XAIConfig { + if in == nil { + return nil + } + out := new(XAIConfig) + in.DeepCopyInto(out) + return out +} From 4d2e61ffd9a0b9db8d72a9ad7bf26b34a75d305b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:23:21 +0200 Subject: [PATCH 06/19] feat(agent): add support for XAI model provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/cli/internal/cli/agent/const.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/go/cli/internal/cli/agent/const.go b/go/cli/internal/cli/agent/const.go index 5c64fc9c3..aeda4e5ca 100644 --- a/go/cli/internal/cli/agent/const.go +++ b/go/cli/internal/cli/agent/const.go @@ -16,6 +16,7 @@ const ( OPENAI_API_KEY = "OPENAI_API_KEY" ANTHROPIC_API_KEY = "ANTHROPIC_API_KEY" AZUREOPENAI_API_KEY = "AZUREOPENAI_API_KEY" + XAI_API_KEY = "XAI_API_KEY" // kagent env variables KAGENT_DEFAULT_MODEL_PROVIDER = "KAGENT_DEFAULT_MODEL_PROVIDER" @@ -40,6 +41,8 @@ func GetModelProvider() v1alpha2.ModelProvider { return v1alpha2.ModelProviderAnthropic case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAzureOpenAI): return v1alpha2.ModelProviderAzureOpenAI + case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderXAI): + return v1alpha2.ModelProviderXAI default: return v1alpha2.ModelProviderOpenAI } @@ -63,6 +66,8 @@ func GetProviderAPIKey(provider v1alpha2.ModelProvider) string { return ANTHROPIC_API_KEY case v1alpha2.ModelProviderAzureOpenAI: return AZUREOPENAI_API_KEY + case v1alpha2.ModelProviderXAI: + return XAI_API_KEY default: return "" } From f0b9153ddc981df74633325113b89c02a6a1147a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:27:50 +0200 Subject: [PATCH 07/19] feat(client): add xAI model configuration support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/pkg/client/api/types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go/pkg/client/api/types.go b/go/pkg/client/api/types.go index a11ec3c77..b3fc6391d 100644 --- a/go/pkg/client/api/types.go +++ b/go/pkg/client/api/types.go @@ -65,6 +65,7 @@ type CreateModelConfigRequest struct { GeminiParams *v1alpha2.GeminiConfig `json:"gemini,omitempty"` GeminiVertexAIParams *v1alpha2.GeminiVertexAIConfig `json:"geminiVertexAI,omitempty"` AnthropicVertexAIParams *v1alpha2.AnthropicVertexAIConfig `json:"anthropicVertexAI,omitempty"` + XAIParams *v1alpha2.XAIConfig `json:"xAI,omitempty"` } // UpdateModelConfigRequest represents a request to update a model configuration @@ -79,6 +80,7 @@ type UpdateModelConfigRequest struct { GeminiParams *v1alpha2.GeminiConfig `json:"gemini,omitempty"` GeminiVertexAIParams *v1alpha2.GeminiVertexAIConfig `json:"geminiVertexAI,omitempty"` AnthropicVertexAIParams *v1alpha2.AnthropicVertexAIConfig `json:"anthropicVertexAI,omitempty"` + XAIParams *v1alpha2.XAIConfig `json:"xAI,omitempty"` } // Agent types From d65b0dff77a160a04379df4b918179b89330881d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:29:06 +0200 Subject: [PATCH 08/19] feat(adk): add XAI model type with server-side tools support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/internal/adk/types.go | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/go/internal/adk/types.go b/go/internal/adk/types.go index 8935328ac..f7be71583 100644 --- a/go/internal/adk/types.go +++ b/go/internal/adk/types.go @@ -69,6 +69,7 @@ const ( ModelTypeGeminiAnthropic = "gemini_anthropic" ModelTypeOllama = "ollama" ModelTypeGemini = "gemini" + ModelTypeXAI = "xai" ) func (o *OpenAI) MarshalJSON() ([]byte, error) { @@ -185,6 +186,52 @@ func (g *Gemini) GetType() string { return ModelTypeGemini } +// XAI uses OpenAI-compatible API but with a different default baseURL and server-side tools support +type XAI struct { + OpenAI + // Server-side tools (e.g., web_search, x_search, code_execution, collections_search) + Tools []string `json:"tools,omitempty"` + // Live search mode for real-time data retrieval ("off", "auto", "on") + LiveSearchMode string `json:"live_search_mode,omitempty"` +} + +func (x *XAI) MarshalJSON() ([]byte, error) { + // Create a map to ensure we override the embedded BaseModel.Type + result := make(map[string]interface{}) + + // Marshal the embedded OpenAI to get all its fields + openaiBytes, err := json.Marshal(x.OpenAI) + if err != nil { + return nil, err + } + var openaiMap map[string]interface{} + if err := json.Unmarshal(openaiBytes, &openaiMap); err != nil { + return nil, err + } + + // Copy OpenAI fields + for k, v := range openaiMap { + result[k] = v + } + + // Override type to xai (this ensures BaseModel.Type is overridden) + result["type"] = ModelTypeXAI + + // Add XAI-specific fields + if len(x.Tools) > 0 { + result["tools"] = x.Tools + } + if x.LiveSearchMode != "" { + result["live_search_mode"] = x.LiveSearchMode + } + + return json.Marshal(result) +} + +func (x *XAI) GetType() string { + return ModelTypeXAI +} + func ParseModel(bytes []byte) (Model, error) { var model BaseModel if err := json.Unmarshal(bytes, &model); err != nil { @@ -197,6 +244,12 @@ func ParseModel(bytes []byte) (Model, error) { return nil, err } return &gemini, nil + case ModelTypeXAI: + var xai XAI + if err := json.Unmarshal(bytes, &xai); err != nil { + return nil, err + } + return &xai, nil case ModelTypeAzureOpenAI: var azureOpenAI AzureOpenAI if err := json.Unmarshal(bytes, &azureOpenAI); err != nil { @@ -291,3 +344,24 @@ var _ driver.Valuer = &AgentConfig{} func (a AgentConfig) Value() (driver.Value, error) { return json.Marshal(a) } + +// MarshalJSON ensures the Model interface is properly marshaled using its concrete type's MarshalJSON +func (a AgentConfig) MarshalJSON() ([]byte, error) { + type Alias AgentConfig + return json.Marshal(&struct { + Model json.RawMessage `json:"model"` + *Alias + }{ + Model: func() json.RawMessage { + if a.Model == nil { + return nil + } + b, err := json.Marshal(a.Model) + if err != nil { + return nil + } + return b + }(), + Alias: (*Alias)(&a), + }) +} From 0f0f63705c30bb77a9e41ae266a2696dc0371484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:34:05 +0200 Subject: [PATCH 09/19] feat(providers): add XAI model provider support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/internal/httpserver/handlers/modelconfig.go | 15 +++++++++++++++ go/internal/httpserver/handlers/models.go | 11 +++++++++++ go/internal/httpserver/handlers/providers.go | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/go/internal/httpserver/handlers/modelconfig.go b/go/internal/httpserver/handlers/modelconfig.go index 622ca020c..0c2e111ec 100644 --- a/go/internal/httpserver/handlers/modelconfig.go +++ b/go/internal/httpserver/handlers/modelconfig.go @@ -312,6 +312,13 @@ func (h *ModelConfigHandler) HandleCreateModelConfig(w ErrorResponseWriter, r *h } else { log.V(1).Info("No AnthropicVertexAI params provided in create.") } + case v1alpha2.ModelProviderXAI: + if req.XAIParams != nil { + modelConfig.Spec.XAI = req.XAIParams + log.V(1).Info("Assigned XAI params to spec") + } else { + log.V(1).Info("No XAI params provided in create.") + } default: providerConfigErr = fmt.Errorf("unsupported provider type: %s", req.Provider.Type) } @@ -432,6 +439,7 @@ func (h *ModelConfigHandler) HandleUpdateModelConfig(w ErrorResponseWriter, r *h Gemini: nil, GeminiVertexAI: nil, AnthropicVertexAI: nil, + XAI: nil, } // --- Update Secret if API Key is provided (and not Ollama) --- @@ -511,6 +519,13 @@ func (h *ModelConfigHandler) HandleUpdateModelConfig(w ErrorResponseWriter, r *h } else { log.V(1).Info("No AnthropicVertexAI params provided in update.") } + case v1alpha2.ModelProviderXAI: + if req.XAIParams != nil { + modelConfig.Spec.XAI = req.XAIParams + log.V(1).Info("Assigned updated XAI params to spec") + } else { + log.V(1).Info("No XAI params provided in update.") + } default: providerConfigErr = fmt.Errorf("unsupported provider type specified: %s", req.Provider.Type) } diff --git a/go/internal/httpserver/handlers/models.go b/go/internal/httpserver/handlers/models.go index 106f04913..42a31f8f8 100644 --- a/go/internal/httpserver/handlers/models.go +++ b/go/internal/httpserver/handlers/models.go @@ -83,6 +83,17 @@ func (h *ModelHandler) HandleListSupportedModels(w ErrorResponseWriter, r *http. {Name: "claude-sonnet-4@20250514", FunctionCalling: true}, {Name: "claude-3-5-haiku@20241022", FunctionCalling: true}, }, + v1alpha2.ModelProviderXAI: { + {Name: "grok-4-1-fast-reasoning", FunctionCalling: true}, + {Name: "grok-4-1-fast-non-reasoning", FunctionCalling: true}, + {Name: "grok-code-fast-1", FunctionCalling: true}, + {Name: "grok-4-fast-reasoning", FunctionCalling: true}, + {Name: "grok-4-fast-non-reasoning", FunctionCalling: true}, + {Name: "grok-4-0709", FunctionCalling: true}, + {Name: "grok-3-mini", FunctionCalling: true}, + {Name: "grok-3", FunctionCalling: true}, + {Name: "grok-2-vision-1212", FunctionCalling: true}, + }, } log.Info("Successfully listed supported models", "count", len(supportedModels)) diff --git a/go/internal/httpserver/handlers/providers.go b/go/internal/httpserver/handlers/providers.go index 482de2dc9..11d2539e4 100644 --- a/go/internal/httpserver/handlers/providers.go +++ b/go/internal/httpserver/handlers/providers.go @@ -26,7 +26,7 @@ func getRequiredKeysForModelProvider(providerType v1alpha2.ModelProvider) []stri case v1alpha2.ModelProviderAzureOpenAI: // Based on the +required comments in the AzureOpenAIConfig struct definition return []string{"azureEndpoint", "apiVersion"} - case v1alpha2.ModelProviderOpenAI, v1alpha2.ModelProviderAnthropic, v1alpha2.ModelProviderOllama: + case v1alpha2.ModelProviderOpenAI, v1alpha2.ModelProviderAnthropic, v1alpha2.ModelProviderOllama, v1alpha2.ModelProviderXAI: // These providers currently have no fields marked as strictly required in the API definition return []string{} default: @@ -101,6 +101,7 @@ func (h *ProviderHandler) HandleListSupportedModelProviders(w ErrorResponseWrite {v1alpha2.ModelProviderGemini, reflect.TypeOf(v1alpha2.GeminiConfig{})}, {v1alpha2.ModelProviderGeminiVertexAI, reflect.TypeOf(v1alpha2.GeminiVertexAIConfig{})}, {v1alpha2.ModelProviderAnthropicVertexAI, reflect.TypeOf(v1alpha2.AnthropicVertexAIConfig{})}, + {v1alpha2.ModelProviderXAI, reflect.TypeOf(v1alpha2.XAIConfig{})}, } providersResponse := []map[string]interface{}{} From 5629913f1fc78de9cd9e2c9b907e1d31a507db1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:36:27 +0200 Subject: [PATCH 10/19] refactor(api): simplify XAIConfig DeepCopyInto by delegating to OpenAIConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/api/v1alpha1/zz_generated.deepcopy.go | 16 +--------------- go/api/v1alpha2/zz_generated.deepcopy.go | 21 +-------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/go/api/v1alpha1/zz_generated.deepcopy.go b/go/api/v1alpha1/zz_generated.deepcopy.go index 0295ee3fe..eb6b17c61 100644 --- a/go/api/v1alpha1/zz_generated.deepcopy.go +++ b/go/api/v1alpha1/zz_generated.deepcopy.go @@ -1120,21 +1120,7 @@ func (in *ValueSource) DeepCopy() *ValueSource { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XAIConfig) DeepCopyInto(out *XAIConfig) { *out = *in - if in.Seed != nil { - in, out := &in.Seed, &out.Seed - *out = new(int) - **out = **in - } - if in.N != nil { - in, out := &in.N, &out.N - *out = new(int) - **out = **in - } - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(int) - **out = **in - } + in.OpenAIConfig.DeepCopyInto(&out.OpenAIConfig) if in.Tools != nil { in, out := &in.Tools, &out.Tools *out = make([]string, len(*in)) diff --git a/go/api/v1alpha2/zz_generated.deepcopy.go b/go/api/v1alpha2/zz_generated.deepcopy.go index f74dab185..6df8688ed 100644 --- a/go/api/v1alpha2/zz_generated.deepcopy.go +++ b/go/api/v1alpha2/zz_generated.deepcopy.go @@ -988,26 +988,7 @@ func (in *ValueSource) DeepCopy() *ValueSource { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XAIConfig) DeepCopyInto(out *XAIConfig) { *out = *in - if in.Seed != nil { - in, out := &in.Seed, &out.Seed - *out = new(int) - **out = **in - } - if in.N != nil { - in, out := &in.N, &out.N - *out = new(int) - **out = **in - } - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(int) - **out = **in - } - if in.ReasoningEffort != nil { - in, out := &in.ReasoningEffort, &out.ReasoningEffort - *out = new(OpenAIReasoningEffort) - **out = **in - } + in.OpenAIConfig.DeepCopyInto(&out.OpenAIConfig) if in.Tools != nil { in, out := &in.Tools, &out.Tools *out = make([]string, len(*in)) From 07ad473d2b92fa6b4be5e359d0f5b79a7e26766c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:36:56 +0200 Subject: [PATCH 11/19] feat(crd): add xAI provider support and enhanced deployment configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- .../crd/bases/kagent.dev_modelconfigs.yaml | 104 + .../templates/kagent.dev_agents.yaml | 2912 ++++++++++++++--- .../templates/kagent.dev_modelconfigs.yaml | 104 + 3 files changed, 2630 insertions(+), 490 deletions(-) diff --git a/go/config/crd/bases/kagent.dev_modelconfigs.yaml b/go/config/crd/bases/kagent.dev_modelconfigs.yaml index f2fa98881..d69ac811c 100644 --- a/go/config/crd/bases/kagent.dev_modelconfigs.yaml +++ b/go/config/crd/bases/kagent.dev_modelconfigs.yaml @@ -8,6 +8,8 @@ metadata: spec: group: kagent.dev names: + categories: + - kagent kind: ModelConfig listKind: ModelConfigList plural: modelconfigs @@ -254,7 +256,50 @@ spec: - Gemini - GeminiVertexAI - AnthropicVertexAI + - XAI type: string + xAI: + description: xAI-specific configuration + properties: + baseUrl: + description: Base URL for the OpenAI API (overrides default) + type: string + frequencyPenalty: + description: Frequency penalty + type: string + liveSearchMode: + description: Live search mode for real-time data retrieval + type: string + maxTokens: + description: Maximum tokens to generate + type: integer + "n": + description: N value + type: integer + organization: + description: Organization ID for the OpenAI API + type: string + presencePenalty: + description: Presence penalty + type: string + seed: + description: Seed value + type: integer + temperature: + description: Temperature for sampling + type: string + timeout: + description: Timeout + type: integer + tools: + description: Server-side tools to enable + items: + type: string + type: array + topP: + description: Top-p sampling parameter + type: string + type: object required: - model - provider @@ -276,6 +321,8 @@ spec: - message: provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI rule: '!(has(self.anthropicVertexAI) && self.provider != ''AnthropicVertexAI'')' + - message: provider.xAI must be nil if the provider is not XAI + rule: '!(has(self.xAI) && self.provider != ''XAI'')' status: description: ModelConfigStatus defines the observed state of ModelConfig. properties: @@ -574,6 +621,7 @@ spec: - Gemini - GeminiVertexAI - AnthropicVertexAI + - XAI type: string tls: description: |- @@ -613,6 +661,56 @@ spec: Production deployments MUST use proper certificates. type: boolean type: object + xAI: + description: xAI-specific configuration + properties: + baseUrl: + description: Base URL for the OpenAI API (overrides default) + type: string + frequencyPenalty: + description: Frequency penalty + type: string + liveSearchMode: + description: Live search mode for real-time data retrieval + type: string + maxTokens: + description: Maximum tokens to generate + type: integer + "n": + description: N value + type: integer + organization: + description: Organization ID for the OpenAI API + type: string + presencePenalty: + description: Presence penalty + type: string + reasoningEffort: + description: Reasoning effort + enum: + - minimal + - low + - medium + - high + type: string + seed: + description: Seed value + type: integer + temperature: + description: Temperature for sampling + type: string + timeout: + description: Timeout + type: integer + tools: + description: Server-side tools to enable + items: + type: string + type: array + topP: + description: Top-p sampling parameter + type: string + type: object required: - model - provider @@ -634,10 +732,16 @@ spec: - message: provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI rule: '!(has(self.anthropicVertexAI) && self.provider != ''AnthropicVertexAI'')' + - message: provider.xAI must be nil if the provider is not XAI + rule: '!(has(self.xAI) && self.provider != ''XAI'')' - message: apiKeySecret must be set if apiKeySecretKey is set rule: '!(has(self.apiKeySecretKey) && !has(self.apiKeySecret))' - message: apiKeySecretKey must be set if apiKeySecret is set rule: '!(has(self.apiKeySecret) && !has(self.apiKeySecretKey))' + - message: caCertSecretKey requires caCertSecretRef + rule: '!(has(self.tls) && has(self.tls.caCertSecretKey) && size(self.tls.caCertSecretKey) + > 0 && (!has(self.tls.caCertSecretRef) || size(self.tls.caCertSecretRef) + == 0))' - message: caCertSecretKey requires caCertSecretRef (unless disableVerify is true) rule: '!(has(self.tls) && (!has(self.tls.disableVerify) || !self.tls.disableVerify) diff --git a/helm/kagent-crds/templates/kagent.dev_agents.yaml b/helm/kagent-crds/templates/kagent.dev_agents.yaml index aa7f8b351..7b6bbc1ea 100644 --- a/helm/kagent-crds/templates/kagent.dev_agents.yaml +++ b/helm/kagent-crds/templates/kagent.dev_agents.yaml @@ -2382,164 +2382,1088 @@ spec: deployment: description: Trust relationship to the agent. properties: - annotations: - additionalProperties: - type: string - type: object - args: - items: - type: string - type: array - cmd: - type: string - env: - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer required: - - fieldPath + - preference + - weight type: object - x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing - the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + annotations: + additionalProperties: + type: string + type: object + args: + items: + type: string + type: array + cmd: + type: string + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean required: - key type: object @@ -2578,6 +3502,10 @@ spec: additionalProperties: type: string type: object + nodeSelector: + additionalProperties: + type: string + type: object replicas: format: int32 type: integer @@ -2641,6 +3569,44 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + tolerations: + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume @@ -4300,371 +5266,1295 @@ spec: type: string tenant: description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by the plugin + type: string + user: + description: |- + user to map volume access to + Defaults to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. + properties: + fsType: + description: |- + fsType is the filesystem type of the volume that you want to mount. + Tip: Ensure that the filesystem type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + type: string + image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + keyring: + default: /etc/ceph/keyring + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: boolean + secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + required: + - image + - monitors + type: object + scaleIO: + description: |- + scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. + Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. + properties: + fsType: + default: xfs + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". + Default is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. If this is not provided, Login operation will fail. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + default: ThinProvisioned + description: |- + storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes.io/docs/concepts/storage/volumes#secret + properties: + defaultMode: + description: |- + defaultMode is Optional: mode bits used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values + for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the Secret, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes.io/docs/concepts/storage/volumes#secret + type: string + type: object + storageos: + description: |- + storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. + Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. If not specified, default values will be attempted. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string - user: + volumeNamespace: description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references - an already created Quobyte volume by name. + volumeNamespace specifies the scope of the volume within StorageOS. If no + namespace is specified then the Pod's namespace will be used. This allows the + Kubernetes name scoping to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default behaviour. + Set to "default" if you are not using namespaces within StorageOS. + Namespaces that do not pre-exist within StorageOS will be created. type: string - required: - - registry - - volume type: object - rbd: + vsphereVolume: description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. + vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine. + Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type + are redirected to the csi.vsphere.vmware.com CSI driver. properties: fsType: description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string - keyring: - default: /etc/ceph/keyring - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - default: rbd - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + declarative: + properties: + a2aConfig: + description: |- + A2AConfig instantiates an A2A server for this agent, + served on the HTTP port of the kagent kubernetes + controller (default 8083). + The A2A server URL will be served at + :8083/api/a2a// + Read more about the A2A protocol here: https://github.com/google/A2A + properties: + skills: + items: + description: AgentSkill describes a specific capability + or function of the agent. + properties: + description: + description: Description is an optional detailed description + of the skill. + type: string + examples: + description: Examples are optional usage examples. + items: + type: string + type: array + id: + description: ID is the unique identifier for the skill. + type: string + inputModes: + description: InputModes are the supported input data + modes/types. + items: + type: string + type: array + name: + description: Name is the human-readable name of the + skill. + type: string + outputModes: + description: OutputModes are the supported output data + modes/types. + items: + type: string + type: array + tags: + description: Tags are optional tags for categorization. + items: + type: string + type: array + required: + - id + - name + - tags + type: object + minItems: 1 + type: array + type: object + deployment: + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: - default: "" + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight type: object - x-kubernetes-map-type: atomic - user: - default: admin - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: |- - scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. - properties: - fsType: - default: xfs - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of the - ScaleIO API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the - ScaleIO Protection Domain for the configured storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running properties: - name: - default: "" + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL - communication with Gateway, default false - type: boolean - storageMode: - default: ThinProvisioned - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage - Pool associated with the protection domain. - type: string - system: - description: system is the name of the storage system - as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. items: description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether the - Secret or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: |- - storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. - Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running properties: - name: - default: "" + labelSelector: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: |- - vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine. - Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type - are redirected to the csi.vsphere.vmware.com CSI driver. - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy - Based Management (SPBM) profile ID associated - with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage Policy - Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - type: object - declarative: - properties: - a2aConfig: - description: |- - A2AConfig instantiates an A2A server for this agent, - served on the HTTP port of the kagent kubernetes - controller (default 8083). - The A2A server URL will be served at - :8083/api/a2a// - Read more about the A2A protocol here: https://github.com/google/A2A - properties: - skills: - items: - description: AgentSkill describes a specific capability - or function of the agent. - properties: - description: - description: Description is an optional detailed description - of the skill. - type: string - examples: - description: Examples are optional usage examples. - items: - type: string - type: array - id: - description: ID is the unique identifier for the skill. - type: string - inputModes: - description: InputModes are the supported input data - modes/types. - items: - type: string - type: array - name: - description: Name is the human-readable name of the - skill. - type: string - outputModes: - description: OutputModes are the supported output data - modes/types. - items: - type: string - type: array - tags: - description: Tags are optional tags for categorization. - items: - type: string - type: array - required: - - id - - name - - tags - type: object - minItems: 1 - type: array - type: object - deployment: - properties: + type: array + x-kubernetes-list-type: atomic + type: object + type: object annotations: additionalProperties: type: string @@ -4854,6 +6744,10 @@ spec: additionalProperties: type: string type: object + nodeSelector: + additionalProperties: + type: string + type: object replicas: format: int32 type: integer @@ -4917,6 +6811,44 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + tolerations: + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array volumeMounts: items: description: VolumeMount describes a mounting of a Volume diff --git a/helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml b/helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml index f2fa98881..d69ac811c 100644 --- a/helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml +++ b/helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml @@ -8,6 +8,8 @@ metadata: spec: group: kagent.dev names: + categories: + - kagent kind: ModelConfig listKind: ModelConfigList plural: modelconfigs @@ -254,7 +256,50 @@ spec: - Gemini - GeminiVertexAI - AnthropicVertexAI + - XAI type: string + xAI: + description: xAI-specific configuration + properties: + baseUrl: + description: Base URL for the OpenAI API (overrides default) + type: string + frequencyPenalty: + description: Frequency penalty + type: string + liveSearchMode: + description: Live search mode for real-time data retrieval + type: string + maxTokens: + description: Maximum tokens to generate + type: integer + "n": + description: N value + type: integer + organization: + description: Organization ID for the OpenAI API + type: string + presencePenalty: + description: Presence penalty + type: string + seed: + description: Seed value + type: integer + temperature: + description: Temperature for sampling + type: string + timeout: + description: Timeout + type: integer + tools: + description: Server-side tools to enable + items: + type: string + type: array + topP: + description: Top-p sampling parameter + type: string + type: object required: - model - provider @@ -276,6 +321,8 @@ spec: - message: provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI rule: '!(has(self.anthropicVertexAI) && self.provider != ''AnthropicVertexAI'')' + - message: provider.xAI must be nil if the provider is not XAI + rule: '!(has(self.xAI) && self.provider != ''XAI'')' status: description: ModelConfigStatus defines the observed state of ModelConfig. properties: @@ -574,6 +621,7 @@ spec: - Gemini - GeminiVertexAI - AnthropicVertexAI + - XAI type: string tls: description: |- @@ -613,6 +661,56 @@ spec: Production deployments MUST use proper certificates. type: boolean type: object + xAI: + description: xAI-specific configuration + properties: + baseUrl: + description: Base URL for the OpenAI API (overrides default) + type: string + frequencyPenalty: + description: Frequency penalty + type: string + liveSearchMode: + description: Live search mode for real-time data retrieval + type: string + maxTokens: + description: Maximum tokens to generate + type: integer + "n": + description: N value + type: integer + organization: + description: Organization ID for the OpenAI API + type: string + presencePenalty: + description: Presence penalty + type: string + reasoningEffort: + description: Reasoning effort + enum: + - minimal + - low + - medium + - high + type: string + seed: + description: Seed value + type: integer + temperature: + description: Temperature for sampling + type: string + timeout: + description: Timeout + type: integer + tools: + description: Server-side tools to enable + items: + type: string + type: array + topP: + description: Top-p sampling parameter + type: string + type: object required: - model - provider @@ -634,10 +732,16 @@ spec: - message: provider.anthropicVertexAI must be nil if the provider is not AnthropicVertexAI rule: '!(has(self.anthropicVertexAI) && self.provider != ''AnthropicVertexAI'')' + - message: provider.xAI must be nil if the provider is not XAI + rule: '!(has(self.xAI) && self.provider != ''XAI'')' - message: apiKeySecret must be set if apiKeySecretKey is set rule: '!(has(self.apiKeySecretKey) && !has(self.apiKeySecret))' - message: apiKeySecretKey must be set if apiKeySecret is set rule: '!(has(self.apiKeySecret) && !has(self.apiKeySecretKey))' + - message: caCertSecretKey requires caCertSecretRef + rule: '!(has(self.tls) && has(self.tls.caCertSecretKey) && size(self.tls.caCertSecretKey) + > 0 && (!has(self.tls.caCertSecretRef) || size(self.tls.caCertSecretRef) + == 0))' - message: caCertSecretKey requires caCertSecretRef (unless disableVerify is true) rule: '!(has(self.tls) && (!has(self.tls.disableVerify) || !self.tls.disableVerify) From 5c944b676fce7e7feacf0dad69ad2d7dbb4e2b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:38:52 +0200 Subject: [PATCH 12/19] feat(ui): add XAI provider support to model provider combobox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/components/ModelProviderCombobox.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/components/ModelProviderCombobox.tsx b/ui/src/components/ModelProviderCombobox.tsx index 98ede6b02..34a26c9b1 100644 --- a/ui/src/components/ModelProviderCombobox.tsx +++ b/ui/src/components/ModelProviderCombobox.tsx @@ -11,6 +11,7 @@ import { Anthropic } from './icons/Anthropic'; import { Ollama } from './icons/Ollama'; import { Azure } from './icons/Azure'; import { Gemini } from './icons/Gemini'; +import { XAI } from './icons/XAI'; interface ComboboxOption { label: string; // e.g., "OpenAI - gpt-4o" @@ -64,6 +65,7 @@ export function ModelProviderCombobox({ 'Gemini': Gemini, 'GeminiVertexAI': Gemini, 'AnthropicVertexAI': Anthropic, + 'XAI': XAI, }; if (!providerKey || !PROVIDER_ICONS[providerKey]) { return null; @@ -199,4 +201,4 @@ export function ModelProviderCombobox({ ); -} \ No newline at end of file +} From 19b794f0c630f75f80c0f204c7da2fcb43057b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:41:53 +0200 Subject: [PATCH 13/19] feat(onboarding): add XAI model provider support to configuration step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/components/onboarding/steps/ModelConfigStep.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/components/onboarding/steps/ModelConfigStep.tsx b/ui/src/components/onboarding/steps/ModelConfigStep.tsx index 126ba52e4..c7f1cb476 100644 --- a/ui/src/components/onboarding/steps/ModelConfigStep.tsx +++ b/ui/src/components/onboarding/steps/ModelConfigStep.tsx @@ -192,6 +192,7 @@ export function ModelConfigStep({ case 'Gemini': payload.gemini = {}; break; case 'GeminiVertexAI': payload.geminiVertexAI = {}; break; case 'AnthropicVertexAI': payload.anthropicVertexAI = {}; break; + case 'XAI': payload.xAI = {}; break; case 'Ollama': const modelTag = values.modelTag?.trim() || ""; if (modelTag && modelTag !== OLLAMA_DEFAULT_TAG) { From e88d0a9e58f2877f92b8bfb3923cfc1e4a1830e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 11:45:55 +0200 Subject: [PATCH 14/19] feat(models): add XAI provider support and improve array parameter handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- ui/src/app/models/new/page.tsx | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/ui/src/app/models/new/page.tsx b/ui/src/app/models/new/page.tsx index b2a07e07b..cde9bd277 100644 --- a/ui/src/app/models/new/page.tsx +++ b/ui/src/app/models/new/page.tsx @@ -17,7 +17,8 @@ import type { ProviderModelsResponse, GeminiConfigPayload, GeminiVertexAIConfigPayload, - AnthropicVertexAIConfigPayload + AnthropicVertexAIConfigPayload, + XAIConfigPayload } from "@/types"; import { toast } from "sonner"; import { isResourceNameValid, createRFC1123ValidName } from "@/lib/utils"; @@ -68,6 +69,11 @@ const processModelParams = (requiredParams: ModelParam[], optionalParams: ModelP 'stream' ]); + // Special handling for array parameters + const arrayKeys = new Set([ + 'tools' + ]); + Object.entries(allParams).forEach(([key, value]) => { if (numericKeys.has(key)) { const numValue = parseFloat(value); @@ -88,6 +94,10 @@ const processModelParams = (requiredParams: ModelParam[], optionalParams: ModelP console.warn(`Invalid boolean for parameter '${key}': '${value}'. Treating as false.`); providerParams[key] = false; } + } else if (arrayKeys.has(key)) { + if (value.trim() !== '') { + providerParams[key] = value.split(',').map(t => t.trim()).filter(t => t !== ''); + } } else { if (value.trim() !== '') { providerParams[key] = value; @@ -229,7 +239,14 @@ function ModelPageContent() { const initialOptional: ModelParam[] = Object.entries(fetchedParams) .filter(([key]) => !requiredKeys.includes(key)) .map(([key, value], index) => { - const displayValue = (value === null || value === undefined) ? "" : String(value); + let displayValue = ""; + if (value !== null && value !== undefined) { + if (Array.isArray(value)) { + displayValue = value.join(', '); + } else { + displayValue = String(value); + } + } return { id: `fetched-opt-${index}`, key, value: displayValue }; }); @@ -451,6 +468,9 @@ function ModelPageContent() { case 'AnthropicVertexAI': payload.anthropicVertexAI = providerParams as AnthropicVertexAIConfigPayload; break; + case 'XAI': + payload.xAI = providerParams as XAIConfigPayload; + break; default: console.error("Unsupported provider type during payload construction:", providerType); toast.error("Internal error: Unsupported provider type."); @@ -469,6 +489,10 @@ function ModelPageContent() { anthropic: payload.anthropic, azureOpenAI: payload.azureOpenAI, ollama: payload.ollama, + gemini: payload.gemini, + geminiVertexAI: payload.geminiVertexAI, + anthropicVertexAI: payload.anthropicVertexAI, + xAI: payload.xAI, }; const modelConfigRef = k8sRefUtils.toRef(modelConfigNamespace || '', modelConfigName); response = await updateModelConfig(modelConfigRef, updatePayload); @@ -607,8 +631,3 @@ export default function ModelPage() { ); } - - - - - From 1123d675e104f9c1acd9ea05cebee823fc17e43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 12:16:24 +0200 Subject: [PATCH 15/19] feat(translator): add XAI provider support with shared OpenAI-compatible field handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- .../translator/agent/adk_api_translator.go | 125 +++++++++++++----- 1 file changed, 94 insertions(+), 31 deletions(-) diff --git a/go/internal/controller/translator/agent/adk_api_translator.go b/go/internal/controller/translator/agent/adk_api_translator.go index adcee86cc..acee821aa 100644 --- a/go/internal/controller/translator/agent/adk_api_translator.go +++ b/go/internal/controller/translator/agent/adk_api_translator.go @@ -624,6 +624,47 @@ func populateTLSFields(baseModel *adk.BaseModel, tlsConfig *v1alpha2.TLSConfig) } } +// populateOpenAIFields populates OpenAI-compatible fields from OpenAIConfig +// into an OpenAI struct. This is used by both OpenAI and XAI providers. +func populateOpenAIFields(openai *adk.OpenAI, config *v1alpha2.OpenAIConfig, mdd *modelDeploymentData) { + if config == nil { + return + } + + // Only overwrite BaseUrl if a non-empty value is provided (preserves defaults like XAI's https://api.x.ai/v1) + if config.BaseURL != "" { + openai.BaseUrl = config.BaseURL + } + openai.Temperature = utils.ParseStringToFloat64(config.Temperature) + openai.TopP = utils.ParseStringToFloat64(config.TopP) + openai.FrequencyPenalty = utils.ParseStringToFloat64(config.FrequencyPenalty) + openai.PresencePenalty = utils.ParseStringToFloat64(config.PresencePenalty) + + if config.MaxTokens > 0 { + openai.MaxTokens = &config.MaxTokens + } + if config.Seed != nil { + openai.Seed = config.Seed + } + if config.N != nil { + openai.N = config.N + } + if config.Timeout != nil { + openai.Timeout = config.Timeout + } + if config.ReasoningEffort != nil { + effort := string(*config.ReasoningEffort) + openai.ReasoningEffort = &effort + } + + if config.Organization != "" { + mdd.EnvVars = append(mdd.EnvVars, corev1.EnvVar{ + Name: "OPENAI_ORGANIZATION", + Value: config.Organization, + }) + } +} + // addTLSConfiguration adds TLS certificate volume mounts to modelDeploymentData // when TLS configuration is present in the ModelConfig. // Note: TLS configuration fields are now included in agent config JSON via BaseModel, @@ -691,37 +732,7 @@ func (a *adkApiTranslator) translateModel(ctx context.Context, namespace, modelC // Populate TLS fields in BaseModel populateTLSFields(&openai.BaseModel, model.Spec.TLS) - if model.Spec.OpenAI != nil { - openai.BaseUrl = model.Spec.OpenAI.BaseURL - openai.Temperature = utils.ParseStringToFloat64(model.Spec.OpenAI.Temperature) - openai.TopP = utils.ParseStringToFloat64(model.Spec.OpenAI.TopP) - openai.FrequencyPenalty = utils.ParseStringToFloat64(model.Spec.OpenAI.FrequencyPenalty) - openai.PresencePenalty = utils.ParseStringToFloat64(model.Spec.OpenAI.PresencePenalty) - - if model.Spec.OpenAI.MaxTokens > 0 { - openai.MaxTokens = &model.Spec.OpenAI.MaxTokens - } - if model.Spec.OpenAI.Seed != nil { - openai.Seed = model.Spec.OpenAI.Seed - } - if model.Spec.OpenAI.N != nil { - openai.N = model.Spec.OpenAI.N - } - if model.Spec.OpenAI.Timeout != nil { - openai.Timeout = model.Spec.OpenAI.Timeout - } - if model.Spec.OpenAI.ReasoningEffort != nil { - effort := string(*model.Spec.OpenAI.ReasoningEffort) - openai.ReasoningEffort = &effort - } - - if model.Spec.OpenAI.Organization != "" { - modelDeploymentData.EnvVars = append(modelDeploymentData.EnvVars, corev1.EnvVar{ - Name: "OPENAI_ORGANIZATION", - Value: model.Spec.OpenAI.Organization, - }) - } - } + populateOpenAIFields(openai, model.Spec.OpenAI, modelDeploymentData) return openai, modelDeploymentData, nil case v1alpha2.ModelProviderAnthropic: if model.Spec.APIKeySecret != "" { @@ -917,6 +928,58 @@ func (a *adkApiTranslator) translateModel(ctx context.Context, namespace, modelC populateTLSFields(&gemini.BaseModel, model.Spec.TLS) return gemini, modelDeploymentData, nil + case v1alpha2.ModelProviderXAI: + if model.Spec.APIKeySecret != "" { + modelDeploymentData.EnvVars = append(modelDeploymentData.EnvVars, corev1.EnvVar{ + Name: "XAI_API_KEY", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: model.Spec.APIKeySecret, + }, + Key: model.Spec.APIKeySecretKey, + }, + }, + }) + } + xai := &adk.XAI{ + OpenAI: adk.OpenAI{ + BaseModel: adk.BaseModel{ + Model: model.Spec.Model, + Headers: model.Spec.DefaultHeaders, + }, + }, + } + // Populate TLS fields in BaseModel + populateTLSFields(&xai.BaseModel, model.Spec.TLS) + + if model.Spec.XAI != nil { + // Populate OpenAI fields + openaiConfig := &v1alpha2.OpenAIConfig{ + BaseURL: model.Spec.XAI.BaseURL, + Organization: model.Spec.XAI.Organization, + Temperature: model.Spec.XAI.Temperature, + MaxTokens: model.Spec.XAI.MaxTokens, + TopP: model.Spec.XAI.TopP, + FrequencyPenalty: model.Spec.XAI.FrequencyPenalty, + PresencePenalty: model.Spec.XAI.PresencePenalty, + Seed: model.Spec.XAI.Seed, + N: model.Spec.XAI.N, + Timeout: model.Spec.XAI.Timeout, + ReasoningEffort: model.Spec.XAI.ReasoningEffort, + } + populateOpenAIFields(&xai.OpenAI, openaiConfig, modelDeploymentData) + + if len(model.Spec.XAI.Tools) > 0 { + xai.Tools = slices.Clone(model.Spec.XAI.Tools) + } + if model.Spec.XAI.LiveSearchMode != "" { + xai.LiveSearchMode = model.Spec.XAI.LiveSearchMode + } else { + xai.LiveSearchMode = "off" + } + } + return xai, modelDeploymentData, nil } return nil, nil, fmt.Errorf("unknown model provider: %s", model.Spec.Provider) } From 84365844e8c38a3cfa952f98ce65ac40da7ffe69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 12:21:12 +0200 Subject: [PATCH 16/19] feat(types): add XAI model support to AgentConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- .../kagent-adk/src/kagent/adk/types.py | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/python/packages/kagent-adk/src/kagent/adk/types.py b/python/packages/kagent-adk/src/kagent/adk/types.py index 8370c2f9c..d8d4f4ba1 100644 --- a/python/packages/kagent-adk/src/kagent/adk/types.py +++ b/python/packages/kagent-adk/src/kagent/adk/types.py @@ -18,6 +18,7 @@ from .models import AzureOpenAI as OpenAIAzure from .models import OpenAI as OpenAINative +from .models import XAI as XAINative logger = logging.getLogger(__name__) @@ -65,6 +66,13 @@ class OpenAI(BaseLLM): type: Literal["openai"] +class XAI(OpenAI): + tools: list[str] | None = None + live_search_mode: str | None = None + + type: Literal["xai"] + + class AzureOpenAI(BaseLLM): type: Literal["azure_openai"] @@ -92,7 +100,7 @@ class Gemini(BaseLLM): class AgentConfig(BaseModel): - model: Union[OpenAI, Anthropic, GeminiVertexAI, GeminiAnthropic, Ollama, AzureOpenAI, Gemini] = Field( + model: Union[OpenAI, Anthropic, GeminiVertexAI, GeminiAnthropic, Ollama, AzureOpenAI, Gemini, XAI] = Field( discriminator="type" ) description: str @@ -176,6 +184,29 @@ def to_agent(self, name: str) -> Agent: ) elif self.model.type == "gemini": model = self.model.model + elif self.model.type == "xai": + model = XAINative( + type="xai", + base_url=self.model.base_url, + default_headers=extra_headers, + frequency_penalty=self.model.frequency_penalty, + max_tokens=self.model.max_tokens, + model=self.model.model, + n=self.model.n, + presence_penalty=self.model.presence_penalty, + reasoning_effort=self.model.reasoning_effort, + seed=self.model.seed, + temperature=self.model.temperature, + timeout=self.model.timeout, + top_p=self.model.top_p, + # XAI-specific fields (not yet implemented in basic support) + tools=self.model.tools, + live_search_mode=self.model.live_search_mode, + # TLS configuration + tls_disable_verify=self.model.tls_disable_verify, + tls_ca_cert_path=self.model.tls_ca_cert_path, + tls_disable_system_cas=self.model.tls_disable_system_cas, + ) else: raise ValueError(f"Invalid model type: {self.model.type}") return Agent( From 65bb0a3408d4286aa28bdbdd9c4e510e0ba91f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 12:22:08 +0200 Subject: [PATCH 17/19] feat(models): add XAI (xAI Grok) model support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- .../src/kagent/adk/models/_openai.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/python/packages/kagent-adk/src/kagent/adk/models/_openai.py b/python/packages/kagent-adk/src/kagent/adk/models/_openai.py index 2588f39ef..959c024b6 100644 --- a/python/packages/kagent-adk/src/kagent/adk/models/_openai.py +++ b/python/packages/kagent-adk/src/kagent/adk/models/_openai.py @@ -475,3 +475,38 @@ def _client(self) -> AsyncAzureOpenAI: default_headers=self.default_headers, http_client=http_client, ) + + +class XAI(BaseOpenAI): + """XAI (xAI Grok) model implementation.""" + + type: Literal["xai"] + # XAI-specific fields + tools: Optional[list[str]] = None + live_search_mode: Optional[str] = None + + def __init__(self, **data): + """Initialize XAI model with default base URL if not provided.""" + # Set default base URL if not provided or empty + if "base_url" not in data or not data["base_url"]: + data["base_url"] = "https://api.x.ai/v1" + super().__init__(**data) + + @cached_property + def _client(self) -> AsyncOpenAI: + """Get the XAI client with optional custom SSL configuration.""" + http_client = self._create_http_client() + api_key = self.api_key or os.environ.get("XAI_API_KEY") + + return AsyncOpenAI( + api_key=api_key, + base_url=self.base_url or None, + default_headers=self.default_headers, + timeout=self.timeout, + http_client=http_client, + ) + + @classmethod + def supported_models(cls) -> list[str]: + """Returns a list of supported models in regex for LlmRegistry.""" + return [r"grok-.*"] From 91dae1b66d9c92e320b9c7bbccb6ab70df3fad8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 13:18:09 +0200 Subject: [PATCH 18/19] feat(models): add XAI model support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- python/packages/kagent-adk/src/kagent/adk/models/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/packages/kagent-adk/src/kagent/adk/models/__init__.py b/python/packages/kagent-adk/src/kagent/adk/models/__init__.py index 19c7943ba..09810b878 100644 --- a/python/packages/kagent-adk/src/kagent/adk/models/__init__.py +++ b/python/packages/kagent-adk/src/kagent/adk/models/__init__.py @@ -1,3 +1,3 @@ -from ._openai import AzureOpenAI, OpenAI +from ._openai import AzureOpenAI, OpenAI, XAI -__all__ = ["OpenAI", "AzureOpenAI"] +__all__ = ["OpenAI", "AzureOpenAI", "XAI"] From 9fe4e424a43767a39decee06adb77fd76583552d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Daba=C5=A1inskas?= Date: Mon, 24 Nov 2025 13:53:03 +0200 Subject: [PATCH 19/19] feat(modelconfig): add support for embedded struct fields with inline json tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomas Dabašinskas --- go/internal/httpserver/handlers/modelconfig.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/go/internal/httpserver/handlers/modelconfig.go b/go/internal/httpserver/handlers/modelconfig.go index 0c2e111ec..349f4c14a 100644 --- a/go/internal/httpserver/handlers/modelconfig.go +++ b/go/internal/httpserver/handlers/modelconfig.go @@ -168,7 +168,13 @@ func getStructJSONKeys(structType reflect.Type) []string { for i := 0; i < structType.NumField(); i++ { field := structType.Field(i) jsonTag := field.Tag.Get("json") - if jsonTag != "" && jsonTag != "-" { + + // Handle embedded structs (anonymous fields) with json:",inline" + if field.Anonymous && strings.Contains(jsonTag, "inline") { + // Recursively get keys from embedded struct + embeddedKeys := getStructJSONKeys(field.Type) + keys = append(keys, embeddedKeys...) + } else if jsonTag != "" && jsonTag != "-" { tagParts := strings.Split(jsonTag, ",") keys = append(keys, tagParts[0]) }