Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions go/api/config/crd/bases/api.kagent.dev_agents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,35 @@ spec:
commit:
pattern: ^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$
type: string
credentialRef:
description: |-
CredentialRef references a key in a same-namespace Secret whose value is
the base64 of "<username>:<token>" for the URL's host (GitHub takes
"x-access-token:<token>"). The egress gateway sends it as
"Authorization: Basic" on every request the actor makes to that host;
the actor never holds it.
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
x-kubernetes-map-type: atomic
url:
minLength: 1
pattern: ^https?://[^[:space:]]+$
Expand All @@ -397,6 +426,12 @@ spec:
- commit
- url
type: object
x-kubernetes-validations:
- message: credentialRef name and key must not be empty
rule: '!has(self.credentialRef) || (self.credentialRef.name.size()
> 0 && self.credentialRef.key.size() > 0)'
- message: credentialRef requires an https URL
rule: '!has(self.credentialRef) || self.url.startsWith(''https://'')'
oci:
description: OCI is a digest-pinned image reference.
pattern: ^[^[:space:]@]+@sha256:[0-9a-f]{64}$
Expand Down Expand Up @@ -502,6 +537,35 @@ spec:
commit:
pattern: ^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$
type: string
credentialRef:
description: |-
CredentialRef references a key in a same-namespace Secret whose value is
the base64 of "<username>:<token>" for the URL's host (GitHub takes
"x-access-token:<token>"). The egress gateway sends it as
"Authorization: Basic" on every request the actor makes to that host;
the actor never holds it.
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
x-kubernetes-map-type: atomic
url:
minLength: 1
pattern: ^https?://[^[:space:]]+$
Expand All @@ -510,6 +574,12 @@ spec:
- commit
- url
type: object
x-kubernetes-validations:
- message: credentialRef name and key must not be empty
rule: '!has(self.credentialRef) || (self.credentialRef.name.size()
> 0 && self.credentialRef.key.size() > 0)'
- message: credentialRef requires an https URL
rule: '!has(self.credentialRef) || self.url.startsWith(''https://'')'
oci:
description: OCI is a digest-pinned image reference.
pattern: ^[^[:space:]@]+@sha256:[0-9a-f]{64}$
Expand Down
70 changes: 70 additions & 0 deletions go/api/config/crd/bases/api.kagent.dev_agenttemplates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,35 @@ spec:
commit:
pattern: ^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$
type: string
credentialRef:
description: |-
CredentialRef references a key in a same-namespace Secret whose value is
the base64 of "<username>:<token>" for the URL's host (GitHub takes
"x-access-token:<token>"). The egress gateway sends it as
"Authorization: Basic" on every request the actor makes to that host;
the actor never holds it.
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
x-kubernetes-map-type: atomic
url:
minLength: 1
pattern: ^https?://[^[:space:]]+$
Expand All @@ -152,6 +181,12 @@ spec:
- commit
- url
type: object
x-kubernetes-validations:
- message: credentialRef name and key must not be empty
rule: '!has(self.credentialRef) || (self.credentialRef.name.size()
> 0 && self.credentialRef.key.size() > 0)'
- message: credentialRef requires an https URL
rule: '!has(self.credentialRef) || self.url.startsWith(''https://'')'
oci:
description: OCI is a digest-pinned image reference.
pattern: ^[^[:space:]@]+@sha256:[0-9a-f]{64}$
Expand Down Expand Up @@ -255,6 +290,35 @@ spec:
commit:
pattern: ^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$
type: string
credentialRef:
description: |-
CredentialRef references a key in a same-namespace Secret whose value is
the base64 of "<username>:<token>" for the URL's host (GitHub takes
"x-access-token:<token>"). The egress gateway sends it as
"Authorization: Basic" on every request the actor makes to that host;
the actor never holds it.
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
x-kubernetes-map-type: atomic
url:
minLength: 1
pattern: ^https?://[^[:space:]]+$
Expand All @@ -263,6 +327,12 @@ spec:
- commit
- url
type: object
x-kubernetes-validations:
- message: credentialRef name and key must not be empty
rule: '!has(self.credentialRef) || (self.credentialRef.name.size()
> 0 && self.credentialRef.key.size() > 0)'
- message: credentialRef requires an https URL
rule: '!has(self.credentialRef) || self.url.startsWith(''https://'')'
oci:
description: OCI is a digest-pinned image reference.
pattern: ^[^[:space:]@]+@sha256:[0-9a-f]{64}$
Expand Down
9 changes: 9 additions & 0 deletions go/api/v1alpha3/agenttemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ type AgentTemplateSkill struct {
}

// GitArtifact identifies immutable content at a full Git commit ID.
// +kubebuilder:validation:XValidation:rule="!has(self.credentialRef) || (self.credentialRef.name.size() > 0 && self.credentialRef.key.size() > 0)",message="credentialRef name and key must not be empty"
// +kubebuilder:validation:XValidation:rule="!has(self.credentialRef) || self.url.startsWith('https://')",message="credentialRef requires an https URL"
type GitArtifact struct {
// +kubebuilder:validation:Pattern=`^https?://[^[:space:]]+$`
// +kubebuilder:validation:MinLength=1
Expand All @@ -110,6 +112,13 @@ type GitArtifact struct {
// +kubebuilder:validation:Pattern=`^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$`
// +required
Commit string `json:"commit"`
// CredentialRef references a key in a same-namespace Secret whose value is
// the base64 of "<username>:<token>" for the URL's host (GitHub takes
// "x-access-token:<token>"). The egress gateway sends it as
// "Authorization: Basic" on every request the actor makes to that host;
// the actor never holds it.
// +optional
CredentialRef *corev1.SecretKeySelector `json:"credentialRef,omitempty"`
}

// S3Object identifies one immutable S3 object version.
Expand Down
7 changes: 6 additions & 1 deletion go/api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions go/core/internal/translator/adkconfig/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,14 @@ func (c *Builder) compileAgent(ctx context.Context, input *v2translator.AgentInp
stream = modelConfig.Spec.Stream
}
cfg := &adk.AgentConfig{Model: modelRuntime.Model, Description: input.Template.Spec.Description, Instruction: input.Instruction, Stream: stream}
pluginConfig, pluginEgress, err := v2translator.CompileSkillResources(input.Template)
skills, err := v2translator.CompileSkillResources(input.Template)
if err != nil {
return nil, err
}
if len(pluginConfig.Skills) > 0 || len(pluginConfig.Plugins) > 0 {
cfg.AgentPlugins = &pluginConfig
if len(skills.Resources.Skills) > 0 || len(skills.Resources.Plugins) > 0 {
cfg.AgentPlugins = &skills.Resources
}
modelRuntime.Environment = append(modelRuntime.Environment, skills.Environment...)
for _, tool := range input.MCPTools {
headers, credentialEnv, err := c.resolveAgentTemplateHeaders(ctx, input.Template.Namespace, tool.Server.Spec.HeadersFrom)
if err != nil {
Expand All @@ -129,7 +130,7 @@ func (c *Builder) compileAgent(ctx context.Context, input *v2translator.AgentInp
result := &Result{
Config: cfg, Templates: []*v2translator.TemplateConfiguration{input.Template},
Environment: modelRuntime.Environment,
Egress: append(agentConfigDestinations(cfg, modelConfig, modelRuntime.Model), pluginEgress...),
Egress: append(agentConfigDestinations(cfg, modelConfig, modelRuntime.Model), skills.Egress...),
}
if modelConfig != nil {
result.Models = []*v2translator.ResolvedModelConfig{input.ResolvedModelConfig}
Expand Down
9 changes: 5 additions & 4 deletions go/core/internal/translator/claude/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
if err != nil {
return nil, err
}
skillResources, skillEgress, err := v2translator.CompileSkillResources(input.Root.Template)
skills, err := v2translator.CompileSkillResources(input.Root.Template)
if err != nil {
return nil, err
}
Expand All @@ -67,6 +67,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
}
environment := append([]corev1.EnvVar(nil), providerEnvironment...)
environment = append(environment, mcp.environment...)
environment = append(environment, skills.Environment...)
harnessAttributes := v2translator.HarnessResourceAttributes(input.Harness)
for _, variable := range input.Harness.Spec.Env {
if v2translator.IsResourceAttributesVariable(variable.Name) {
Expand Down Expand Up @@ -99,8 +100,8 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
config := claudeconfig.Production(model.Spec.Model, input.Root.Instruction)
config.Agents = localAgents
config.RuntimeTelemetry = runtimeTelemetry
if len(skillResources.Skills) != 0 || len(skillResources.Plugins) != 0 {
config.SkillResources = &skillResources
if len(skills.Resources.Skills) != 0 || len(skills.Resources.Plugins) != 0 {
config.SkillResources = &skills.Resources
}
config.MCPServers = mcp.servers
if err := config.Validate(); err != nil {
Expand All @@ -123,7 +124,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
return nil, err
}

egress = append(egress, skillEgress...)
egress = append(egress, skills.Egress...)
egress = append(egress, mcp.egress...)
egress = append(egress, telemetryConfig.Destinations()...)
egress = append(egress, "http://"+utils.GetControllerName()+"."+utils.GetResourceNamespace()+":8083")
Expand Down
9 changes: 5 additions & 4 deletions go/core/internal/translator/codex/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
if err != nil {
return nil, err
}
skillResources, skillEgress, err := v2translator.CompileSkillResources(input.Root.Template)
skills, err := v2translator.CompileSkillResources(input.Root.Template)
if err != nil {
return nil, err
}
Expand All @@ -82,6 +82,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
return nil, err
}
environment := append(providerEnvironment, mcp.environment...)
environment = append(environment, skills.Environment...)
harnessAttributes := v2translator.HarnessResourceAttributes(input.Harness)
for _, variable := range input.Harness.Spec.Env {
if v2translator.IsResourceAttributesVariable(variable.Name) {
Expand Down Expand Up @@ -115,8 +116,8 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
cfg.Telemetry.Logs = &codexconfig.OTLPExporter{Endpoint: logConfig.Endpoint, Protocol: logConfig.Protocol}
}
}
if len(skillResources.Skills) != 0 || len(skillResources.Plugins) != 0 {
cfg.SkillResources = &skillResources
if len(skills.Resources.Skills) != 0 || len(skills.Resources.Plugins) != 0 {
cfg.SkillResources = &skills.Resources
}
if err := cfg.Validate(); err != nil {
return nil, v2translator.NewValidationError("invalid compiled Codex configuration: %v", err)
Expand All @@ -137,7 +138,7 @@ func (c *Compiler) Compile(ctx context.Context, input *v2translator.HarnessInput
if err != nil {
return nil, err
}
egress = append(egress, skillEgress...)
egress = append(egress, skills.Egress...)
egress = append(egress, mcp.egress...)
egress = append(egress, telemetryConfig.Destinations()...)
egress = append(egress, "http://"+utils.GetControllerName()+"."+utils.GetResourceNamespace()+":8083")
Expand Down
Loading
Loading