Add sequential conversation coordinator
This commit is contained in:
66
internal/usecase/coordinate.go
Normal file
66
internal/usecase/coordinate.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.maximumdirect.net/promptkit/internal/domain"
|
||||
)
|
||||
|
||||
// ConversationTurn is one delivery to a coordinator callback.
|
||||
type ConversationTurn[R any] struct {
|
||||
Exchange *domain.Exchange
|
||||
Result *R
|
||||
RemainingTurns int
|
||||
}
|
||||
|
||||
// CoordinationOutcome describes a normal coordinator termination.
|
||||
type CoordinationOutcome string
|
||||
|
||||
const (
|
||||
CoordinationStopped CoordinationOutcome = "stopped"
|
||||
CoordinationExhausted CoordinationOutcome = "exhausted"
|
||||
)
|
||||
|
||||
// CoordinationResult holds a normal outcome or a completed undelivered result.
|
||||
type CoordinationResult[R any] struct {
|
||||
Outcome CoordinationOutcome
|
||||
Undelivered *R
|
||||
}
|
||||
|
||||
// Coordinate advances one branch using the supplied callback and ordinary run.
|
||||
func Coordinate[Q, R any](ctx context.Context, start *domain.Exchange, turns int,
|
||||
next func(context.Context, ConversationTurn[R]) (*Q, error),
|
||||
run func(context.Context, *domain.Exchange, *Q) (*R, *domain.Exchange, error),
|
||||
) (CoordinationResult[R], error) {
|
||||
current := start
|
||||
var pending *R
|
||||
for {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return CoordinationResult[R]{Undelivered: pending}, err
|
||||
}
|
||||
request, err := next(ctx, ConversationTurn[R]{Exchange: current, Result: pending, RemainingTurns: turns})
|
||||
pending = nil
|
||||
if contextErr := ctx.Err(); contextErr != nil {
|
||||
return CoordinationResult[R]{}, contextErr
|
||||
}
|
||||
if err != nil {
|
||||
return CoordinationResult[R]{}, err
|
||||
}
|
||||
if request == nil {
|
||||
return CoordinationResult[R]{Outcome: CoordinationStopped}, nil
|
||||
}
|
||||
if turns == 0 {
|
||||
return CoordinationResult[R]{Outcome: CoordinationExhausted}, nil
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
return CoordinationResult[R]{}, err
|
||||
}
|
||||
turns--
|
||||
var nextExchange *domain.Exchange
|
||||
pending, nextExchange, err = run(ctx, current, request)
|
||||
if err != nil {
|
||||
return CoordinationResult[R]{}, err
|
||||
}
|
||||
current = nextExchange
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user