1- from google .adk .agents .invocation_context import InvocationContext
1+ # Copyright 2025 Google LLC
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+
215from google .adk .agents .llm_agent import Agent
316from google .adk .agents .readonly_context import ReadonlyContext
417from google .adk .sessions .session import Session
@@ -17,7 +30,7 @@ async def load_artifact(self, app_name, user_id, session_id, filename):
1730 if filename in self .artifacts :
1831 return self .artifacts [filename ]
1932 else :
20- raise KeyError ( f"Artifact ' { filename } ' not found." )
33+ return None
2134
2235
2336async def _create_test_readonly_context (
@@ -114,7 +127,7 @@ async def test_inject_session_state_with_missing_artifact_raises_key_error():
114127 artifact_service = mock_artifact_service
115128 )
116129
117- with pytest .raises (KeyError , match = "Artifact ' missing_file' not found." ):
130+ with pytest .raises (KeyError , match = "Artifact missing_file not found." ):
118131 await instructions_utils .inject_session_state (
119132 instruction_template , invocation_context
120133 )
@@ -200,7 +213,7 @@ async def test_inject_session_state_with_empty_artifact_name_raises_key_error():
200213 artifact_service = mock_artifact_service
201214 )
202215
203- with pytest .raises (KeyError , match = "Artifact '' not found." ):
216+ with pytest .raises (KeyError , match = "Artifact not found." ):
204217 await instructions_utils .inject_session_state (
205218 instruction_template , invocation_context
206219 )
@@ -214,3 +227,43 @@ async def test_inject_session_state_artifact_service_not_initialized_raises_valu
214227 await instructions_utils .inject_session_state (
215228 instruction_template , invocation_context
216229 )
230+
231+
232+ @pytest .mark .asyncio
233+ async def test_inject_session_state_with_optional_missing_artifact_returns_empty ():
234+ instruction_template = "Optional artifact: {artifact.missing_file?}"
235+ mock_artifact_service = MockArtifactService (
236+ {"my_file" : "This is my artifact content." }
237+ )
238+ invocation_context = await _create_test_readonly_context (
239+ artifact_service = mock_artifact_service
240+ )
241+
242+ populated_instruction = await instructions_utils .inject_session_state (
243+ instruction_template , invocation_context
244+ )
245+ assert populated_instruction == "Optional artifact: "
246+
247+
248+ @pytest .mark .asyncio
249+ async def test_inject_session_state_with_none_state_value_returns_empty ():
250+ instruction_template = "Value: {test_key}"
251+ invocation_context = await _create_test_readonly_context (
252+ state = {"test_key" : None }
253+ )
254+
255+ populated_instruction = await instructions_utils .inject_session_state (
256+ instruction_template , invocation_context
257+ )
258+ assert populated_instruction == "Value: "
259+
260+
261+ @pytest .mark .asyncio
262+ async def test_inject_session_state_with_optional_missing_state_returns_empty ():
263+ instruction_template = "Optional value: {missing_key?}"
264+ invocation_context = await _create_test_readonly_context ()
265+
266+ populated_instruction = await instructions_utils .inject_session_state (
267+ instruction_template , invocation_context
268+ )
269+ assert populated_instruction == "Optional value: "
0 commit comments