Skip to content

Commit 0a5e312

Browse files
authored
Merge branch 'main' into fix/bedrock-thinking-tool-use
2 parents 79f3917 + e638807 commit 0a5e312

9 files changed

Lines changed: 158 additions & 4 deletions

File tree

.editorconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
tab_width = 2
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true
11+
12+
[{Makefile,*.go,go.*}]
13+
indent_style = tab
14+
indent_size = 4
15+
tab_width = 4
16+
17+
[*.py]
18+
indent_size = 4
19+
tab_width = 4

helm/kagent/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ querydoc:
556556
memory: 512Mi
557557
openai:
558558
apiKey: ""
559+
# secretRef: "" # Name of existing Secret containing OPENAI_API_KEY. Takes precedence over apiKey.
559560

560561
# ==============================================================================
561562
# OAUTH2-PROXY CONFIGURATION (Optional)

helm/tools/querydoc/templates/deployment.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ spec:
1414
metadata:
1515
annotations:
1616
checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
17-
{{- if .Values.openai.apiKey }}
17+
{{- if and .Values.openai.apiKey (not .Values.openai.secretRef) }}
1818
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
1919
{{- end }}
2020
labels:
@@ -46,9 +46,9 @@ spec:
4646
envFrom:
4747
- configMapRef:
4848
name: {{ include "querydoc.fullname" . }}
49-
{{- if .Values.openai.apiKey }}
49+
{{- if or .Values.openai.apiKey .Values.openai.secretRef }}
5050
- secretRef:
51-
name: {{ include "querydoc.fullname" . }}
51+
name: {{ .Values.openai.secretRef | default (include "querydoc.fullname" .) | quote }}
5252
{{- end }}
5353
ports:
5454
- name: http

helm/tools/querydoc/templates/secret.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{- if .Values.openai.apiKey }}
1+
{{- if and .Values.openai.apiKey (not .Values.openai.secretRef) }}
22
apiVersion: v1
33
kind: Secret
44
metadata:

helm/tools/querydoc/tests/deployment_test.yaml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ suite: test querydoc deployment
22
templates:
33
- deployment.yaml
44
- configmap.yaml
5+
- secret.yaml
56
tests:
67
- it: should render deployment with default values
78
template: deployment.yaml
@@ -163,3 +164,57 @@ tests:
163164
value: AI
164165
effect: NoSchedule
165166
operator: Equal
167+
168+
- it: should not include secretRef by default
169+
template: deployment.yaml
170+
asserts:
171+
- equal:
172+
path: spec.template.spec.containers[0].envFrom
173+
value:
174+
- configMapRef:
175+
name: RELEASE-NAME-querydoc
176+
- notExists:
177+
path: spec.template.metadata.annotations.checksum/secret
178+
179+
- it: should reference chart-owned Secret when only openai.apiKey is set
180+
template: deployment.yaml
181+
set:
182+
openai:
183+
apiKey: foo
184+
asserts:
185+
- contains:
186+
path: spec.template.spec.containers[0].envFrom
187+
content:
188+
secretRef:
189+
name: RELEASE-NAME-querydoc
190+
- exists:
191+
path: spec.template.metadata.annotations.checksum/secret
192+
193+
- it: should reference external Secret when openai.secretRef is set
194+
template: deployment.yaml
195+
set:
196+
openai:
197+
secretRef: my-secret
198+
asserts:
199+
- contains:
200+
path: spec.template.spec.containers[0].envFrom
201+
content:
202+
secretRef:
203+
name: my-secret
204+
- notExists:
205+
path: spec.template.metadata.annotations.checksum/secret
206+
207+
- it: secretRef should win over apiKey when both are set
208+
template: deployment.yaml
209+
set:
210+
openai:
211+
apiKey: foo
212+
secretRef: my-secret
213+
asserts:
214+
- contains:
215+
path: spec.template.spec.containers[0].envFrom
216+
content:
217+
secretRef:
218+
name: my-secret
219+
- notExists:
220+
path: spec.template.metadata.annotations.checksum/secret
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
suite: test querydoc secret
2+
templates:
3+
- secret.yaml
4+
tests:
5+
- it: should not render a Secret with default values
6+
asserts:
7+
- hasDocuments:
8+
count: 0
9+
10+
- it: should render a Secret when openai.apiKey is set
11+
set:
12+
openai:
13+
apiKey: foo
14+
asserts:
15+
- hasDocuments:
16+
count: 1
17+
- isKind:
18+
of: Secret
19+
- equal:
20+
path: metadata.name
21+
value: RELEASE-NAME-querydoc
22+
- equal:
23+
path: data.OPENAI_API_KEY
24+
value: Zm9v # `foo` base64 encoded
25+
26+
- it: should not render a Secret when openai.secretRef is set
27+
set:
28+
openai:
29+
secretRef: my-secret
30+
asserts:
31+
- hasDocuments:
32+
count: 0
33+
34+
- it: should not render a Secret when both apiKey and secretRef are set (secretRef wins)
35+
set:
36+
openai:
37+
apiKey: foo
38+
secretRef: my-secret
39+
asserts:
40+
- hasDocuments:
41+
count: 0

helm/tools/querydoc/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ config:
5252
# Secret configuration
5353
openai:
5454
apiKey: ""
55+
# secretRef: "" # Name of existing Secret containing OPENAI_API_KEY. Takes precedence over apiKey.
5556

5657
# OTEL configuration
5758
otel:

python/packages/kagent-adk/src/kagent/adk/_session_service.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,14 @@ async def create_session(
4646
request_data["source"] = state.get("source", "")
4747

4848
# Make API call to create session
49+
# Pass user_id as a query param so the controller's auth middleware
50+
# (UnsecureAuthenticator) reads it consistently — matching the user_id
51+
# used by get_session, list_sessions, delete_session, and append_event.
52+
# Without this, unsecure-mode requests fall back to "admin@kagent.dev"
53+
# while all lookups use the A2A-derived user_id, causing SessionNotFoundError.
4954
response = await self.client.post(
5055
"/api/sessions",
56+
params={"user_id": user_id},
5157
json=request_data,
5258
)
5359
response.raise_for_status()

python/packages/kagent-adk/tests/unittests/test_session_service.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,37 @@ def _factory(response_json: dict | None, status_code: int = 200) -> KAgentSessio
6666
return _factory
6767

6868

69+
@pytest.mark.asyncio
70+
async def test_create_session_passes_user_id_as_query_param():
71+
"""create_session must include user_id as a query param on POST /api/sessions.
72+
73+
Regression test for the SessionNotFoundError caused by a user_id mismatch:
74+
the controller's UnsecureAuthenticator resolves identity from the query param
75+
(or X-User-Id header), not the JSON body. Without the query param the
76+
controller falls back to "admin@kagent.dev" for the session create, while
77+
every subsequent GET uses the A2A-derived user_id — guaranteeing a 404.
78+
Fixes: https://github.com/kagent-dev/kagent/issues/1882
79+
"""
80+
mock_response = MagicMock(spec=httpx.Response)
81+
mock_response.status_code = 201
82+
mock_response.json.return_value = {"data": {"id": "sess-1", "user_id": "A2A_USER_ctx123"}}
83+
mock_response.raise_for_status = MagicMock()
84+
85+
client = MagicMock(spec=httpx.AsyncClient)
86+
client.post = AsyncMock(return_value=mock_response)
87+
88+
svc = KAgentSessionService(client)
89+
await svc.create_session(app_name="my-agent", user_id="A2A_USER_ctx123", session_id="ctx123")
90+
91+
client.post.assert_called_once()
92+
call_kwargs = client.post.call_args.kwargs
93+
assert call_kwargs.get("params", {}).get("user_id") == "A2A_USER_ctx123", (
94+
f"Expected params['user_id']='A2A_USER_ctx123', got params={call_kwargs.get('params')!r}. "
95+
"Without this query param the controller's UnsecureAuthenticator falls back "
96+
"to 'admin@kagent.dev', causing a SessionNotFoundError on subsequent lookups."
97+
)
98+
99+
69100
@pytest.mark.asyncio
70101
async def test_get_session_returns_none_on_404(mock_client):
71102
"""A 404 response returns None without raising."""

0 commit comments

Comments
 (0)