Skip to content

Commit c46cd2f

Browse files
authored
Merge branch 'main' into fix/go-allowed-headers-mcp
2 parents 9f58d1a + 6da271a commit c46cd2f

73 files changed

Lines changed: 4481 additions & 2051 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,15 @@ updates:
4848
- "minor"
4949
- "patch"
5050

51-
# Python (uv) — workspace root and all packages
51+
# Python (uv) — single workspace root.
52+
# Dependabot's native `uv` ecosystem detects workspace members through
53+
# python/pyproject.toml's [tool.uv.workspace] section and updates the
54+
# root python/uv.lock alongside any member's pyproject.toml in the
55+
# same PR. Listing each member as its own directory caused Dependabot
56+
# to open per-member PRs that did not refresh the root lockfile,
57+
# which then failed `uv sync --locked` in CI.
5258
- package-ecosystem: "uv"
53-
directories:
54-
- "/python"
55-
- "/python/packages/kagent-adk"
56-
- "/python/packages/kagent-core"
57-
- "/python/packages/kagent-skills"
58-
- "/python/packages/kagent-crewai"
59-
- "/python/packages/kagent-langgraph"
60-
- "/python/packages/kagent-openai"
61-
- "/python/packages/agentsts-core"
62-
- "/python/packages/agentsts-adk"
59+
directory: "/python"
6360
schedule:
6461
interval: "weekly"
6562
day: "monday"
@@ -73,7 +70,24 @@ updates:
7370
- "peterj"
7471
- "yuval-k"
7572
groups:
73+
python-opentelemetry:
74+
applies-to: version-updates
75+
patterns:
76+
- "opentelemetry-*"
77+
update-types:
78+
- "minor"
79+
- "patch"
80+
python-google-ai:
81+
applies-to: version-updates
82+
patterns:
83+
- "google-adk"
84+
- "google-genai"
85+
- "google-auth"
86+
update-types:
87+
- "minor"
88+
- "patch"
7689
python-minor-patch:
90+
applies-to: version-updates
7791
patterns:
7892
- "*"
7993
update-types:
@@ -93,6 +107,13 @@ updates:
93107
prefix: "chore(deps):"
94108
reviewers:
95109
- "peterj"
110+
ignore:
111+
# Suppress major UI dependency bumps (e.g., Next.js, React) until
112+
# the frontend is ready for those migrations. Minor/patch updates
113+
# still flow through via the npm-minor-patch group below.
114+
- dependency-name: "*"
115+
update-types:
116+
- "version-update:semver-major"
96117
groups:
97118
npm-minor-patch:
98119
patterns:

go/adk/pkg/telemetry/tracing.go

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ package telemetry
22

33
import (
44
"context"
5+
"fmt"
56
"net/url"
67
"os"
78
"strings"
89
"time"
910

1011
"go.opentelemetry.io/otel"
1112
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
13+
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
1214
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
15+
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
1316
"go.opentelemetry.io/otel/propagation"
1417
sdklog "go.opentelemetry.io/otel/sdk/log"
1518
"go.opentelemetry.io/otel/sdk/resource"
@@ -54,14 +57,14 @@ func Init(ctx context.Context, serviceName string, serviceNamespace string) (shu
5457
loggingEnabled := strings.EqualFold(strings.TrimSpace(os.Getenv("OTEL_LOGGING_ENABLED")), "true")
5558
otelOpts := []adktelemetry.Option{adktelemetry.WithResource(telemetryResource)}
5659
if tracingEnabled {
57-
tracerProvider, tpErr := newGRPCTracerProvider(ctx, telemetryResource)
60+
tracerProvider, tpErr := newTracerProvider(ctx, telemetryResource)
5861
if tpErr != nil {
5962
return nil, true, tpErr
6063
}
6164
otelOpts = append(otelOpts, adktelemetry.WithTracerProvider(tracerProvider))
6265
}
6366
if loggingEnabled {
64-
loggerProvider, lpErr := newGRPCLoggerProvider(ctx, telemetryResource)
67+
loggerProvider, lpErr := newLoggerProvider(ctx, telemetryResource)
6568
if lpErr != nil {
6669
return nil, true, lpErr
6770
}
@@ -87,35 +90,66 @@ func isTelemetryEnabled() bool {
8790
strings.EqualFold(strings.TrimSpace(os.Getenv("OTEL_LOGGING_ENABLED")), "true")
8891
}
8992

90-
func newGRPCTracerProvider(ctx context.Context, res *resource.Resource) (*sdktrace.TracerProvider, error) {
91-
traceEndpoint := strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"))
92-
if traceEndpoint == "" {
93-
traceEndpoint = strings.TrimSpace(os.Getenv("OTEL_TRACING_EXPORTER_OTLP_ENDPOINT"))
93+
// resolveOTLPProtocol returns the OTLP protocol for the given signal,
94+
// following OTel spec precedence: signal-specific > general > default (grpc).
95+
func resolveOTLPProtocol(signal string) string {
96+
if v := strings.TrimSpace(os.Getenv(fmt.Sprintf("OTEL_EXPORTER_OTLP_%s_PROTOCOL", signal))); v != "" {
97+
return strings.ToLower(v)
9498
}
95-
if traceEndpoint == "" {
96-
traceEndpoint = strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"))
99+
if v := strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL")); v != "" {
100+
return strings.ToLower(v)
97101
}
102+
return "grpc"
103+
}
104+
105+
func resolveEndpoint(signalEnvSuffix string) string {
106+
endpoint := strings.TrimSpace(os.Getenv(fmt.Sprintf("OTEL_EXPORTER_OTLP_%s_ENDPOINT", signalEnvSuffix)))
107+
if endpoint == "" {
108+
endpoint = strings.TrimSpace(os.Getenv(fmt.Sprintf("OTEL_%s_EXPORTER_OTLP_ENDPOINT", signalEnvSuffix)))
109+
}
110+
if endpoint == "" {
111+
endpoint = strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"))
112+
}
113+
return endpoint
114+
}
98115

99-
opts := []otlptracegrpc.Option{
100-
// Retry on transient failures
101-
otlptracegrpc.WithRetry(otlptracegrpc.RetryConfig{
116+
func newTracerProvider(ctx context.Context, res *resource.Resource) (*sdktrace.TracerProvider, error) {
117+
protocol := resolveOTLPProtocol("TRACES")
118+
traceEndpoint := resolveEndpoint("TRACES")
119+
120+
var exporter sdktrace.SpanExporter
121+
var err error
122+
123+
switch protocol {
124+
case "http/protobuf":
125+
var opts []otlptracehttp.Option
126+
if traceEndpoint != "" {
127+
opts = append(opts, otlptracehttp.WithEndpointURL(traceEndpoint))
128+
}
129+
opts = append(opts, otlptracehttp.WithRetry(otlptracehttp.RetryConfig{
102130
Enabled: true,
103131
InitialInterval: 1 * time.Second,
104132
MaxInterval: 5 * time.Second,
105133
MaxElapsedTime: 30 * time.Second,
106-
}),
107-
}
108-
if traceEndpoint != "" {
109-
// If the endpoint has a valid scheme, host, port, path ("scheme://host:port/path"), set endpoint url.
110-
if u, err := url.Parse(traceEndpoint); err == nil && u.Scheme != "" && u.Host != "" {
111-
opts = append(opts, otlptracegrpc.WithEndpointURL(u.String()))
112-
} else {
113-
// Else, treat it as a regular endpoint ("example.com:4317", no scheme or path)
114-
opts = append(opts, otlptracegrpc.WithEndpoint(traceEndpoint))
134+
}))
135+
exporter, err = otlptracehttp.New(ctx, opts...)
136+
default:
137+
var opts []otlptracegrpc.Option
138+
opts = append(opts, otlptracegrpc.WithRetry(otlptracegrpc.RetryConfig{
139+
Enabled: true,
140+
InitialInterval: 1 * time.Second,
141+
MaxInterval: 5 * time.Second,
142+
MaxElapsedTime: 30 * time.Second,
143+
}))
144+
if traceEndpoint != "" {
145+
if u, parseErr := url.Parse(traceEndpoint); parseErr == nil && u.Scheme != "" && u.Host != "" {
146+
opts = append(opts, otlptracegrpc.WithEndpointURL(u.String()))
147+
} else {
148+
opts = append(opts, otlptracegrpc.WithEndpoint(traceEndpoint))
149+
}
115150
}
151+
exporter, err = otlptracegrpc.New(ctx, opts...)
116152
}
117-
118-
exporter, err := otlptracegrpc.New(ctx, opts...)
119153
if err != nil {
120154
return nil, err
121155
}
@@ -127,25 +161,31 @@ func newGRPCTracerProvider(ctx context.Context, res *resource.Resource) (*sdktra
127161
), nil
128162
}
129163

130-
func newGRPCLoggerProvider(ctx context.Context, res *resource.Resource) (*sdklog.LoggerProvider, error) {
131-
logEndpoint := strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"))
132-
if logEndpoint == "" {
133-
logEndpoint = strings.TrimSpace(os.Getenv("OTEL_LOGGING_EXPORTER_OTLP_ENDPOINT"))
134-
}
135-
if logEndpoint == "" {
136-
logEndpoint = strings.TrimSpace(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"))
137-
}
164+
func newLoggerProvider(ctx context.Context, res *resource.Resource) (*sdklog.LoggerProvider, error) {
165+
protocol := resolveOTLPProtocol("LOGS")
166+
logEndpoint := resolveEndpoint("LOGS")
167+
168+
var exporter sdklog.Exporter
169+
var err error
138170

139-
var opts []otlploggrpc.Option
140-
if logEndpoint != "" {
141-
if u, err := url.Parse(logEndpoint); err == nil && u.Scheme != "" && u.Host != "" {
142-
opts = append(opts, otlploggrpc.WithEndpointURL(u.String()))
143-
} else {
144-
opts = append(opts, otlploggrpc.WithEndpoint(logEndpoint))
171+
switch protocol {
172+
case "http/protobuf":
173+
var opts []otlploghttp.Option
174+
if logEndpoint != "" {
175+
opts = append(opts, otlploghttp.WithEndpointURL(logEndpoint))
145176
}
177+
exporter, err = otlploghttp.New(ctx, opts...)
178+
default:
179+
var opts []otlploggrpc.Option
180+
if logEndpoint != "" {
181+
if u, parseErr := url.Parse(logEndpoint); parseErr == nil && u.Scheme != "" && u.Host != "" {
182+
opts = append(opts, otlploggrpc.WithEndpointURL(u.String()))
183+
} else {
184+
opts = append(opts, otlploggrpc.WithEndpoint(logEndpoint))
185+
}
186+
}
187+
exporter, err = otlploggrpc.New(ctx, opts...)
146188
}
147-
148-
exporter, err := otlploggrpc.New(ctx, opts...)
149189
if err != nil {
150190
return nil, err
151191
}

go/core/cli/internal/cli/agent/const.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ func GetModelProvider() v1alpha2.ModelProvider {
2828
return v1alpha2.ModelProviderAnthropic
2929
case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAzureOpenAI):
3030
return v1alpha2.ModelProviderAzureOpenAI
31+
case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderGemini):
32+
return v1alpha2.ModelProviderGemini
33+
case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderGeminiVertexAI):
34+
return v1alpha2.ModelProviderGeminiVertexAI
35+
case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderAnthropicVertexAI):
36+
return v1alpha2.ModelProviderAnthropicVertexAI
37+
case GetModelProviderHelmValuesKey(v1alpha2.ModelProviderBedrock):
38+
return v1alpha2.ModelProviderBedrock
3139
default:
3240
return v1alpha2.ModelProviderOpenAI
3341
}
@@ -42,7 +50,9 @@ func GetModelProviderHelmValuesKey(provider v1alpha2.ModelProvider) string {
4250
return helmKey
4351
}
4452

45-
// GetProviderAPIKey returns API_KEY env var name from provider type
53+
// GetProviderAPIKey returns the env var name for the provider's API key.
54+
// Returns "" for providers that use cloud credentials instead of an API key
55+
// (Ollama, Bedrock, GeminiVertexAI, AnthropicVertexAI).
4656
func GetProviderAPIKey(provider v1alpha2.ModelProvider) string {
4757
switch provider {
4858
case v1alpha2.ModelProviderOpenAI:
@@ -51,7 +61,16 @@ func GetProviderAPIKey(provider v1alpha2.ModelProvider) string {
5161
return env.AnthropicAPIKey.Name()
5262
case v1alpha2.ModelProviderAzureOpenAI:
5363
return env.AzureOpenAIAPIKey.Name()
64+
case v1alpha2.ModelProviderGemini:
65+
// Prefer GOOGLE_API_KEY, fall back to GEMINI_API_KEY to match the
66+
// runtime behaviour in go/adk/pkg/agent/agent.go.
67+
if _, ok := os.LookupEnv(env.GoogleAPIKey.Name()); ok {
68+
return env.GoogleAPIKey.Name()
69+
}
70+
return "GEMINI_API_KEY"
5471
default:
72+
// Ollama, Bedrock, GeminiVertexAI, AnthropicVertexAI use cloud
73+
// credentials rather than a simple API key, so no check is needed.
5574
return ""
5675
}
5776
}

go/core/cli/internal/cli/agent/install.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func InstallCmd(ctx context.Context, cfg *InstallCfg) *PortForward {
8686
if apiKeyName != "" && apiKeyValue == "" {
8787
fmt.Fprintf(os.Stderr, "%s is not set\n", apiKeyName)
8888
fmt.Fprintf(os.Stderr, "Please set the %s environment variable\n", apiKeyName)
89+
fmt.Fprintf(os.Stderr, "To use a different provider set KAGENT_DEFAULT_MODEL_PROVIDER (e.g. ollama, anthropic, gemini)\n")
8990
return nil
9091
}
9192

@@ -127,6 +128,7 @@ func InteractiveInstallCmd(ctx context.Context, c *ishell.Context) *PortForward
127128
if apiKeyName != "" && apiKeyValue == "" {
128129
fmt.Fprintf(os.Stderr, "%s is not set\n", apiKeyName)
129130
fmt.Fprintf(os.Stderr, "Please set the %s environment variable\n", apiKeyName)
131+
fmt.Fprintf(os.Stderr, "To use a different provider set KAGENT_DEFAULT_MODEL_PROVIDER (e.g. ollama, anthropic, gemini)\n")
130132
return nil
131133
}
132134

go/core/internal/httpserver/handlers/memory.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package handlers
33
import (
44
"encoding/json"
55
"fmt"
6-
"log"
76
"net/http"
87
"time"
98

9+
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
10+
1011
"github.com/kagent-dev/kagent/go/api/database"
1112
"github.com/pgvector/pgvector-go"
1213
)
@@ -69,6 +70,7 @@ type ListMemoryResponse struct {
6970

7071
// AddSession handles POST /api/memories/sessions
7172
func (h *MemoryHandler) AddSession(w ErrorResponseWriter, r *http.Request) {
73+
log := ctrllog.FromContext(r.Context())
7274
var req AddSessionMemoryRequest
7375
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
7476
RespondWithError(w, http.StatusBadRequest, "Invalid request body")
@@ -106,12 +108,12 @@ func (h *MemoryHandler) AddSession(w ErrorResponseWriter, r *http.Request) {
106108
}
107109

108110
if err := h.DatabaseService.StoreAgentMemory(r.Context(), memory); err != nil {
109-
log.Printf("Failed to store agent memory: %v", err)
111+
log.Error(err, "failed to store agent memory")
110112
RespondWithError(w, http.StatusInternalServerError, fmt.Sprintf("failed to save memory: %v", err))
111113
return
112114
}
113115

114-
log.Printf("Successfully added memory ID %s for user %s agent %s", memory.ID, req.UserID, req.AgentName)
116+
log.Info("added memory", "id", memory.ID, "userID", req.UserID, "agentName", req.AgentName)
115117

116118
RespondWithJSON(w, http.StatusCreated, map[string]string{"id": memory.ID})
117119
}
@@ -123,6 +125,7 @@ type AddSessionMemoryBatchRequest struct {
123125

124126
// AddSessionBatch handles POST /api/memories/sessions/batch
125127
func (h *MemoryHandler) AddSessionBatch(w ErrorResponseWriter, r *http.Request) {
128+
log := ctrllog.FromContext(r.Context())
126129
var req AddSessionMemoryBatchRequest
127130
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
128131
RespondWithError(w, http.StatusBadRequest, "Invalid request body")
@@ -174,12 +177,12 @@ func (h *MemoryHandler) AddSessionBatch(w ErrorResponseWriter, r *http.Request)
174177
}
175178

176179
if err := h.DatabaseService.StoreAgentMemories(r.Context(), memories); err != nil {
177-
log.Printf("Failed to store agent memory batch: %v", err)
180+
log.Error(err, "failed to store agent memory batch")
178181
RespondWithError(w, http.StatusInternalServerError, fmt.Sprintf("failed to save memory batch: %v", err))
179182
return
180183
}
181184

182-
log.Printf("Successfully added %d memory items", len(memories))
185+
log.Info("added memory batch", "count", len(memories))
183186
RespondWithJSON(w, http.StatusCreated, map[string]int{"count": len(memories)})
184187
}
185188

@@ -242,6 +245,7 @@ func (h *MemoryHandler) Search(w ErrorResponseWriter, r *http.Request) {
242245

243246
// List handles GET /api/memories and returns all memories for an agent+user, ranked by access frequency
244247
func (h *MemoryHandler) List(w ErrorResponseWriter, r *http.Request) {
248+
log := ctrllog.FromContext(r.Context())
245249
agentName := r.URL.Query().Get("agent_name")
246250
userID := r.URL.Query().Get("user_id")
247251

@@ -252,7 +256,7 @@ func (h *MemoryHandler) List(w ErrorResponseWriter, r *http.Request) {
252256

253257
memories, err := h.DatabaseService.ListAgentMemories(r.Context(), agentName, userID)
254258
if err != nil {
255-
log.Printf("Failed to list agent memories: %v", err)
259+
log.Error(err, "failed to list agent memories")
256260
RespondWithError(w, http.StatusInternalServerError, fmt.Sprintf("failed to list memories: %v", err))
257261
return
258262
}
@@ -276,6 +280,7 @@ func (h *MemoryHandler) List(w ErrorResponseWriter, r *http.Request) {
276280

277281
// Delete handles DELETE /api/memories
278282
func (h *MemoryHandler) Delete(w ErrorResponseWriter, r *http.Request) {
283+
log := ctrllog.FromContext(r.Context())
279284
agentName := r.URL.Query().Get("agent_name")
280285
userID := r.URL.Query().Get("user_id")
281286

@@ -285,7 +290,7 @@ func (h *MemoryHandler) Delete(w ErrorResponseWriter, r *http.Request) {
285290
}
286291

287292
if err := h.DatabaseService.DeleteAgentMemory(r.Context(), agentName, userID); err != nil {
288-
log.Printf("Failed to delete agent memory: %v", err)
293+
log.Error(err, "failed to delete agent memory")
289294
RespondWithError(w, http.StatusInternalServerError, fmt.Sprintf("failed to delete memory: %v", err))
290295
return
291296
}

0 commit comments

Comments
 (0)