Run D&D spell lanes through typed artifacts

This commit is contained in:
2026-07-17 07:19:58 +00:00
parent 52e6b31408
commit 66de1a5520
17 changed files with 699 additions and 56 deletions

View File

@@ -1,6 +1,7 @@
package pipeline
import (
"context"
"fmt"
"reflect"
"strings"
@@ -28,6 +29,7 @@ type typedMergerEntry struct {
valueType reflect.Type
validateOptions OptionValidator
builder func(BuildRequest) (any, error)
merge typedMergeOperation
}
func NewMergerRegistry() *MergerRegistry {
@@ -127,6 +129,25 @@ func RegisterMergerBuilder[T any](registry *MergerRegistry, spec ModuleSpec, val
builder: func(request BuildRequest) (any, error) {
return builder(cloneBuildRequest(request))
},
merge: func(ctx context.Context, implementation any, request contracts.TypedMergeRequest[any]) (erasedTypedResult, error) {
merger, ok := implementation.(contracts.Merger[T])
if !ok {
return erasedTypedResult{}, fmt.Errorf("merger %q has incompatible implementation %T", normalizedSpec.Key, implementation)
}
outputs := make([]contracts.ExtractArtifact[T], len(request.ExtractOutputs))
for i, output := range request.ExtractOutputs {
value, err := exactTypedValue[T]("merge extract value", output.Value)
if err != nil {
return erasedTypedResult{}, err
}
outputs[i] = contracts.ExtractArtifact[T]{LaneID: output.LaneID, ExtractorKey: output.ExtractorKey, SourceID: output.SourceID, ChunkID: output.ChunkID, ChunkIndex: output.ChunkIndex, ChunkRef: output.ChunkRef, Value: value}
}
result, err := merger.Merge(ctx, contracts.TypedMergeRequest[T]{Source: request.Source, LaneID: request.LaneID, ExtractOutputs: outputs, SourceInput: request.SourceInput, SessionID: request.SessionID, References: request.References, LLMProfile: request.LLMProfile, Metadata: request.Metadata})
if err != nil {
return erasedTypedResult{}, err
}
return erasedTypedResult{Value: result.Value, Warnings: result.Warnings}, nil
},
}
return nil
}