@@ -246,6 +246,23 @@ def test_scorer_invoke_request_serialization_keeps_legacy_record_shape(self) ->
246246 "config" : {},
247247 }
248248
249+ def test_execution_context_serializes_missing_optional_claims_as_null (self ) -> None :
250+ from agent_control_evaluator_galileo .luna import ScorerInvokeInputs , ScorerInvokeRequest
251+ from agent_control_evaluator_galileo .luna .client import GalileoExecutionContext
252+
253+ request = ScorerInvokeRequest (
254+ scorer_id = "scorer-123" ,
255+ inputs = ScorerInvokeInputs (query = "hello" ),
256+ execution_context = GalileoExecutionContext (organization_id = "org-1" ),
257+ )
258+
259+ assert request .to_dict ()["execution_context" ] == {
260+ "organization_id" : "org-1" ,
261+ "user_id" : None ,
262+ "project_id" : None ,
263+ "run_id" : None ,
264+ }
265+
249266 def test_scorer_invoke_request_rejects_unknown_config (self ) -> None :
250267 from agent_control_evaluator_galileo .luna import (
251268 ScorerInvokeInputs ,
@@ -1064,7 +1081,8 @@ async def test_evaluator_contextual_hook_forwards_complete_step(self) -> None:
10641081
10651082 @patch .dict (os .environ , LUNA_ENV )
10661083 @pytest .mark .asyncio
1067- async def test_evaluator_consumes_verified_opaque_extensions (self ) -> None :
1084+ @pytest .mark .parametrize ("target_type" , ["log_stream" , "agent_stream" ])
1085+ async def test_evaluator_consumes_verified_opaque_extensions (self , target_type : str ) -> None :
10681086 from agent_control_evaluator_galileo .luna import LunaEvaluator , ScorerInvokeResponse
10691087 from agent_control_evaluator_galileo .luna .client import (
10701088 GalileoExecutionContext ,
@@ -1077,7 +1095,7 @@ async def test_evaluator_consumes_verified_opaque_extensions(self) -> None:
10771095 extensions = {
10781096 "namespace_key" : "org-1" ,
10791097 "caller_id" : "verified-user-2" ,
1080- "target_type" : "log_stream" ,
1098+ "target_type" : target_type ,
10811099 "target_id" : "run-4" ,
10821100 "metadata" : {"project_id" : "project-3" },
10831101 }
@@ -1106,25 +1124,105 @@ async def test_evaluator_consumes_verified_opaque_extensions(self) -> None:
11061124
11071125 @patch .dict (os .environ , LUNA_ENV )
11081126 @pytest .mark .asyncio
1109- async def test_evaluator_requires_authenticated_caller_id (self ) -> None :
1110- from agent_control_evaluator_galileo .luna import LunaEvaluator
1111- from agent_control_evaluator_galileo .luna .client import GalileoLunaClient
1127+ async def test_evaluator_allows_missing_caller_id (self ) -> None :
1128+ from agent_control_evaluator_galileo .luna import LunaEvaluator , ScorerInvokeResponse
1129+ from agent_control_evaluator_galileo .luna .client import (
1130+ GalileoExecutionContext ,
1131+ GalileoLunaClient ,
1132+ )
11121133
11131134 evaluator = LunaEvaluator .from_dict ({"scorer_id" : "scorer-123" })
11141135 extensions = {
11151136 "namespace_key" : "org-1" ,
11161137 "target_type" : "log_stream" ,
11171138 "target_id" : "run-4" ,
1139+ "metadata" : {},
1140+ }
1141+
1142+ with patch .object (GalileoLunaClient , "invoke" , new_callable = AsyncMock ) as mock_invoke :
1143+ mock_invoke .return_value = ScorerInvokeResponse (score = 0.8 , status = "success" )
1144+ result = await evaluator .evaluate_with_extensions (
1145+ "selected input" , Step (type = "llm" , name = "answer" , input = "prompt" ), extensions
1146+ )
1147+
1148+ assert result .error is None
1149+ mock_invoke .assert_awaited_once_with (
1150+ scorer_id = "scorer-123" ,
1151+ step = Step (type = "llm" , name = "answer" , input = "prompt" ),
1152+ execution_context = GalileoExecutionContext (
1153+ organization_id = "org-1" ,
1154+ user_id = None ,
1155+ project_id = None ,
1156+ run_id = "run-4" ,
1157+ ),
1158+ input = "selected input" ,
1159+ output = None ,
1160+ config = None ,
1161+ timeout = 10.0 ,
1162+ )
1163+
1164+ @patch .dict (os .environ , LUNA_ENV )
1165+ @pytest .mark .asyncio
1166+ async def test_evaluator_omits_run_id_for_unsupported_target_type (self ) -> None :
1167+ from agent_control_evaluator_galileo .luna import LunaEvaluator , ScorerInvokeResponse
1168+ from agent_control_evaluator_galileo .luna .client import (
1169+ GalileoExecutionContext ,
1170+ GalileoLunaClient ,
1171+ )
1172+
1173+ evaluator = LunaEvaluator .from_dict ({"scorer_id" : "scorer-123" })
1174+ extensions = {
1175+ "namespace_key" : "org-1" ,
1176+ "caller_id" : "verified-user-2" ,
1177+ "target_type" : "environment" ,
1178+ "target_id" : "prod" ,
11181179 "metadata" : {"project_id" : "project-3" },
11191180 }
11201181
11211182 with patch .object (GalileoLunaClient , "invoke" , new_callable = AsyncMock ) as mock_invoke :
1183+ mock_invoke .return_value = ScorerInvokeResponse (score = 0.8 , status = "success" )
11221184 result = await evaluator .evaluate_with_extensions (
11231185 "selected input" , Step (type = "llm" , name = "answer" , input = "prompt" ), extensions
11241186 )
11251187
1188+ assert result .error is None
1189+ mock_invoke .assert_awaited_once_with (
1190+ scorer_id = "scorer-123" ,
1191+ step = Step (type = "llm" , name = "answer" , input = "prompt" ),
1192+ execution_context = GalileoExecutionContext (
1193+ organization_id = "org-1" ,
1194+ user_id = "verified-user-2" ,
1195+ project_id = "project-3" ,
1196+ run_id = None ,
1197+ ),
1198+ input = "selected input" ,
1199+ output = None ,
1200+ config = None ,
1201+ timeout = 10.0 ,
1202+ )
1203+
1204+ @patch .dict (os .environ , LUNA_ENV )
1205+ @pytest .mark .asyncio
1206+ async def test_evaluator_rejects_missing_organization_id (self ) -> None :
1207+ from agent_control_evaluator_galileo .luna import LunaEvaluator
1208+ from agent_control_evaluator_galileo .luna .client import GalileoLunaClient
1209+
1210+ evaluator = LunaEvaluator .from_dict ({"scorer_id" : "scorer-123" })
1211+ extensions = {
1212+ "target_type" : "log_stream" ,
1213+ "target_id" : "run-4" ,
1214+ "metadata" : {"project_id" : "project-3" },
1215+ }
1216+
1217+ with patch .object (GalileoLunaClient , "invoke" , new_callable = AsyncMock ) as mock_invoke :
1218+ result = await evaluator .evaluate_with_extensions (
1219+ "selected input" ,
1220+ Step (type = "llm" , name = "answer" , input = "prompt" ),
1221+ extensions ,
1222+ )
1223+
11261224 assert result .error is not None
1127- assert "user_id " in result .error
1225+ assert "organization_id " in result .error
11281226 mock_invoke .assert_not_called ()
11291227
11301228 @patch .dict (os .environ , LUNA_ENV )
0 commit comments