agent_patch
runs/2026-02-28__13-38-10__gpt-5-3-codex/flux-pr-1209/flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/agent-logs/agent.patch
14983 bytes
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go b/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
index 1b519b7..6cc424e 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
@@ -295,7 +295,12 @@ func NewProtoCompiler(schema string, mapping *GRPCMapping) (*RPCCompiler, error)
// Process all services in the schema
for i := 0; i < f.Services().Len(); i++ {
- pc.doc.Services = append(pc.doc.Services, pc.parseService(f.Services().Get(i)))
+ service, err := pc.parseService(f.Services().Get(i))
+ if err != nil {
+ return nil, err
+ }
+
+ pc.doc.Services = append(pc.doc.Services, service)
}
return pc, nil
@@ -322,8 +327,18 @@ func (p *RPCCompiler) Compile(executionPlan *RPCExecutionPlan, inputData gjson.R
invocations := make([]Invocation, 0, len(executionPlan.Calls))
for _, call := range executionPlan.Calls {
- inputMessage := p.doc.MessageByName(call.Request.Name)
- outputMessage := p.doc.MessageByName(call.Response.Name)
+ inputMessageRef := p.doc.MessageRefByName(call.Request.Name)
+ if inputMessageRef == -1 {
+ return nil, fmt.Errorf("request message type %q for method %q not found in protobuf schema", call.Request.Name, call.MethodName)
+ }
+
+ outputMessageRef := p.doc.MessageRefByName(call.Response.Name)
+ if outputMessageRef == -1 {
+ return nil, fmt.Errorf("response message type %q for method %q not found in protobuf schema", call.Response.Name, call.MethodName)
+ }
+
+ inputMessage := p.doc.MessageByRef(inputMessageRef)
+ outputMessage := p.doc.MessageByRef(outputMessageRef)
request := p.buildProtoMessage(inputMessage, &call.Request, inputData)
response := p.newEmptyMessage(outputMessage)
@@ -519,16 +534,25 @@ func (p *RPCCompiler) parseEnumValue(v protoref.EnumValueDescriptor, enumValueMa
// parseService extracts information from a protobuf service descriptor,
// including all its methods.
-func (p *RPCCompiler) parseService(s protoref.ServiceDescriptor) Service {
+func (p *RPCCompiler) parseService(s protoref.ServiceDescriptor) (Service, error) {
name := string(s.Name())
m := s.Methods()
methods := make([]Method, 0, m.Len())
methodsRefs := make([]int, 0, m.Len())
+ methodOffset := len(p.doc.Methods)
for j := 0; j < m.Len(); j++ {
- methods = append(methods, p.parseMethod(m.Get(j)))
- methodsRefs = append(methodsRefs, j)
+ method := p.parseMethod(m.Get(j))
+ if method.InputRef == -1 {
+ return Service{}, fmt.Errorf("input message type %q for method %q not found in protobuf schema", method.InputName, method.Name)
+ }
+ if method.OutputRef == -1 {
+ return Service{}, fmt.Errorf("output message type %q for method %q not found in protobuf schema", method.OutputName, method.Name)
+ }
+
+ methods = append(methods, method)
+ methodsRefs = append(methodsRefs, methodOffset+j)
}
// Add the methods to the Document
@@ -538,7 +562,7 @@ func (p *RPCCompiler) parseService(s protoref.ServiceDescriptor) Service {
Name: name,
FullName: string(s.FullName()),
MethodsRefs: methodsRefs,
- }
+ }, nil
}
// parseMethod extracts information from a protobuf method descriptor,
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go b/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
index 5e098c3..17dcb38 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
@@ -291,3 +291,38 @@ func TestBuildProtoMessage(t *testing.T) {
require.Equal(t, 1, len(invocations))
}
+
+func TestRPCCompilerCompileValidatesReferencedMessageTypes(t *testing.T) {
+ compiler, err := NewProtoCompiler(grpctest.MustProtoSchema(t), nil)
+ require.NoError(t, err)
+
+ _, err = compiler.Compile(&RPCExecutionPlan{
+ Calls: []RPCCall{
+ {
+ MethodName: "QueryUsers",
+ Request: RPCMessage{
+ Name: "MissingRequestMessage",
+ },
+ Response: RPCMessage{
+ Name: "QueryUsersResponse",
+ },
+ },
+ },
+ }, gjson.Parse(`{"variables":{}}`))
+ require.ErrorContains(t, err, `request message type "MissingRequestMessage" for method "QueryUsers" not found in protobuf schema`)
+
+ _, err = compiler.Compile(&RPCExecutionPlan{
+ Calls: []RPCCall{
+ {
+ MethodName: "QueryUsers",
+ Request: RPCMessage{
+ Name: "QueryUsersRequest",
+ },
+ Response: RPCMessage{
+ Name: "MissingResponseMessage",
+ },
+ },
+ },
+ }, gjson.Parse(`{"variables":{}}`))
+ require.ErrorContains(t, err, `response message type "MissingResponseMessage" for method "QueryUsers" not found in protobuf schema`)
+}
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go
index 1eb2b6c..65c8af8 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan.go
@@ -126,11 +126,11 @@ func (r RPCFieldSelectionSet) SelectFieldsForTypes(validTypes []string) RPCField
}
for _, field := range lookupFields {
- if _, found := fieldSet[field.Name]; found {
+ if _, found := fieldSet[field.JSONPath]; found {
continue
}
- fieldSet[field.Name] = struct{}{}
+ fieldSet[field.JSONPath] = struct{}{}
fields = append(fields, field)
}
}
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go
index 5c5f066..b06ed8c 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_test.go
@@ -1374,6 +1374,35 @@ func TestQueryExecutionPlans(t *testing.T) {
}
}
+func TestQueryExecutionPlan_UsesFieldAliasAsResponsePath(t *testing.T) {
+ report := &operationreport.Report{}
+ schemaDoc := grpctest.MustGraphQLSchema(t)
+
+ astvalidation.DefaultDefinitionValidator().Validate(&schemaDoc, report)
+ require.False(t, report.HasErrors())
+
+ query := `query { users { userId: id userName: name } }`
+ queryDoc, queryReport := astparser.ParseGraphqlDocumentString(query)
+ require.False(t, queryReport.HasErrors())
+
+ astvalidation.DefaultOperationValidator().Validate(&queryDoc, &schemaDoc, report)
+ require.False(t, report.HasErrors())
+
+ planner := NewPlanner("Products", testMapping())
+ outPlan, err := planner.PlanOperation(&queryDoc, &schemaDoc)
+ require.NoError(t, err)
+ require.Len(t, outPlan.Calls, 1)
+ require.Len(t, outPlan.Calls[0].Response.Fields, 1)
+ require.NotNil(t, outPlan.Calls[0].Response.Fields[0].Message)
+
+ messageFields := outPlan.Calls[0].Response.Fields[0].Message.Fields
+ require.Len(t, messageFields, 2)
+ require.Equal(t, "id", messageFields[0].Name)
+ require.Equal(t, "userId", messageFields[0].JSONPath)
+ require.Equal(t, "name", messageFields[1].Name)
+ require.Equal(t, "userName", messageFields[1].JSONPath)
+}
+
func TestCompositeTypeExecutionPlan(t *testing.T) {
tests := []struct {
name string
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go
index f1ad122..11ec5da 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go
@@ -289,6 +289,7 @@ func (r *rpcPlanVisitor) handleRootField(ref int) error {
// EnterField implements astvisitor.EnterFieldVisitor.
func (r *rpcPlanVisitor) EnterField(ref int) {
fieldName := r.operation.FieldNameString(ref)
+ fieldAliasOrName := r.operation.FieldAliasOrNameString(ref)
if r.IsRootField() {
if err := r.handleRootField(ref); err != nil {
r.walker.StopWithInternalErr(err)
@@ -310,11 +311,6 @@ func (r *rpcPlanVisitor) EnterField(ref int) {
return
}
- // prevent duplicate fields
- if r.planInfo.currentResponseMessage.Fields.Exists(fieldName) {
- return
- }
-
fd, ok := r.walker.FieldDefinition(ref)
if !ok {
r.walker.Report.AddExternalError(operationreport.ExternalError{
@@ -328,10 +324,17 @@ func (r *rpcPlanVisitor) EnterField(ref int) {
parentTypeName := r.walker.EnclosingTypeDefinition.NameString(r.definition)
+ // prevent duplicate response fields for the same response key
+ for _, existingField := range r.planInfo.currentResponseMessage.Fields {
+ if existingField.JSONPath == fieldAliasOrName {
+ return
+ }
+ }
+
field := RPCField{
Name: r.resolveFieldMapping(parentTypeName, fieldName),
TypeName: typeName.String(),
- JSONPath: fieldName,
+ JSONPath: fieldAliasOrName,
Repeated: r.definition.TypeIsList(fdt),
}
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
index 71bf396..f2aaca3 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
@@ -830,6 +830,22 @@ func Test_Datasource_Load_WithUnionTypes(t *testing.T) {
}
},
},
+ {
+ name: "Mutation perform action with aliases",
+ query: `mutation($input: ActionInput!) { actionAlias: performAction(input: $input) { typeName: __typename ... on ActionSuccess { aliasedMessage: message at: timestamp } ... on ActionError { aliasedMessage: message errorCode: code } } }`,
+ vars: `{"variables":{"input":{"type":"create_user","payload":"user data"}}}`,
+ validate: func(t *testing.T, data map[string]interface{}) {
+ actionResult, ok := data["actionAlias"].(map[string]interface{})
+ require.True(t, ok, "actionAlias should be an object")
+ require.NotEmpty(t, actionResult, "actionAlias should not be empty")
+ require.Equal(t, "ActionSuccess", actionResult["typeName"])
+ require.Equal(t, "Action 'create_user' completed successfully", actionResult["aliasedMessage"])
+ require.Equal(t, "2024-01-01T00:00:00Z", actionResult["at"])
+ require.NotContains(t, actionResult, "__typename")
+ require.NotContains(t, actionResult, "message")
+ require.NotContains(t, actionResult, "timestamp")
+ },
+ },
{
name: "Mutation perform action - success case",
query: `mutation($input: ActionInput!) { performAction(input: $input) { __typename ... on ActionSuccess { message timestamp } ... on ActionError { message code } } }`,
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go b/app/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go
index 10313fe..ae31951 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/mapping_test_helper.go
@@ -87,9 +87,9 @@ func testMapping() *GRPCMapping {
},
MutationRPCs: RPCConfigMap{
"createUser": {
- RPC: "CreateUser",
- Request: "CreateUserRequest",
- Response: "CreateUserResponse",
+ RPC: "MutationCreateUser",
+ Request: "MutationCreateUserRequest",
+ Response: "MutationCreateUserResponse",
},
"performAction": {
RPC: "MutationPerformAction",
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/grpctest/mapping/mapping.go b/app/v2/pkg/grpctest/mapping/mapping.go
index 9282fa5..1e3e71b 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/grpctest/mapping/mapping.go
+++ b/app/v2/pkg/grpctest/mapping/mapping.go
@@ -89,9 +89,9 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping {
},
MutationRPCs: grpcdatasource.RPCConfigMap{
"createUser": {
- RPC: "CreateUser",
- Request: "CreateUserRequest",
- Response: "CreateUserResponse",
+ RPC: "MutationCreateUser",
+ Request: "MutationCreateUserRequest",
+ Response: "MutationCreateUserResponse",
},
"performAction": {
RPC: "MutationPerformAction",
@@ -469,6 +469,25 @@ func DefaultGRPCMapping() *grpcdatasource.GRPCMapping {
TargetName: "payload",
},
},
+ "SearchResult": {
+ "product": {
+ TargetName: "product",
+ },
+ "user": {
+ TargetName: "user",
+ },
+ "category": {
+ TargetName: "category",
+ },
+ },
+ "ActionResult": {
+ "actionSuccess": {
+ TargetName: "action_success",
+ },
+ "actionError": {
+ TargetName: "action_error",
+ },
+ },
},
}
}
diff --git a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/grpctest/schema.go b/app/v2/pkg/grpctest/schema.go
index 0e2a9bf..3cbc084 100644
--- a/tmp/agent-patch-flux-pr-1209.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/grpctest/schema.go
+++ b/app/v2/pkg/grpctest/schema.go
@@ -196,6 +196,16 @@ func GetFieldConfigurations() plan.FieldConfigurations {
},
},
},
+ {
+ TypeName: "Mutation",
+ FieldName: "performAction",
+ Arguments: []plan.ArgumentConfiguration{
+ {
+ Name: "input",
+ SourceType: plan.FieldArgumentSource,
+ },
+ },
+ },
}
}
@@ -228,17 +238,22 @@ func GetDataSourceMetadata() *plan.DataSourceMetadata {
"typeFilterWithArguments",
"typeWithMultipleFilterFields",
"complexFilterType",
+ "calculateTotals",
"categories",
"categoriesByKind",
+ "categoriesByKinds",
"filterCategories",
"randomPet",
"allPets",
+ "search",
+ "randomSearchResult",
},
},
{
TypeName: "Mutation",
FieldNames: []string{
"createUser",
+ "performAction",
},
},
},
@@ -370,6 +385,20 @@ func GetDataSourceMetadata() *plan.DataSourceMetadata {
"modifiers",
},
},
+ {
+ TypeName: "ActionSuccess",
+ FieldNames: []string{
+ "message",
+ "timestamp",
+ },
+ },
+ {
+ TypeName: "ActionError",
+ FieldNames: []string{
+ "message",
+ "code",
+ },
+ },
},
}
}