Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
157 lines
7.3 KiB
Go
157 lines
7.3 KiB
Go
package agenthost
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
storesqlite "github.com/tutti-os/tutti/packages/agent/store-sqlite"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidArgument = errors.New("invalid agent session request")
|
|
ErrRailPlacementConflict = errors.New("agent session rail placement conflicts with canonical state")
|
|
ErrSessionNotFound = errors.New("workspace agent session not found")
|
|
ErrTurnNotFound = errors.New("workspace agent turn not found")
|
|
ErrProviderSessionNotEstablished = errors.New("provider session was never established")
|
|
ErrSubmitDeliveryUnknown = errors.New("agent submit delivery is still being confirmed")
|
|
ErrActiveTurnTargetRequired = errors.New("active-turn guidance requires an exact target turn")
|
|
ErrActiveTurnTargetMismatch = errors.New("active-turn guidance target is no longer active")
|
|
ErrSessionTitleTooLong = errors.New("agent session title is too long")
|
|
ErrRuntimeSessionDisconnected = errors.New("agent runtime session is disconnected")
|
|
// ErrRuntimeCancelDeliveryUnconfirmed means the runtime received an exact
|
|
// cancel request but could not confirm that the requested provider turn was
|
|
// the one it stopped. Host keeps the durable cancel operation retryable and
|
|
// waits for canonical terminal evidence instead of fabricating a terminal.
|
|
ErrRuntimeCancelDeliveryUnconfirmed = errors.New("agent runtime cancellation delivery is unconfirmed")
|
|
ErrRuntimeProviderStateLost = errors.New("agent provider state was lost")
|
|
ErrRuntimeSessionActive = errors.New("agent runtime session has an active turn")
|
|
ErrRuntimeSessionReprepareUnavailable = errors.New("agent runtime session reprepare is unavailable")
|
|
ErrRuntimeContextConflict = errors.New("agent runtime context changed before rebind commit")
|
|
ErrRuntimeSessionPublishUnavailable = errors.New("agent runtime session initialization publication is unavailable")
|
|
ErrRuntimeRailPlacementUnavailable = errors.New("agent runtime rail placement resolution is unavailable")
|
|
ErrWorkspaceDisconnectUnavailable = errors.New("agent workspace runtime disconnect is unavailable")
|
|
ErrInteractionNotFound = errors.New("agent interaction was not found")
|
|
ErrRuntimeOperationInProgress = errors.New("agent runtime operation is already in progress")
|
|
ErrRuntimeOperationFailed = errors.New("agent runtime operation failed")
|
|
ErrRuntimeOperationIdentityMismatch = errors.New("agent runtime operation identity is inconsistent")
|
|
ErrGoalConsumerUnavailable = errors.New("agent goal reconcile consumer is unavailable")
|
|
ErrGoalGenerationFenceUnavailable = errors.New("agent goal generation fence consumer is unavailable")
|
|
ErrRuntimeSessionLivenessUnavailable = errors.New("agent runtime session liveness is unavailable")
|
|
ErrSessionForkUnsupported = errors.New("agent session through-turn fork is unsupported")
|
|
ErrSessionForkInProgress = errors.New("agent session fork is in progress")
|
|
ErrSessionForkDeliveryUnknown = errors.New("agent session fork provider delivery is unknown")
|
|
ErrSessionForkFailed = errors.New("agent session fork failed")
|
|
ErrEditRetryNotEligible = errors.New("only the latest completed user turn can be edited and retried")
|
|
ErrEditRetryHistoryConflict = errors.New("agent effective history revision changed")
|
|
ErrRuntimeHistoryUnsupported = errors.New("agent provider does not support effective history mutation")
|
|
ErrEditRetryInProgress = errors.New("agent history edit is still being confirmed")
|
|
ErrEditRetryResendPending = errors.New("agent history was rolled back but the edited turn still needs to be resent")
|
|
ErrEditRetryRecoveryRequired = errors.New("agent provider history diverged and requires explicit recovery")
|
|
ErrSideConversationUnsupported = errors.New("agent side conversation is unsupported")
|
|
ErrSideConversationInProgress = errors.New("agent side conversation is being opened")
|
|
ErrSideConversationConflict = errors.New("agent side conversation identity conflicts with an existing side")
|
|
ErrSideConversationExpired = errors.New("agent side conversation has expired")
|
|
ErrInteractiveRequestNotLive = errors.New("agent interactive request is no longer live")
|
|
ErrInteractiveAlreadyAnswered = errors.New("agent interactive request has already been answered")
|
|
ErrInteractiveResponseInvalid = errors.New("agent interactive response is invalid")
|
|
ErrDeletedSessionNotFound = storesqlite.ErrDeletedSessionNotFound
|
|
ErrDeletedSessionNotRestorable = storesqlite.ErrDeletedSessionNotRestorable
|
|
)
|
|
|
|
// ProviderError preserves a provider-owned failure across the runtime adapter
|
|
// and Host boundary. Consumers may use errors.As to distinguish an explicit
|
|
// downstream failure from preparation, canonical-store, timeout, and other
|
|
// Host-local errors without parsing error text or depending on provider codes.
|
|
//
|
|
// Code and diagnostic text remain local observations. They are not a stable
|
|
// cross-service taxonomy and must not be persisted as coordination metadata.
|
|
type ProviderError struct {
|
|
Code string
|
|
Message string
|
|
DebugMessage string
|
|
Cause error
|
|
}
|
|
|
|
const ProviderErrorCodeStartTimeout = "provider_start_timeout"
|
|
|
|
// NewProviderError converts an adapter's structured provider observation into
|
|
// the Host contract. Cancellation and deadline errors remain unclassified
|
|
// because their delivery result is unknown and consumers must keep them
|
|
// recoverable.
|
|
func NewProviderError(code, message, debugMessage string, cause error) error {
|
|
if cause == nil {
|
|
return nil
|
|
}
|
|
if errors.Is(cause, context.Canceled) || errors.Is(cause, context.DeadlineExceeded) {
|
|
return cause
|
|
}
|
|
return &ProviderError{
|
|
Code: code,
|
|
Message: message,
|
|
DebugMessage: debugMessage,
|
|
Cause: cause,
|
|
}
|
|
}
|
|
|
|
// NewProviderStartTimeoutError preserves the narrow runtime verdict that a
|
|
// provider adapter timed out while starting, before a runtime Session was
|
|
// established. Unlike an arbitrary deadline, this verdict is safe to expose as
|
|
// a ProviderError because the runtime owner has already identified the failed
|
|
// lifecycle stage.
|
|
func NewProviderStartTimeoutError(message, debugMessage string, cause error) error {
|
|
if cause == nil {
|
|
return nil
|
|
}
|
|
return &ProviderError{
|
|
Code: ProviderErrorCodeStartTimeout,
|
|
Message: message,
|
|
DebugMessage: debugMessage,
|
|
Cause: cause,
|
|
}
|
|
}
|
|
|
|
func (e *ProviderError) Error() string {
|
|
if e == nil {
|
|
return ""
|
|
}
|
|
if e.Message != "" {
|
|
return e.Message
|
|
}
|
|
if e.Code != "" {
|
|
return e.Code
|
|
}
|
|
if e.Cause != nil {
|
|
return e.Cause.Error()
|
|
}
|
|
return "agent provider error"
|
|
}
|
|
|
|
func (e *ProviderError) Unwrap() error {
|
|
if e == nil {
|
|
return nil
|
|
}
|
|
return e.Cause
|
|
}
|
|
|
|
func terminalFailureCode(err error) string {
|
|
var providerErr *ProviderError
|
|
if errors.As(err, &providerErr) && providerErr != nil {
|
|
return strings.TrimSpace(providerErr.Code)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func guidanceTargetFailureCode(err error) string {
|
|
switch {
|
|
case errors.Is(err, ErrActiveTurnTargetRequired):
|
|
return "active_turn_target_required"
|
|
case errors.Is(err, ErrActiveTurnTargetMismatch):
|
|
return "active_turn_target_mismatch"
|
|
}
|
|
if code := terminalFailureCode(err); code != "" {
|
|
return code
|
|
}
|
|
return "guidance_target"
|
|
}
|