agent_patch
runs/2026-02-28__13-38-10__gpt-5-1-codex-mini/flux-pr-859/flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/agent-logs/agent.patch
14149 bytes
diff --git a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/configuration_visitor.go b/app/v2/pkg/engine/plan/configuration_visitor.go
index 505795a..11b459c 100644
--- a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/configuration_visitor.go
+++ b/app/v2/pkg/engine/plan/configuration_visitor.go
@@ -44,6 +44,7 @@ type configurationVisitor struct {
skipFieldsRefs []int // skipFieldsRefs holds required field refs added by planner and should not be added to user response
missingPathTracker map[string]missingPath // missingPathTracker is a map of paths which will be added on secondary runs
addedPathTracker []pathConfiguration // addedPathTracker is a list of paths which were added
+ addedPathIndex map[string]map[DSHash]struct{}
pendingRequiredFields map[int]selectionSetPendingRequirements // pendingRequiredFields is a map[selectionSetRef][]fieldsRequirementConfig
processedFieldNotHavingRequires map[int]struct{} // processedFieldNotHavingRequires is a map[FieldRef] of already processed fields which do not have @requires directive
@@ -184,27 +185,41 @@ func (c *configurationVisitor) saveAddedPath(configuration pathConfiguration) {
}
c.addedPathTracker = append(c.addedPathTracker, configuration)
+ if c.addedPathIndex == nil {
+ c.addedPathIndex = make(map[string]map[DSHash]struct{}, 8)
+ }
+ if _, exists := c.addedPathIndex[configuration.path]; !exists {
+ c.addedPathIndex[configuration.path] = make(map[DSHash]struct{}, 1)
+ }
+ c.addedPathIndex[configuration.path][configuration.dsHash] = struct{}{}
c.removeMissingPath(configuration.path)
}
func (c *configurationVisitor) addedPathDSHash(path string) (hash DSHash, ok bool) {
- // NOTE: it will found first occurence of such path
- for i := range c.addedPathTracker {
- if c.addedPathTracker[i].path == path {
- return c.addedPathTracker[i].dsHash, true
+ if c.addedPathIndex == nil {
+ return 0, false
+ }
+
+ if hashes, exists := c.addedPathIndex[path]; exists {
+ for dsHash := range hashes {
+ return dsHash, true
}
}
+
return 0, false
}
func (c *configurationVisitor) isPathAddedFor(path string, hash DSHash) bool {
- // TODO: could be optimized by using map[struct{path,hash}]
- for i := range c.addedPathTracker {
- if c.addedPathTracker[i].path == path && c.addedPathTracker[i].dsHash == hash {
- return true
- }
+ if c.addedPathIndex == nil {
+ return false
}
+
+ if hashes, exists := c.addedPathIndex[path]; exists {
+ _, ok := hashes[hash]
+ return ok
+ }
+
return false
}
@@ -300,6 +315,7 @@ func (c *configurationVisitor) EnterDocument(operation, definition *ast.Document
c.missingPathTracker = make(map[string]missingPath)
c.addedPathTracker = make([]pathConfiguration, 0, 8)
+ c.addedPathIndex = make(map[string]map[DSHash]struct{}, 8)
c.pendingRequiredFields = make(map[int]selectionSetPendingRequirements)
c.fieldDependenciesForPlanners = make(map[int][]int)
@@ -733,9 +749,7 @@ func (c *configurationVisitor) isParentPathIsRootOperationPath(parentPath string
}
func (c *configurationVisitor) allowNewPlannerForTypenameField(fieldName string, typeName string, parentPath string, dsCfg DataSource) bool {
- isEntityInterface := slices.ContainsFunc(dsCfg.FederationConfiguration().EntityInterfaces, func(interfaceObjCfg EntityInterfaceConfiguration) bool {
- return interfaceObjCfg.InterfaceTypeName == typeName || slices.Contains(interfaceObjCfg.ConcreteTypeNames, typeName)
- })
+ isEntityInterface := dsCfg.IsEntityInterfaceType(typeName)
if isEntityInterface {
return true
@@ -1226,13 +1240,7 @@ func (c *configurationVisitor) handleFieldsRequiredByKey(plannerIdx int, parentP
}
if len(requiredFieldsForType) > 0 {
- isInterfaceObject := false
- for _, interfaceObjCfg := range plannerConfig.DataSourceConfiguration().FederationConfiguration().InterfaceObjects {
- if slices.Contains(interfaceObjCfg.ConcreteTypeNames, typeName) {
- isInterfaceObject = true
- break
- }
- }
+ isInterfaceObject := plannerConfig.DataSourceConfiguration().HasInterfaceObjectConcreteType(typeName)
requiredFieldsConfiguration, planned := c.planKeyRequiredFields(plannerIdx, typeName, parentPath, requiredFieldsForType, isInterfaceObject)
if planned {
@@ -1287,9 +1295,7 @@ func (c *configurationVisitor) planKeyRequiredFields(currentPlannerIdx int, type
for _, possibleRequiredFieldConfig := range possibleRequiredFields {
if c.planners[i].DataSourceConfiguration().HasKeyRequirement(typeName, possibleRequiredFieldConfig.SelectionSet) {
- isInterfaceObject := slices.ContainsFunc(c.planners[i].DataSourceConfiguration().FederationConfiguration().InterfaceObjects, func(interfaceObjCfg EntityInterfaceConfiguration) bool {
- return slices.Contains(interfaceObjCfg.ConcreteTypeNames, typeName)
- })
+ isInterfaceObject := c.planners[i].DataSourceConfiguration().HasInterfaceObjectConcreteType(typeName)
skipTypename := forInterfaceObject && isInterfaceObject
diff --git a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_configuration.go b/app/v2/pkg/engine/plan/datasource_configuration.go
index f078113..6dde7ea 100644
--- a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_configuration.go
+++ b/app/v2/pkg/engine/plan/datasource_configuration.go
@@ -40,6 +40,14 @@ type DataSourceMetadata struct {
// Note: Unions are not present in the child or root nodes
ChildNodes TypeFields
Directives *DirectiveConfigurations
+
+ rootNodeLookup map[string]map[string]struct{}
+ childNodeLookup map[string]map[string]struct{}
+ rootTypeNames map[string]struct{}
+ childTypeNames map[string]struct{}
+ interfaceObjectMembers map[string]struct{}
+ interfaceObjectNameByType map[string]string
+ entityInterfaceMembers map[string]struct{}
}
type DirectivesConfigurations interface {
@@ -56,6 +64,10 @@ type NodesInfo interface {
HasRootNodeWithTypename(typeName string) bool
HasChildNode(typeName, fieldName string) bool
HasChildNodeWithTypename(typeName string) bool
+ IsEntityInterfaceType(typeName string) bool
+ IsInterfaceObjectType(typeName string) bool
+ HasInterfaceObjectConcreteType(typeName string) bool
+ InterfaceObjectNameForConcreteType(typeName string) (string, bool)
}
func (d *DataSourceMetadata) DirectiveConfigurations() *DirectiveConfigurations {
@@ -63,19 +75,130 @@ func (d *DataSourceMetadata) DirectiveConfigurations() *DirectiveConfigurations
}
func (d *DataSourceMetadata) HasRootNode(typeName, fieldName string) bool {
- return d.RootNodes.HasNode(typeName, fieldName)
+ d.ensureNodeLookups()
+ if fields, ok := d.rootNodeLookup[typeName]; ok {
+ _, hasField := fields[fieldName]
+ return hasField
+ }
+ return false
}
func (d *DataSourceMetadata) HasRootNodeWithTypename(typeName string) bool {
- return d.RootNodes.HasNodeWithTypename(typeName)
+ d.ensureNodeLookups()
+ _, ok := d.rootTypeNames[typeName]
+ return ok
}
func (d *DataSourceMetadata) HasChildNode(typeName, fieldName string) bool {
- return d.ChildNodes.HasNode(typeName, fieldName)
+ d.ensureNodeLookups()
+ if fields, ok := d.childNodeLookup[typeName]; ok {
+ _, hasField := fields[fieldName]
+ return hasField
+ }
+ return false
}
func (d *DataSourceMetadata) HasChildNodeWithTypename(typeName string) bool {
- return d.ChildNodes.HasNodeWithTypename(typeName)
+ d.ensureNodeLookups()
+ _, ok := d.childTypeNames[typeName]
+ return ok
+}
+
+func (d *DataSourceMetadata) ensureNodeLookups() {
+ if d.rootNodeLookup != nil && d.childNodeLookup != nil {
+ return
+ }
+
+ d.rootNodeLookup = make(map[string]map[string]struct{}, len(d.RootNodes))
+ d.childNodeLookup = make(map[string]map[string]struct{}, len(d.ChildNodes))
+ d.rootTypeNames = make(map[string]struct{}, len(d.RootNodes))
+ d.childTypeNames = make(map[string]struct{}, len(d.ChildNodes))
+
+ for _, node := range d.RootNodes {
+ d.rootTypeNames[node.TypeName] = struct{}{}
+
+ fields := d.rootNodeLookup[node.TypeName]
+ if fields == nil {
+ fields = make(map[string]struct{}, len(node.FieldNames))
+ d.rootNodeLookup[node.TypeName] = fields
+ }
+
+ for _, fieldName := range node.FieldNames {
+ fields[fieldName] = struct{}{}
+ }
+ }
+
+ for _, node := range d.ChildNodes {
+ d.childTypeNames[node.TypeName] = struct{}{}
+
+ fields := d.childNodeLookup[node.TypeName]
+ if fields == nil {
+ fields = make(map[string]struct{}, len(node.FieldNames))
+ d.childNodeLookup[node.TypeName] = fields
+ }
+
+ for _, fieldName := range node.FieldNames {
+ fields[fieldName] = struct{}{}
+ }
+ }
+}
+
+func (d *DataSourceMetadata) ensureInterfaceObjectLookup() {
+ if d.interfaceObjectMembers != nil {
+ return
+ }
+
+ d.interfaceObjectMembers = make(map[string]struct{}, len(d.InterfaceObjects)*2)
+ d.interfaceObjectNameByType = make(map[string]string, len(d.InterfaceObjects)*2)
+
+ for _, cfg := range d.InterfaceObjects {
+ d.interfaceObjectMembers[cfg.InterfaceTypeName] = struct{}{}
+ for _, typeName := range cfg.ConcreteTypeNames {
+ if _, exists := d.interfaceObjectNameByType[typeName]; !exists {
+ d.interfaceObjectNameByType[typeName] = cfg.InterfaceTypeName
+ }
+ d.interfaceObjectMembers[typeName] = struct{}{}
+ }
+ }
+}
+
+func (d *DataSourceMetadata) ensureEntityInterfaceLookup() {
+ if d.entityInterfaceMembers != nil {
+ return
+ }
+
+ d.entityInterfaceMembers = make(map[string]struct{}, len(d.EntityInterfaces)*2)
+
+ for _, cfg := range d.EntityInterfaces {
+ d.entityInterfaceMembers[cfg.InterfaceTypeName] = struct{}{}
+ for _, typeName := range cfg.ConcreteTypeNames {
+ d.entityInterfaceMembers[typeName] = struct{}{}
+ }
+ }
+}
+
+func (d *DataSourceMetadata) HasInterfaceObjectConcreteType(typeName string) bool {
+ d.ensureInterfaceObjectLookup()
+ _, ok := d.interfaceObjectNameByType[typeName]
+ return ok
+}
+
+func (d *DataSourceMetadata) IsInterfaceObjectType(typeName string) bool {
+ d.ensureInterfaceObjectLookup()
+ _, ok := d.interfaceObjectMembers[typeName]
+ return ok
+}
+
+func (d *DataSourceMetadata) InterfaceObjectNameForConcreteType(typeName string) (string, bool) {
+ d.ensureInterfaceObjectLookup()
+ name, ok := d.interfaceObjectNameByType[typeName]
+ return name, ok
+}
+
+func (d *DataSourceMetadata) IsEntityInterfaceType(typeName string) bool {
+ d.ensureEntityInterfaceLookup()
+ _, ok := d.entityInterfaceMembers[typeName]
+ return ok
}
func (d *DataSourceMetadata) ListRootNodes() TypeFields {
@@ -154,6 +277,22 @@ func (d *dataSourceConfiguration[T]) FederationConfiguration() FederationMetaDat
return d.FederationMetaData
}
+func (d *dataSourceConfiguration[T]) HasInterfaceObjectConcreteType(typeName string) bool {
+ return d.DataSourceMetadata.HasInterfaceObjectConcreteType(typeName)
+}
+
+func (d *dataSourceConfiguration[T]) IsInterfaceObjectType(typeName string) bool {
+ return d.DataSourceMetadata.IsInterfaceObjectType(typeName)
+}
+
+func (d *dataSourceConfiguration[T]) InterfaceObjectNameForConcreteType(typeName string) (string, bool) {
+ return d.DataSourceMetadata.InterfaceObjectNameForConcreteType(typeName)
+}
+
+func (d *dataSourceConfiguration[T]) IsEntityInterfaceType(typeName string) bool {
+ return d.DataSourceMetadata.IsEntityInterfaceType(typeName)
+}
+
func (d *dataSourceConfiguration[T]) Hash() DSHash {
return d.hash
}
diff --git a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_filter_collect_nodes_visitor.go b/app/v2/pkg/engine/plan/datasource_filter_collect_nodes_visitor.go
index 3852ed6..c295ed0 100644
--- a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_filter_collect_nodes_visitor.go
+++ b/app/v2/pkg/engine/plan/datasource_filter_collect_nodes_visitor.go
@@ -1,8 +1,6 @@
package plan
import (
- "slices"
-
"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
"github.com/wundergraph/graphql-go-tools/v2/pkg/astvisitor"
)
@@ -38,6 +36,9 @@ func (f *collectNodesVisitor) EnterField(ref int) {
if f.nodes.IsFieldSeen(ref) {
currentNodeId := TreeNodeID(ref)
f.parentNodeIds = append(f.parentNodeIds, currentNodeId)
+ if !f.operation.FieldHasSelections(ref) {
+ f.walker.SkipNode()
+ }
return
}
f.nodes.AddSeenField(ref)
@@ -64,12 +65,8 @@ func (f *collectNodesVisitor) EnterField(ref int) {
hasChildNode := v.HasChildNode(typeName, fieldName) || (isTypeName && v.HasChildNodeWithTypename(typeName))
allowTypeName := true
- // we should not select a typename on the interface object
- for _, k := range v.FederationConfiguration().InterfaceObjects {
- if k.InterfaceTypeName == typeName || slices.Contains(k.ConcreteTypeNames, typeName) {
- allowTypeName = false
- break
- }
+ if v.IsInterfaceObjectType(typeName) {
+ allowTypeName = false
}
lessPreferable := false
diff --git a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/visitor.go b/app/v2/pkg/engine/plan/visitor.go
index 9fa8e45..4c67369 100644
--- a/tmp/agent-patch-flux-pr-859.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/visitor.go
+++ b/app/v2/pkg/engine/plan/visitor.go
@@ -495,12 +495,9 @@ func (v *Visitor) addInterfaceObjectNameToTypeNames(fieldRef int, typeName []byt
continue
}
- for _, interfaceObjCfg := range v.planners[i].DataSourceConfiguration().FederationConfiguration().InterfaceObjects {
- if slices.Contains(interfaceObjCfg.ConcreteTypeNames, string(typeName)) {
- includeInterfaceObjectName = true
- interfaceObjectName = interfaceObjCfg.InterfaceTypeName
- break
- }
+ if name, ok := v.planners[i].DataSourceConfiguration().InterfaceObjectNameForConcreteType(string(typeName)); ok {
+ includeInterfaceObjectName = true
+ interfaceObjectName = name
}
}
if includeInterfaceObjectName {