3333import com .alibaba .dashscope .agentstudio .param .EnvironmentCreateParam ;
3434import com .alibaba .dashscope .agentstudio .param .EnvironmentListParam ;
3535import com .alibaba .dashscope .agentstudio .param .FileListParam ;
36+ import com .alibaba .dashscope .agentstudio .param .SessionAgent ;
3637import com .alibaba .dashscope .agentstudio .param .SessionCreateParam ;
3738import com .alibaba .dashscope .agentstudio .param .SessionEventListParam ;
3839import com .alibaba .dashscope .agentstudio .param .SessionListParam ;
5051import com .alibaba .dashscope .exception .ApiException ;
5152import com .alibaba .dashscope .utils .Constants ;
5253import com .alibaba .dashscope .utils .JsonUtils ;
54+ import com .google .gson .JsonElement ;
5355import com .google .gson .JsonObject ;
5456import java .io .ByteArrayInputStream ;
5557import java .io .IOException ;
5961import java .nio .file .Paths ;
6062import java .util .Arrays ;
6163import java .util .Collections ;
64+ import java .util .HashMap ;
65+ import java .util .Map ;
6266import okhttp3 .mockwebserver .MockResponse ;
6367import okhttp3 .mockwebserver .MockWebServer ;
6468import okhttp3 .mockwebserver .RecordedRequest ;
@@ -288,7 +292,7 @@ public void testSessionCreate() throws Exception {
288292 enqueue ("session_response" );
289293 Session session =
290294 new Sessions (null , null , null )
291- .create (SessionCreateParam .builder ().agent ("agent_xyz" ).title ("Test Session" ).build ());
295+ .create (SessionCreateParam .builder ().agent (SessionAgent . ofString ( "agent_xyz" ) ).title ("Test Session" ).build ());
292296 RecordedRequest req = mockServer .takeRequest ();
293297 assertEquals ("POST" , req .getMethod ());
294298 assertTrue (req .getPath ().endsWith ("/sessions" ));
@@ -309,7 +313,7 @@ public void testSessionCreateWithVaultIds() throws Exception {
309313 new Sessions (null , null , null )
310314 .create (
311315 SessionCreateParam .builder ()
312- .agent ("agent_xyz" )
316+ .agent (SessionAgent . ofString ( "agent_xyz" ) )
313317 .vaultIds (Arrays .asList ("vlt_x" ))
314318 .metadata (Collections .singletonMap ("biz_ticket_id" , "1234" ))
315319 .build ());
@@ -323,11 +327,130 @@ public void testSessionCreateWithVaultIds() throws Exception {
323327
324328 // Omitted vault_ids must not produce a null vault_ids in the body.
325329 enqueue ("session_response" );
326- new Sessions (null , null , null ).create (SessionCreateParam .builder ().agent ("agent_xyz" ).build ());
330+ new Sessions (null , null , null ).create (SessionCreateParam .builder ().agent (SessionAgent . ofString ( "agent_xyz" ) ).build ());
327331 JsonObject body2 = JsonUtils .parse (mockServer .takeRequest ().getBody ().readUtf8 ());
328332 assertFalse (body2 .has ("vault_ids" ));
329333 }
330334
335+ @ Test
336+ public void testSessionCreateWithAgentOverride () throws Exception {
337+ // agent accepts an override object (type=agent_with_overrides) in
338+ // addition to the Agent ID string; environment_variables / mcp_configs
339+ // are new top-level fields. Omitted optional fields are not sent.
340+ enqueue ("session_response" );
341+ Map <String , Object > agent = new HashMap <>();
342+ agent .put ("type" , "agent_with_overrides" );
343+ agent .put ("id" , "agent_xxx" );
344+ agent .put ("version" , 3 );
345+ agent .put ("system" , "你是此 Session 专用的助手。" );
346+ agent .put ("tools" , Collections .emptyList ());
347+ Map <String , Object > mcpServer = new HashMap <>();
348+ mcpServer .put ("type" , "official" );
349+ mcpServer .put ("name" , "weather" );
350+ agent .put ("mcp_servers" , Collections .singletonList (mcpServer ));
351+
352+ Map <String , String > headers = new HashMap <>();
353+ headers .put ("X-Tenant-Id" , "demo" );
354+ Map <String , Object > mcpConfig = new HashMap <>();
355+ mcpConfig .put ("mcp_server_name" , "weather" );
356+ mcpConfig .put ("headers" , headers );
357+
358+ new Sessions (null , null , null )
359+ .create (
360+ SessionCreateParam .builder ()
361+ .agent (SessionAgent .ofOverride (agent ))
362+ .title ("项目分析" )
363+ .environmentVariables (Collections .singletonMap ("LANG" , "zh_CN.UTF-8" ))
364+ .mcpConfigs (Collections .singletonList (mcpConfig ))
365+ .build ());
366+ JsonObject body = JsonUtils .parse (mockServer .takeRequest ().getBody ().readUtf8 ());
367+ assertTrue (body .has ("agent" ));
368+ assertEquals (
369+ "agent_with_overrides" , body .getAsJsonObject ("agent" ).get ("type" ).getAsString ());
370+ assertEquals ("agent_xxx" , body .getAsJsonObject ("agent" ).get ("id" ).getAsString ());
371+ assertTrue (body .getAsJsonObject ("agent" ).get ("tools" ).isJsonArray ());
372+ assertEquals (
373+ "zh_CN.UTF-8" ,
374+ body .getAsJsonObject ("environment_variables" ).get ("LANG" ).getAsString ());
375+ assertEquals (
376+ "demo" ,
377+ body .getAsJsonArray ("mcp_configs" )
378+ .get (0 )
379+ .getAsJsonObject ()
380+ .getAsJsonObject ("headers" )
381+ .get ("X-Tenant-Id" )
382+ .getAsString ());
383+ // Omitted fields are absent — never sent as null.
384+ assertFalse (body .has ("resources" ));
385+ assertFalse (body .has ("vault_ids" ));
386+ assertFalse (body .has ("metadata" ));
387+ }
388+
389+ @ Test
390+ public void testSessionUpdateAgentPatchAndClear () throws Exception {
391+ // update: agent patch sub-fields — null revokes the override (must be
392+ // preserved as JSON null, not dropped), "" / [] override to empty, an
393+ // omitted sub-field stays absent. Top-level [] / {} explicitly clear.
394+ enqueue ("session_response" );
395+ Map <String , Object > agentPatch = new HashMap <>();
396+ agentPatch .put ("system" , "" );
397+ agentPatch .put ("tools" , null );
398+ agentPatch .put ("skills" , Collections .emptyList ());
399+
400+ new Sessions (null , null , null )
401+ .update (
402+ "sess_abc123" ,
403+ SessionUpdateParam .builder ()
404+ .title ("更新后" )
405+ .vaultIds (Collections .emptyList ())
406+ .environmentVariables (new HashMap <String , String >())
407+ .mcpConfigs (Collections .emptyList ())
408+ .agent (SessionAgent .ofOverride (agentPatch ))
409+ .build ());
410+ JsonObject body = JsonUtils .parse (mockServer .takeRequest ().getBody ().readUtf8 ());
411+ // Top-level [] / {} clear (sent, not null, not omitted).
412+ assertTrue (body .has ("vault_ids" ));
413+ assertTrue (body .getAsJsonArray ("vault_ids" ).isEmpty ());
414+ assertTrue (body .has ("environment_variables" ));
415+ assertTrue (body .getAsJsonObject ("environment_variables" ).entrySet ().isEmpty ());
416+ assertTrue (body .has ("mcp_configs" ));
417+ assertTrue (body .getAsJsonArray ("mcp_configs" ).isEmpty ());
418+ // Agent patch: null preserved (revoke), "" preserved (empty prompt),
419+ // [] preserved (empty), omitted sub-field absent (keep).
420+ JsonObject agent = body .getAsJsonObject ("agent" );
421+ assertTrue (agent .has ("tools" ));
422+ assertTrue (agent .get ("tools" ).isJsonNull ());
423+ assertEquals ("" , agent .get ("system" ).getAsString ());
424+ assertTrue (agent .getAsJsonArray ("skills" ).isEmpty ());
425+ assertFalse (agent .has ("mcp_servers" ));
426+ }
427+
428+ @ Test
429+ public void testSessionAgentUnionSerialization () {
430+ // string form -> JSON string primitive
431+ JsonElement s = SessionAgent .ofString ("agent_01" ).toJsonElement ();
432+ assertTrue (s .isJsonPrimitive ());
433+ assertEquals ("agent_01" , s .getAsString ());
434+
435+ // override form preserves null sub-fields (revoke override) and [] / ""
436+ Map <String , Object > patch = new HashMap <>();
437+ patch .put ("system" , "" );
438+ patch .put ("tools" , null );
439+ patch .put ("skills" , Collections .emptyList ());
440+ JsonElement o = SessionAgent .ofOverride (patch ).toJsonElement ();
441+ assertTrue (o .isJsonObject ());
442+ assertTrue (o .getAsJsonObject ().get ("tools" ).isJsonNull ());
443+ assertEquals ("" , o .getAsJsonObject ().get ("system" ).getAsString ());
444+ assertTrue (o .getAsJsonObject ().getAsJsonArray ("skills" ).isEmpty ());
445+
446+ // static toJsonElement accepts String / Map / SessionAgent
447+ assertEquals ("agent_01" , SessionAgent .toJsonElement ("agent_01" ).getAsString ());
448+ assertTrue (SessionAgent .toJsonElement (patch ).isJsonObject ());
449+ // unsupported type -> IllegalArgumentException
450+ assertThrows (IllegalArgumentException .class , () -> SessionAgent .toJsonElement (42 ));
451+ assertThrows (IllegalArgumentException .class , () -> SessionAgent .toJsonElement (null ));
452+ }
453+
331454 @ Test
332455 public void testSessionRetrieve () throws Exception {
333456 enqueue ("session_response" );
0 commit comments