Dev starts on pi-native and keeps pi-agent available for a failed turn. Latency tuning stays deferred.
47 lines
1.0 KiB
Go
47 lines
1.0 KiB
Go
package agent
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
)
|
|
|
|
// fallbackBackend runs pi-native first. A failed turn is retried on the container pi-agent.
|
|
type fallbackBackend struct {
|
|
primary Backend
|
|
fallback Backend
|
|
}
|
|
|
|
func (f *fallbackBackend) Name() string {
|
|
if f.primary == nil {
|
|
return "pi-native"
|
|
}
|
|
return f.primary.Name()
|
|
}
|
|
|
|
func (f *fallbackBackend) Execute(ctx context.Context, req Request) (*Result, error) {
|
|
res, err := f.primary.Execute(ctx, req)
|
|
if ctx.Err() != nil || succeeded(res, err) || f.fallback == nil {
|
|
return res, err
|
|
}
|
|
fb, fbErr := f.fallback.Execute(ctx, req)
|
|
if !succeeded(fb, fbErr) {
|
|
return res, err
|
|
}
|
|
note := "pi-native failed; served by pi-agent"
|
|
if res != nil && strings.TrimSpace(res.ErrorReason) != "" {
|
|
note += ": " + strings.TrimSpace(res.ErrorReason)
|
|
} else if err != nil {
|
|
note += ": " + err.Error()
|
|
}
|
|
if strings.TrimSpace(fb.Logs) == "" {
|
|
fb.Logs = note
|
|
} else {
|
|
fb.Logs = note + "\n" + fb.Logs
|
|
}
|
|
return fb, nil
|
|
}
|
|
|
|
func succeeded(res *Result, err error) bool {
|
|
return err == nil && res != nil && res.Success
|
|
}
|