@@ -500,6 +500,92 @@ func TestHandleListAgents(t *testing.T) {
500500 }
501501 require .True (t , found )
502502 })
503+
504+ t .Run ("filters Agent and AgentHarness rows by namespace query parameter" , func (t * testing.T ) {
505+ modelConfig := createTestModelConfig ()
506+ agentDefault := createTestAgent ("agent-in-default" , modelConfig )
507+ agentOther := & v1alpha2.Agent {
508+ ObjectMeta : metav1.ObjectMeta {Name : "agent-in-other" , Namespace : "other" },
509+ Spec : v1alpha2.AgentSpec {
510+ Type : v1alpha2 .AgentType_Declarative ,
511+ Declarative : & v1alpha2.DeclarativeAgentSpec {
512+ ModelConfig : modelConfig .Name ,
513+ },
514+ },
515+ }
516+ harnessDefault := & v1alpha2.AgentHarness {
517+ ObjectMeta : metav1.ObjectMeta {Name : "harness-default" , Namespace : "default" },
518+ Spec : v1alpha2.AgentHarnessSpec {
519+ Backend : v1alpha2 .AgentHarnessBackendOpenClaw ,
520+ ModelConfigRef : "test-model-config" ,
521+ },
522+ }
523+ harnessOther := & v1alpha2.AgentHarness {
524+ ObjectMeta : metav1.ObjectMeta {Name : "harness-other" , Namespace : "other" },
525+ Spec : v1alpha2.AgentHarnessSpec {
526+ Backend : v1alpha2 .AgentHarnessBackendOpenClaw ,
527+ ModelConfigRef : "test-model-config" ,
528+ },
529+ }
530+ unsupportedHarnessDefault := & v1alpha2.AgentHarness {
531+ ObjectMeta : metav1.ObjectMeta {Name : "unsupported-harness" , Namespace : "default" },
532+ Spec : v1alpha2.AgentHarnessSpec {
533+ Backend : v1alpha2 .AgentHarnessBackendType ("unsupported" ),
534+ ModelConfigRef : "test-model-config" ,
535+ },
536+ }
537+ handler , _ := setupTestHandler (t , agentDefault , agentOther , harnessDefault , harnessOther , unsupportedHarnessDefault , modelConfig )
538+
539+ req := httptest .NewRequest ("GET" , "/api/agents?namespace=default" , nil )
540+ req = setUser (req , "test-user" )
541+ w := httptest .NewRecorder ()
542+
543+ handler .HandleListAgents (& testErrorResponseWriter {w }, req )
544+
545+ require .Equal (t , http .StatusOK , w .Code )
546+ var response api.StandardResponse [[]api.AgentResponse ]
547+ require .NoError (t , json .Unmarshal (w .Body .Bytes (), & response ))
548+ require .Len (t , response .Data , 2 )
549+
550+ byName := make (map [string ]api.AgentResponse , len (response .Data ))
551+ for _ , row := range response .Data {
552+ byName [row .Agent .Metadata .Name ] = row
553+ require .Equal (t , "default" , row .Agent .Metadata .Namespace )
554+ }
555+ require .Contains (t , byName , "agent-in-default" )
556+ require .Contains (t , byName , "harness-default" )
557+ require .NotContains (t , byName , "agent-in-other" )
558+ require .NotContains (t , byName , "harness-other" )
559+ require .NotContains (t , byName , "unsupported-harness" )
560+ })
561+
562+ // Kubernetes namespace names must be DNS-1123 labels. Rejecting invalid input
563+ // before calling the Kubernetes client keeps the list path consistent with
564+ // other resource handlers and avoids surprising cross-namespace behavior.
565+ t .Run ("returns 400 for invalid namespace query value" , func (t * testing.T ) {
566+ handler , _ := setupTestHandler (t )
567+
568+ req := httptest .NewRequest ("GET" , "/api/agents?namespace=INVALID_NS!" , nil )
569+ req = setUser (req , "test-user" )
570+ w := httptest .NewRecorder ()
571+
572+ handler .HandleListAgents (& testErrorResponseWriter {w }, req )
573+
574+ require .Equal (t , http .StatusBadRequest , w .Code )
575+ })
576+
577+ t .Run ("returns 400 for namespace query value with leading or trailing whitespace" , func (t * testing.T ) {
578+ handler , _ := setupTestHandler (t )
579+
580+ req := httptest .NewRequest ("GET" , "/api/agents?namespace=%20default" , nil )
581+ req = setUser (req , "test-user" )
582+ w := httptest .NewRecorder ()
583+
584+ handler .HandleListAgents (& testErrorResponseWriter {w }, req )
585+
586+ require .Equal (t , http .StatusBadRequest , w .Code )
587+ require .Contains (t , w .Body .String (), "must not contain leading or trailing whitespace" )
588+ })
503589}
504590
505591func TestHandleListSandboxAgents (t * testing.T ) {
0 commit comments