agent_patch
runs/2026-02-28__13-38-10__gpt-5-4/flux-pr-1268/flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/agent-logs/agent.patch
25921 bytes
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
index 316e2fc..f347100 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
@@ -269,14 +269,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias
return "", false
}
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
- return plan.DataSourcePlanningBehavior{
- MergeAliasedRootNodes: true,
- OverrideFieldPathFromAlias: true,
- IncludeTypeNameFields: true,
- }
-}
-
func (p *Planner[T]) Register(visitor *plan.Visitor, configuration plan.DataSourceConfiguration[T], dataSourcePlannerConfiguration plan.DataSourcePlannerConfiguration) error {
p.visitor = visitor
@@ -1825,6 +1817,15 @@ func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguratio
return schema, true
}
+func (f *Factory[T]) PlanningBehavior() plan.DataSourcePlanningBehavior {
+ return plan.DataSourcePlanningBehavior{
+ MergeAliasedRootNodes: true,
+ OverrideFieldPathFromAlias: true,
+ AllowPlanningTypeName: true,
+ AlwaysFlattenFragments: f.grpcClient != nil || f.grpcClientProvider != nil,
+ }
+}
+
type Source struct {
httpClient *http.Client
}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/factory.go b/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
index a251521..5f97576 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
@@ -29,3 +29,11 @@ func (f *Factory[T]) Context() context.Context {
func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguration[T]) (*ast.Document, bool) {
return nil, false
}
+
+func (f *Factory[T]) PlanningBehavior() plan.DataSourcePlanningBehavior {
+ return plan.DataSourcePlanningBehavior{
+ MergeAliasedRootNodes: false,
+ OverrideFieldPathFromAlias: true,
+ AllowPlanningTypeName: true,
+ }
+}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/planner.go b/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
index 2b05800..481dc3c 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
@@ -45,14 +45,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(_ int) (alias string, exists b
return
}
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
- return plan.DataSourcePlanningBehavior{
- MergeAliasedRootNodes: false,
- OverrideFieldPathFromAlias: true,
- IncludeTypeNameFields: true,
- }
-}
-
func (p *Planner[T]) EnterField(ref int) {
fieldName := p.v.Operation.FieldNameString(ref)
fieldAliasOrName := p.v.Operation.FieldAliasOrNameString(ref)
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go b/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
index 60faa27..9e14ba1 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
+++ b/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
@@ -275,14 +275,6 @@ func (p *Planner[T]) ConfigureSubscription() plan.SubscriptionConfiguration {
return plan.SubscriptionConfiguration{}
}
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
- return plan.DataSourcePlanningBehavior{
- MergeAliasedRootNodes: false,
- OverrideFieldPathFromAlias: false,
- IncludeTypeNameFields: true,
- }
-}
-
func (p *Planner[T]) DownstreamResponseFieldAlias(_ int) (alias string, exists bool) {
return "", false
}
@@ -316,6 +308,14 @@ func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguratio
return nil, false
}
+func (f *Factory[T]) PlanningBehavior() plan.DataSourcePlanningBehavior {
+ return plan.DataSourcePlanningBehavior{
+ MergeAliasedRootNodes: false,
+ OverrideFieldPathFromAlias: false,
+ AllowPlanningTypeName: true,
+ }
+}
+
func buildEventDataBytes(ref int, visitor *plan.Visitor, variables *resolve.Variables) ([]byte, error) {
// Collect the field arguments for fetch based operations
fieldArgs := visitor.Operation.FieldArguments(ref)
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go b/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
index 3449afb..c05efc7 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
+++ b/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
@@ -18,7 +18,7 @@ type Configuration struct {
type Factory[T Configuration] struct{}
-func (f *Factory[T]) Planner(logger abstractlogger.Logger) plan.DataSourcePlanner[T] {
+func (f *Factory[T]) Planner(_ abstractlogger.Logger) plan.DataSourcePlanner[T] {
return &Planner[T]{}
}
@@ -26,10 +26,14 @@ func (f *Factory[T]) Context() context.Context {
return context.TODO()
}
-func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguration[T]) (*ast.Document, bool) {
+func (f *Factory[T]) UpstreamSchema(_ plan.DataSourceConfiguration[T]) (*ast.Document, bool) {
return nil, false
}
+func (f *Factory[T]) PlanningBehavior() plan.DataSourcePlanningBehavior {
+ return plan.DataSourcePlanningBehavior{}
+}
+
type Planner[T Configuration] struct {
id int
config Configuration
@@ -48,13 +52,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias
return
}
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
- return plan.DataSourcePlanningBehavior{
- MergeAliasedRootNodes: false,
- OverrideFieldPathFromAlias: false,
- }
-}
-
func (p *Planner[T]) Register(_ *plan.Visitor, configuration plan.DataSourceConfiguration[T], _ plan.DataSourcePlannerConfiguration) error {
p.config = Configuration(configuration.CustomConfiguration())
return nil
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
index 284ad42..2bfffcf 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
@@ -13,9 +13,10 @@ import (
)
var (
- FieldDoesntHaveSelectionSetErr = errors.New("unexpected error: field does not have a selection set")
- InlineFragmentDoesntHaveSelectionSetErr = errors.New("unexpected error: inline fragment does not have a selection set")
- InlineFragmentTypeIsNotExistsErr = errors.New("unexpected error: inline fragment type condition does not exists")
+ ErrFieldHasNoSelectionSet = errors.New("unexpected error: field does not have a selection set")
+ ErrInlineFragmentHasNoSelectionSet = errors.New("unexpected error: inline fragment does not have a selection set")
+ ErrInlineFragmentHasNoCondition = errors.New("unexpected error: inline fragment type condition does not exists")
+ ErrNoUpstreamSchema = errors.New("unexpected error: upstream schema is not defined in DataSource")
)
/*
@@ -65,6 +66,7 @@ type fieldSelectionRewriter struct {
dsConfiguration DataSource
skipFieldRefs []int
+ alwaysRewrite bool
}
type RewriteResult struct {
@@ -74,19 +76,19 @@ type RewriteResult struct {
var resultNotRewritten = RewriteResult{}
-func newFieldSelectionRewriter(operation *ast.Document, definition *ast.Document) *fieldSelectionRewriter {
- return &fieldSelectionRewriter{
- operation: operation,
- definition: definition,
+func newFieldSelectionRewriter(operation *ast.Document, definition *ast.Document, dsConfiguration DataSource) (*fieldSelectionRewriter, error) {
+ upstreamDefinition, ok := dsConfiguration.UpstreamSchema()
+ if !ok {
+ return nil, ErrNoUpstreamSchema
}
-}
-
-func (r *fieldSelectionRewriter) SetUpstreamDefinition(upstreamDefinition *ast.Document) {
- r.upstreamDefinition = upstreamDefinition
-}
-func (r *fieldSelectionRewriter) SetDatasourceConfiguration(dsConfiguration DataSource) {
- r.dsConfiguration = dsConfiguration
+ return &fieldSelectionRewriter{
+ operation: operation,
+ definition: definition,
+ upstreamDefinition: upstreamDefinition,
+ dsConfiguration: dsConfiguration,
+ alwaysRewrite: dsConfiguration.PlanningBehavior().AlwaysFlattenFragments,
+ }, nil
}
func (r *fieldSelectionRewriter) RewriteFieldSelection(fieldRef int, enclosingNode ast.Node) (res RewriteResult, err error) {
@@ -168,7 +170,18 @@ func (r *fieldSelectionRewriter) processUnionSelection(fieldRef int, unionDefRef
}, nil
}
+func (r *fieldSelectionRewriter) mustRewrite(selectionSetInfo selectionSetInfo) bool {
+ return r.alwaysRewrite &&
+ (selectionSetInfo.hasInlineFragmentsOnInterfaces ||
+ selectionSetInfo.hasInlineFragmentsOnUnions ||
+ selectionSetInfo.hasInlineFragmentsOnObjects)
+}
+
func (r *fieldSelectionRewriter) unionFieldSelectionNeedsRewrite(selectionSetInfo selectionSetInfo, unionTypeNames, entityNames []string) (needRewrite bool) {
+ if r.mustRewrite(selectionSetInfo) {
+ return true
+ }
+
if selectionSetInfo.hasInlineFragmentsOnObjects {
// when we have types not exists in the current datasource - we need to rewrite
if r.objectFragmentsRequiresCleanup(selectionSetInfo.inlineFragmentsOnObjects, unionTypeNames) {
@@ -263,7 +276,7 @@ func (r *fieldSelectionRewriter) replaceFieldSelections(fieldRef int, newSelecti
func (r *fieldSelectionRewriter) processObjectSelection(fieldRef int, objectDefRef int) (res RewriteResult, err error) {
selectionSetRef, ok := r.operation.FieldSelectionSet(fieldRef)
if !ok {
- return resultNotRewritten, FieldDoesntHaveSelectionSetErr
+ return resultNotRewritten, ErrFieldHasNoSelectionSet
}
fieldTypeName := r.definition.ObjectTypeDefinitionNameBytes(objectDefRef)
@@ -346,6 +359,10 @@ func (r *fieldSelectionRewriter) rewriteObjectSelection(fieldRef int, fieldInfo
}
func (r *fieldSelectionRewriter) objectFieldSelectionNeedsRewrite(selectionSetInfo selectionSetInfo, objectTypeName string) (needRewrite bool) {
+ if r.mustRewrite(selectionSetInfo) {
+ return true
+ }
+
if selectionSetInfo.hasInlineFragmentsOnObjects {
if r.objectFragmentsRequiresCleanup(selectionSetInfo.inlineFragmentsOnObjects, []string{objectTypeName}) {
return true
@@ -412,6 +429,10 @@ func (r *fieldSelectionRewriter) processInterfaceSelection(fieldRef int, interfa
}
func (r *fieldSelectionRewriter) interfaceFieldSelectionNeedsRewrite(selectionSetInfo selectionSetInfo, interfaceTypeNames []string, entityNames []string) (needRewrite bool) {
+ if r.mustRewrite(selectionSetInfo) {
+ return true
+ }
+
// when we do not have fragments
if !selectionSetInfo.hasInlineFragmentsOnInterfaces &&
!selectionSetInfo.hasInlineFragmentsOnUnions &&
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
index 950ccb0..61a76ab 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
@@ -83,7 +83,7 @@ func (r *fieldSelectionRewriter) selectionSetFieldSelections(selectionSetRef int
func (r *fieldSelectionRewriter) collectFieldInformation(fieldRef int) (selectionSetInfo, error) {
fieldSelectionSetRef, ok := r.operation.FieldSelectionSet(fieldRef)
if !ok {
- return selectionSetInfo{}, FieldDoesntHaveSelectionSetErr
+ return selectionSetInfo{}, ErrFieldHasNoSelectionSet
}
return r.collectSelectionSetInformation(fieldSelectionSetRef)
@@ -101,7 +101,7 @@ func (r *fieldSelectionRewriter) collectInlineFragmentInformation(
typeCondition := r.operation.InlineFragmentTypeConditionNameString(inlineFragmentRef)
inlineFragmentSelectionSetRef, ok := r.operation.InlineFragmentSelectionSet(inlineFragmentRef)
if !ok {
- return InlineFragmentDoesntHaveSelectionSetErr
+ return ErrInlineFragmentHasNoSelectionSet
}
hasDirectives := r.operation.InlineFragmentHasDirectives(inlineFragmentRef)
@@ -110,7 +110,7 @@ func (r *fieldSelectionRewriter) collectInlineFragmentInformation(
// because it could be absent in the current SUBGRAPH document
definitionNode, hasNode := r.definition.NodeByNameStr(typeCondition)
if !hasNode {
- return InlineFragmentTypeIsNotExistsErr
+ return ErrInlineFragmentHasNoCondition
}
selectionSetInfo, err := r.collectSelectionSetInformation(inlineFragmentSelectionSetRef)
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
index 11b5fc8..df18217 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
@@ -46,12 +46,27 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
break
}
}
+ require.NotEqual(t, ast.InvalidRef, fieldRef)
+
+ if cfg, ok := testCase.dsConfiguration.(*dataSourceConfiguration[any]); ok {
+ behavior := cfg.PlanningBehavior()
+ if cfg.factory == nil {
+ cfg.factory = &FakeFactory[any]{
+ upstreamSchema: &upstreamDef,
+ behavior: &behavior,
+ }
+ } else if _, hasSchema := cfg.UpstreamSchema(); !hasSchema {
+ cfg.factory = &FakeFactory[any]{
+ upstreamSchema: &upstreamDef,
+ behavior: &behavior,
+ }
+ }
+ }
node, _ := def.Index.FirstNodeByNameStr(testCase.enclosingTypeName)
- rewriter := newFieldSelectionRewriter(&op, &def)
- rewriter.SetUpstreamDefinition(&upstreamDef)
- rewriter.SetDatasourceConfiguration(testCase.dsConfiguration)
+ rewriter, err := newFieldSelectionRewriter(&op, &def, testCase.dsConfiguration)
+ require.NoError(t, err)
result, err := rewriter.RewriteFieldSelection(fieldRef, node)
require.NoError(t, err)
@@ -179,7 +194,113 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
}).
DS()
+ definitionB := `
+ type Query {
+ named: Named
+ union: U
+ }
+
+ union U = User
+
+ interface Named {
+ name: String
+ }
+
+ interface Numbered {
+ number: Int
+ }
+
+ type User implements Named & Numbered {
+ id: ID
+ name: String
+ number: Int
+ }`
+
testCases := []testCase{
+ {
+ name: "should flatten interfaces for gRPC",
+ fieldName: "named",
+ definition: definitionB,
+ upstreamDefinition: definitionB,
+ dsConfiguration: dsb().
+ WithBehavior(DataSourcePlanningBehavior{AlwaysFlattenFragments: true}).
+ RootNode("Query", "named", "union").
+ RootNode("User", "id", "name", "number").
+ ChildNode("Named", "name").
+ ChildNode("Numbered", "number").
+ KeysMetadata(FederationFieldConfigurations{
+ {
+ TypeName: "User",
+ SelectionSet: "id",
+ },
+ }).
+ DS(),
+ operation: `
+ query {
+ named {
+ ... on Numbered {
+ ... on User {
+ name
+ }
+ }
+ ... on User {
+ id
+ }
+ }
+ }`,
+ expectedOperation: `
+ query {
+ named {
+ ... on User {
+ id
+ name
+ }
+ }
+ }`,
+ shouldRewrite: true,
+ },
+ {
+ name: "should flatten union for gRPC",
+ fieldName: "union",
+ definition: definitionB,
+ upstreamDefinition: definitionB,
+ dsConfiguration: dsb().
+ WithBehavior(DataSourcePlanningBehavior{AlwaysFlattenFragments: true}).
+ RootNode("Query", "named", "union").
+ RootNode("User", "id", "name", "number").
+ ChildNode("Named", "name").
+ ChildNode("Numbered", "number").
+ KeysMetadata(FederationFieldConfigurations{
+ {
+ TypeName: "User",
+ SelectionSet: "id",
+ },
+ }).
+ DS(),
+ operation: `
+ query {
+ union {
+ ... on Numbered {
+ ... on User {
+ name
+ }
+ }
+ ... on User {
+ id
+ }
+ }
+ }`,
+ expectedOperation: `
+ query {
+ union {
+ ... on User {
+ id
+ name
+ }
+ }
+ }`,
+ shouldRewrite: true,
+ },
{
name: "one field is external. query without fragments",
definition: definition,
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/datasource_configuration.go b/app/v2/pkg/engine/plan/datasource_configuration.go
index 07ec63e..62b0b00 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/datasource_configuration.go
+++ b/app/v2/pkg/engine/plan/datasource_configuration.go
@@ -25,6 +25,7 @@ type PlannerFactory[DataSourceSpecificConfiguration any] interface {
// This method serves as a flag that factory should have a context
Context() context.Context
UpstreamSchema(dataSourceConfig DataSourceConfiguration[DataSourceSpecificConfiguration]) (*ast.Document, bool)
+ PlanningBehavior() DataSourcePlanningBehavior
}
type DataSourceMetadata struct {
@@ -245,15 +246,12 @@ type DataSourceConfiguration[T any] interface {
CustomConfiguration() T
}
-type DataSourceUpstreamSchema interface {
- UpstreamSchema() (*ast.Document, bool)
-}
-
type DataSource interface {
FederationInfo
NodesInfo
DirectivesConfigurations
- DataSourceUpstreamSchema
+ UpstreamSchema() (*ast.Document, bool)
+ PlanningBehavior() DataSourcePlanningBehavior
Id() string
Name() string
Hash() DSHash
@@ -287,6 +285,10 @@ func (d *dataSourceConfiguration[T]) UpstreamSchema() (*ast.Document, bool) {
return d.factory.UpstreamSchema(d)
}
+func (d *dataSourceConfiguration[T]) PlanningBehavior() DataSourcePlanningBehavior {
+ return d.factory.PlanningBehavior()
+}
+
func (d *dataSourceConfiguration[T]) Id() string {
return d.id
}
@@ -383,8 +385,10 @@ type DataSourcePlanningBehavior struct {
// When true expected response will be { "rootField": ..., "alias": ... }
// When false expected response will be { "rootField": ..., "original": ... }
OverrideFieldPathFromAlias bool
- // IncludeTypeNameFields should be set to true if the planner allows to plan __typename fields
- IncludeTypeNameFields bool
+ // AllowPlanningTypeName set to true will allow the planner to plan __typename fields.
+ AllowPlanningTypeName bool
+ // AlwaysFlattenFragments rewrites inline fragments to concrete types unconditionally.
+ AlwaysFlattenFragments bool
}
type DataSourceFetchPlanner interface {
@@ -393,7 +397,6 @@ type DataSourceFetchPlanner interface {
}
type DataSourceBehavior interface {
- DataSourcePlanningBehavior() DataSourcePlanningBehavior
// DownstreamResponseFieldAlias allows the DataSourcePlanner to overwrite the response path with an alias
// It's required to set OverrideFieldPathFromAlias to true
// This function is useful in the following scenario
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go b/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
index acf02a9..9a3584c 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
+++ b/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
@@ -64,6 +64,16 @@ func (b *dsBuilder) Schema(schema string) *dsBuilder {
return b
}
+func (b *dsBuilder) SchemaMergedWithBase(schema string) *dsBuilder {
+ def := unsafeparser.ParseGraphqlDocumentStringWithBaseSchema(schema)
+ b.ds.factory = &FakeFactory[any]{
+ upstreamSchema: &def,
+ behavior: b.behavior,
+ }
+
+ return b
+}
+
func (b *dsBuilder) KeysMetadata(keys FederationFieldConfigurations) *dsBuilder {
b.ds.FederationMetaData.Keys = keys
return b
@@ -85,6 +95,11 @@ func (b *dsBuilder) Id(id string) *dsBuilder {
}
func (b *dsBuilder) DS() DataSource {
+ if b.ds.factory == nil {
+ b.ds.factory = &FakeFactory[any]{
+ behavior: b.behavior,
+ }
+ }
if err := b.ds.DataSourceMetadata.Init(); err != nil {
panic(err)
}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/node_selection_visitor.go b/app/v2/pkg/engine/plan/node_selection_visitor.go
index 95c4f01..fa2d045 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/node_selection_visitor.go
+++ b/app/v2/pkg/engine/plan/node_selection_visitor.go
@@ -644,14 +644,15 @@ func (c *nodeSelectionVisitor) rewriteSelectionSetHavingAbstractFragments(fieldR
}
c.visitedFieldsAbstractChecks[fieldRef] = struct{}{}
- upstreamSchema, ok := ds.UpstreamSchema()
- if !ok {
+ if _, ok := ds.UpstreamSchema(); !ok {
return
}
- rewriter := newFieldSelectionRewriter(c.operation, c.definition)
- rewriter.SetUpstreamDefinition(upstreamSchema)
- rewriter.SetDatasourceConfiguration(ds)
+ rewriter, err := newFieldSelectionRewriter(c.operation, c.definition, ds)
+ if err != nil {
+ c.walker.StopWithInternalErr(err)
+ return
+ }
result, err := rewriter.RewriteFieldSelection(fieldRef, c.walker.EnclosingTypeDefinition)
if err != nil {
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/path_builder_visitor.go b/app/v2/pkg/engine/plan/path_builder_visitor.go
index bd4d6b2..a551826 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/path_builder_visitor.go
+++ b/app/v2/pkg/engine/plan/path_builder_visitor.go
@@ -719,8 +719,8 @@ func (c *pathBuilderVisitor) isAllFieldDependenciesOnSameDataSource(fieldRef int
func (c *pathBuilderVisitor) planWithExistingPlanners(fieldRef int, typeName, fieldName, currentPath, parentPath, precedingParentPath string, suggestion *NodeSuggestion) (plannerIdx int, planned bool) {
for plannerIdx, plannerConfig := range c.planners {
- planningBehaviour := plannerConfig.DataSourcePlanningBehavior()
dsConfiguration := plannerConfig.DataSourceConfiguration()
+ planningBehaviour := dsConfiguration.PlanningBehavior()
currentPlannerDSHash := dsConfiguration.Hash()
hasSuggestion := suggestion != nil
@@ -1247,7 +1247,7 @@ func (c *pathBuilderVisitor) addPlannerPathForTypename(
if fieldName != typeNameField {
return false
}
- if !planningBehaviour.IncludeTypeNameFields {
+ if !planningBehaviour.AllowPlanningTypeName {
return false
}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/planner_configuration.go b/app/v2/pkg/engine/plan/planner_configuration.go
index 69e23e8..7bc5614 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/planner_configuration.go
+++ b/app/v2/pkg/engine/plan/planner_configuration.go
@@ -62,10 +62,6 @@ func (p *plannerConfiguration[T]) ObjectFetchConfiguration() *objectFetchConfigu
return p.objectFetchConfiguration
}
-func (p *plannerConfiguration[T]) DataSourcePlanningBehavior() DataSourcePlanningBehavior {
- return p.planner.DataSourcePlanningBehavior()
-}
-
func (p *plannerConfiguration[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool) {
return p.planner.DownstreamResponseFieldAlias(downstreamFieldRef)
}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/planner_test.go b/app/v2/pkg/engine/plan/planner_test.go
index 0a498ad..c377dae 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/planner_test.go
+++ b/app/v2/pkg/engine/plan/planner_test.go
@@ -997,7 +997,14 @@ type FakeFactory[T any] struct {
}
func (f *FakeFactory[T]) UpstreamSchema(dataSourceConfig DataSourceConfiguration[T]) (*ast.Document, bool) {
- return f.upstreamSchema, true
+ return f.upstreamSchema, f.upstreamSchema != nil
+}
+
+func (f *FakeFactory[T]) PlanningBehavior() DataSourcePlanningBehavior {
+ if f.behavior == nil {
+ return DataSourcePlanningBehavior{}
+ }
+ return *f.behavior
}
func (f *FakeFactory[T]) Planner(logger abstractlogger.Logger) DataSourcePlanner[T] {
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/visitor.go b/app/v2/pkg/engine/plan/visitor.go
index 848c5cc..a49955f 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/visitor.go
+++ b/app/v2/pkg/engine/plan/visitor.go
@@ -1021,7 +1021,7 @@ func (v *Visitor) resolveFieldPath(ref int) []string {
aliasOverride := false
if plannerConfig != nil && plannerConfig.Planner() != nil {
- aliasOverride = plannerConfig.DataSourcePlanningBehavior().OverrideFieldPathFromAlias
+ aliasOverride = plannerConfig.DataSourceConfiguration().PlanningBehavior().OverrideFieldPathFromAlias
}
for i := range v.Config.Fields {