iop/apps/edge/internal/openai/hot_path_review.go

96 lines
3.1 KiB
Go

package openai
import (
"context"
"fmt"
)
func (s *Server) advanceHotPathReview(
ctx context.Context,
requestID string,
phase hotPathLightPhase,
output normalizedStageOutput,
visible normalizedStageOutput,
) (normalizedStageOutput, bool, error) {
kind, cleanup, err := classifyHotPathReviewOutput(requestID, phase, output)
if err != nil {
return normalizedStageOutput{}, false, err
}
if cleanup {
intent := hotPathTerminalIntent{Output: output.StageResponseOverlay(visible)}
mapped, err := s.lightFlows.beginCleanup(ctx, requestID, s.edgeIDValue(), intent, s.requestCoordinator)
if err != nil {
return normalizedStageOutput{}, false, err
}
return mapped, true, nil
}
mapped, err := s.lightFlows.issueTools(requestID, s.edgeIDValue(), output, visible, kind, s.requestCoordinator)
if err != nil {
return normalizedStageOutput{}, false, err
}
return mapped, true, nil
}
func classifyHotPathReviewOutput(requestID string, phase hotPathLightPhase, output normalizedStageOutput) (hotPathPendingKind, bool, error) {
paths := newReservedPaths(requestID)
switch phase {
case hotPathPhaseReviewActive:
if len(output.ToolCalls) == 0 {
return "", false, fmt.Errorf("review stage completed before writing the issued review artifact")
}
writeCount := 0
reservedCount := 0
for _, call := range output.ToolCalls {
observed := reservedPathsFromToolCall(call)
if len(observed) == 0 {
continue
}
reservedCount++
if len(observed) == 1 && cleanRelativePath(observed[0]) == cleanRelativePath(paths.ReviewPath) {
writeCount++
}
}
if writeCount == 0 && reservedCount == 0 {
return hotPathPendingReviewInspection, false, nil
}
if writeCount == 1 && reservedCount == 1 && len(output.ToolCalls) == 1 {
return hotPathPendingReviewWrite, false, nil
}
return "", false, fmt.Errorf("review write must be one exact review-path tool call")
case hotPathPhaseReviewAwaitRead:
if len(output.ToolCalls) != 1 {
return "", false, fmt.Errorf("review write result must be followed by one exact review read")
}
observed := reservedPathsFromToolCall(output.ToolCalls[0])
if len(observed) != 1 || cleanRelativePath(observed[0]) != cleanRelativePath(paths.ReviewPath) {
return "", false, fmt.Errorf("review write result must be followed by the issued review read")
}
return hotPathPendingReviewRead, false, nil
case hotPathPhaseReviewResolution:
if len(output.ToolCalls) == 0 {
return "", true, nil
}
for _, call := range output.ToolCalls {
if len(reservedPathsFromToolCall(call)) > 0 {
return "", false, fmt.Errorf("review resolution cannot start another reserved review cycle")
}
}
return hotPathPendingReviewRepair, false, nil
case hotPathPhaseReviewRepair:
if len(output.ToolCalls) == 0 {
return "", true, nil
}
for _, call := range output.ToolCalls {
if len(reservedPathsFromToolCall(call)) > 0 {
return "", false, fmt.Errorf("repair cannot start a second review cycle")
}
}
return hotPathPendingReviewRepair, false, nil
default:
return "", false, fmt.Errorf("phase %q is not a review phase", phase)
}
}