Remove legacy raw pipeline contracts
This commit is contained in:
@@ -52,7 +52,7 @@ func (c *Codec) Encode(value dnd.SpellList) ([]byte, error) {
|
||||
}
|
||||
|
||||
// EncodeCandidate provides the same stable representation before typed
|
||||
// validators have approved a value on the temporary raw downstream path.
|
||||
// validators have approved a value.
|
||||
func (c *Codec) EncodeCandidate(value dnd.SpellList) ([]byte, error) {
|
||||
content, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
@@ -73,7 +73,7 @@ func (c *Codec) Decode(content []byte) (dnd.SpellList, error) {
|
||||
}
|
||||
|
||||
// DecodeCandidate reads the durable representation before semantic validators
|
||||
// have approved it on the temporary raw runner path.
|
||||
// have approved it.
|
||||
func (c *Codec) DecodeCandidate(content []byte) (dnd.SpellList, error) {
|
||||
decoder := json.NewDecoder(bytes.NewReader(content))
|
||||
decoder.DisallowUnknownFields()
|
||||
|
||||
@@ -39,18 +39,6 @@ type Extractor struct {
|
||||
llm contracts.StructuredLLMClient
|
||||
}
|
||||
|
||||
type rawAdapter struct {
|
||||
extractor *Extractor
|
||||
codec RawAdapterCodec
|
||||
}
|
||||
|
||||
type RawAdapterCodec interface {
|
||||
contracts.ArtifactCodec[dnd.SpellList]
|
||||
EncodeCandidate(dnd.SpellList) ([]byte, error)
|
||||
}
|
||||
|
||||
var _ contracts.LegacyRawExtractor = (*rawAdapter)(nil)
|
||||
|
||||
func New(llmClient contracts.StructuredLLMClient, _ Options) (*Extractor, error) {
|
||||
if llmClient == nil {
|
||||
return nil, extractorErrorf("LLM client must not be nil")
|
||||
@@ -169,66 +157,6 @@ func Register(registry *pipeline.ExtractorRegistry) error {
|
||||
})
|
||||
}
|
||||
|
||||
// RegisterWithRawAdapter keeps existing raw downstream implementations usable
|
||||
// while the extractor itself produces the canonical typed artifact.
|
||||
func RegisterWithRawAdapter(registry *pipeline.ExtractorRegistry, codec RawAdapterCodec) error {
|
||||
if codec == nil {
|
||||
return extractorErrorf("artifact codec must not be nil")
|
||||
}
|
||||
build := func(request pipeline.BuildRequest) (*Extractor, error) {
|
||||
options, err := DecodeOptions(request.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(request.Dependencies.LLM, options)
|
||||
}
|
||||
return pipeline.RegisterExtractorBuilderWithRawAdapter(registry, ModuleSpec(), validateOptions,
|
||||
func(request pipeline.BuildRequest) (contracts.Extractor[dnd.SpellList], error) {
|
||||
return build(request)
|
||||
},
|
||||
func(request pipeline.BuildRequest) (contracts.LegacyRawExtractor, error) {
|
||||
extractor, err := build(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rawAdapter{extractor: extractor, codec: codec}, nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (adapter *rawAdapter) Key() string { return Key }
|
||||
|
||||
func (adapter *rawAdapter) ReferenceSlots() []contracts.ReferenceSlot {
|
||||
return adapter.extractor.ReferenceSlots()
|
||||
}
|
||||
|
||||
func (adapter *rawAdapter) ManifestMetadata() map[string]any {
|
||||
return adapter.extractor.ManifestMetadata()
|
||||
}
|
||||
|
||||
func (adapter *rawAdapter) Extract(ctx context.Context, req contracts.ExtractionRequest) (contracts.ExtractionResult, error) {
|
||||
result, err := adapter.extractor.Extract(ctx, contracts.TypedExtractionRequest{
|
||||
Source: req.Source, Chunk: req.Chunk, AmbientContext: req.AmbientContext,
|
||||
SourceInput: req.SourceInput, SessionID: req.SessionID, References: req.References,
|
||||
LLMProfile: req.LLMProfile, Metadata: req.Metadata,
|
||||
})
|
||||
if err != nil {
|
||||
return contracts.ExtractionResult{}, err
|
||||
}
|
||||
content, err := adapter.codec.EncodeCandidate(result.Value)
|
||||
if err != nil {
|
||||
return contracts.ExtractionResult{}, extractorErrorf("encode canonical output: %w", err)
|
||||
}
|
||||
schema := adapter.codec.Schema()
|
||||
return contracts.ExtractionResult{
|
||||
Output: contracts.ExtractOutput{
|
||||
Schema: contracts.ResponseSchema{ID: schema.ID, Name: schema.Name, Version: schema.Version, JSONSchema: append([]byte(nil), schema.JSONSchema...)},
|
||||
Payload: contracts.RawPayload{Content: content, MediaType: adapter.codec.MediaType(), Metadata: map[string]any{"spell_cast_count": len(result.Value.SpellCasts)}},
|
||||
},
|
||||
Warnings: result.Warnings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateOptions(options map[string]any) error {
|
||||
_, err := DecodeOptions(options)
|
||||
return err
|
||||
|
||||
@@ -76,9 +76,6 @@ func TestRegisterMakesExtractorBuildable(t *testing.T) {
|
||||
t.Fatalf("Register() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
if _, err := registry.BuildLegacyRaw(Key); err == nil || !strings.Contains(err.Error(), "legacy raw") {
|
||||
t.Fatalf("BuildLegacyRaw() error = %v, want typed registration error", err)
|
||||
}
|
||||
if _, err := DecodeOptions(map[string]any{"unexpected": true}); err == nil || !strings.Contains(err.Error(), "unknown option") {
|
||||
t.Fatalf("DecodeOptions() error = %v, want unknown option error", err)
|
||||
}
|
||||
|
||||
@@ -15,10 +15,6 @@ const ReasonCode = "invalid_spell_shape"
|
||||
|
||||
type Options struct{}
|
||||
type Validator struct{}
|
||||
type legacyValidator struct{ codec decoder }
|
||||
type decoder interface {
|
||||
DecodeCandidate([]byte) (dnd.SpellList, error)
|
||||
}
|
||||
|
||||
var _ contracts.TypedValidator[dnd.SpellList] = (*Validator)(nil)
|
||||
|
||||
@@ -58,18 +54,6 @@ func Validate(value dnd.SpellList) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *legacyValidator) Name() string { return Key }
|
||||
func (v *legacyValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
func (v *legacyValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
value, err := v.codec.DecodeCandidate(req.Payload.Content)
|
||||
if err != nil {
|
||||
return rejection(err.Error()), nil
|
||||
}
|
||||
return New(Options{}).Validate(ctx, contracts.TypedValidationRequest[dnd.SpellList]{Value: value})
|
||||
}
|
||||
|
||||
func Spec() pipeline.ValidatorSpec {
|
||||
return pipeline.ValidatorSpec{Key: Key, ExecutionClass: contracts.ExecutionClassDeterministic}
|
||||
}
|
||||
@@ -82,17 +66,6 @@ func Register(registry *pipeline.ValidatorRegistry) error {
|
||||
return New(options), nil
|
||||
})
|
||||
}
|
||||
func RegisterLegacy(registry *pipeline.ValidatorRegistry, codec decoder) error {
|
||||
if codec == nil {
|
||||
return fmt.Errorf("spell shape validator codec must not be nil")
|
||||
}
|
||||
return registry.RegisterLegacyRawBuilderWithSpec(Spec(), validateOptions, func(request pipeline.BuildRequest) (contracts.LegacyRawValidator, error) {
|
||||
if _, err := DecodeOptions(request.Options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &legacyValidator{codec: codec}, nil
|
||||
})
|
||||
}
|
||||
func DecodeOptions(options map[string]any) (Options, error) {
|
||||
if err := pipeline.RejectUnknownOptions(options); err != nil {
|
||||
return Options{}, err
|
||||
|
||||
@@ -16,10 +16,6 @@ const ReasonCode = "invalid_source_refs"
|
||||
|
||||
type Options struct{}
|
||||
type Validator struct{}
|
||||
type legacyValidator struct{ codec decoder }
|
||||
type decoder interface {
|
||||
DecodeCandidate([]byte) (dnd.SpellList, error)
|
||||
}
|
||||
|
||||
var _ contracts.TypedValidator[dnd.SpellList] = (*Validator)(nil)
|
||||
|
||||
@@ -41,20 +37,6 @@ func (v *Validator) Validate(_ context.Context, req contracts.TypedValidationReq
|
||||
}
|
||||
return contracts.ValidationResult{Approved: true}, nil
|
||||
}
|
||||
func (v *legacyValidator) Name() string { return Key }
|
||||
func (v *legacyValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
func (v *legacyValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
value, err := v.codec.DecodeCandidate(req.Payload.Content)
|
||||
if err != nil {
|
||||
return rejection(err.Error()), nil
|
||||
}
|
||||
if err := spellshape.Validate(value); err != nil {
|
||||
return rejection(err.Error()), nil
|
||||
}
|
||||
return New(Options{}).Validate(ctx, contracts.TypedValidationRequest[dnd.SpellList]{Source: req.Source, Value: value})
|
||||
}
|
||||
func Spec() pipeline.ValidatorSpec {
|
||||
return pipeline.ValidatorSpec{Key: Key, ExecutionClass: contracts.ExecutionClassDeterministic}
|
||||
}
|
||||
@@ -67,17 +49,6 @@ func Register(registry *pipeline.ValidatorRegistry) error {
|
||||
return New(options), nil
|
||||
})
|
||||
}
|
||||
func RegisterLegacy(registry *pipeline.ValidatorRegistry, codec decoder) error {
|
||||
if codec == nil {
|
||||
return fmt.Errorf("spell source references validator codec must not be nil")
|
||||
}
|
||||
return registry.RegisterLegacyRawBuilderWithSpec(Spec(), validateOptions, func(request pipeline.BuildRequest) (contracts.LegacyRawValidator, error) {
|
||||
if _, err := DecodeOptions(request.Options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &legacyValidator{codec: codec}, nil
|
||||
})
|
||||
}
|
||||
func DecodeOptions(options map[string]any) (Options, error) {
|
||||
if err := pipeline.RejectUnknownOptions(options); err != nil {
|
||||
return Options{}, err
|
||||
|
||||
@@ -17,10 +17,6 @@ const WarningReasonCode = "spell_not_near_source"
|
||||
|
||||
type Options struct{}
|
||||
type Validator struct{}
|
||||
type legacyValidator struct{ codec decoder }
|
||||
type decoder interface {
|
||||
DecodeCandidate([]byte) (dnd.SpellList, error)
|
||||
}
|
||||
|
||||
var _ contracts.TypedValidator[dnd.SpellList] = (*Validator)(nil)
|
||||
|
||||
@@ -41,20 +37,6 @@ func (v *Validator) Validate(_ context.Context, req contracts.TypedValidationReq
|
||||
}
|
||||
return contracts.ValidationResult{Approved: true, Warnings: warnings}, nil
|
||||
}
|
||||
func (v *legacyValidator) Name() string { return Key }
|
||||
func (v *legacyValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
func (v *legacyValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
value, err := v.codec.DecodeCandidate(req.Payload.Content)
|
||||
if err != nil {
|
||||
return contracts.ValidationResult{Approved: true}, nil
|
||||
}
|
||||
if err := spellshape.Validate(value); err != nil {
|
||||
return contracts.ValidationResult{Approved: true}, nil
|
||||
}
|
||||
return New(Options{}).Validate(ctx, contracts.TypedValidationRequest[dnd.SpellList]{Source: req.Source, Value: value})
|
||||
}
|
||||
func spellAppearsInCitedText(doc *source.SourceDocument, spell dnd.SpellCast) bool {
|
||||
name := strings.ToLower(strings.TrimSpace(spell.Spell))
|
||||
if name == "" {
|
||||
@@ -100,17 +82,6 @@ func Register(registry *pipeline.ValidatorRegistry) error {
|
||||
return New(options), nil
|
||||
})
|
||||
}
|
||||
func RegisterLegacy(registry *pipeline.ValidatorRegistry, codec decoder) error {
|
||||
if codec == nil {
|
||||
return fmt.Errorf("spell source relatedness validator codec must not be nil")
|
||||
}
|
||||
return registry.RegisterLegacyRawBuilderWithSpec(Spec(), validateOptions, func(request pipeline.BuildRequest) (contracts.LegacyRawValidator, error) {
|
||||
if _, err := DecodeOptions(request.Options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &legacyValidator{codec: codec}, nil
|
||||
})
|
||||
}
|
||||
func DecodeOptions(options map[string]any) (Options, error) {
|
||||
if err := pipeline.RejectUnknownOptions(options); err != nil {
|
||||
return Options{}, err
|
||||
|
||||
Reference in New Issue
Block a user