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
88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package agentruntime
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
activityshared "github.com/tutti-os/tutti/packages/agent/daemon/activity/events"
|
|
)
|
|
|
|
// ProviderTurnAcceptanceInput is an authoritative history observation. This
|
|
// path only repairs the durable projection; it never dispatches provider work.
|
|
type ProviderTurnAcceptanceInput struct {
|
|
RoomID string
|
|
AgentSessionID string
|
|
Provider string
|
|
RootTurnID string
|
|
ExpectedProviderSessionID string
|
|
ExpectedProviderTurnID string
|
|
// ClientUserMessageID is opaque provider correlation evidence and must be
|
|
// distinct from the canonical RootTurnID.
|
|
ClientUserMessageID string
|
|
}
|
|
|
|
func (c *Controller) ReconcileProviderTurnAcceptance(
|
|
ctx context.Context,
|
|
input ProviderTurnAcceptanceInput,
|
|
) error {
|
|
input.RoomID = strings.TrimSpace(input.RoomID)
|
|
input.AgentSessionID = strings.TrimSpace(input.AgentSessionID)
|
|
input.Provider = strings.TrimSpace(input.Provider)
|
|
input.RootTurnID = strings.TrimSpace(input.RootTurnID)
|
|
input.ExpectedProviderSessionID = strings.TrimSpace(input.ExpectedProviderSessionID)
|
|
input.ExpectedProviderTurnID = strings.TrimSpace(input.ExpectedProviderTurnID)
|
|
input.ClientUserMessageID = strings.TrimSpace(input.ClientUserMessageID)
|
|
if c == nil || input.RoomID == "" || input.AgentSessionID == "" ||
|
|
input.RootTurnID == "" || input.ExpectedProviderSessionID == "" ||
|
|
input.ExpectedProviderTurnID == "" ||
|
|
input.ClientUserMessageID == "" ||
|
|
input.ClientUserMessageID == input.RootTurnID {
|
|
return errors.New("valid provider turn acceptance evidence is required")
|
|
}
|
|
session, found := c.get(input.RoomID, input.AgentSessionID)
|
|
if !found {
|
|
return ErrSessionNotFound
|
|
}
|
|
if strings.TrimSpace(session.ProviderSessionID) != input.ExpectedProviderSessionID ||
|
|
(input.Provider != "" && strings.TrimSpace(session.Provider) != input.Provider) {
|
|
return errors.New("provider turn acceptance session identity changed")
|
|
}
|
|
eventContext, ok := activityEventContext(
|
|
session,
|
|
"root-provider-turn-started:"+input.ExpectedProviderTurnID,
|
|
input.RootTurnID,
|
|
)
|
|
if !ok {
|
|
return ErrSessionDisconnected
|
|
}
|
|
accepted := activityshared.NewRootProviderTurnStarted(
|
|
eventContext,
|
|
input.RootTurnID,
|
|
input.ExpectedProviderTurnID,
|
|
)
|
|
accepted.Payload.ProviderTurnBindingJSON = c.providerTurnBindingJSON(
|
|
ctx,
|
|
session,
|
|
ProviderTurnBindingWriteInput{
|
|
Kind: ProviderTurnBindingWriteRecovered,
|
|
ProviderTurnID: input.ExpectedProviderTurnID,
|
|
},
|
|
)
|
|
accepted.Payload.Metadata = map[string]any{
|
|
"acceptanceSource": string(AcceptanceSourceHistoryRead),
|
|
}
|
|
reported, err := c.reportProviderAcceptanceDurable(
|
|
ctx,
|
|
session,
|
|
[]activityshared.Event{accepted},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !reported {
|
|
return errors.New("durable provider acceptance reporter is unavailable")
|
|
}
|
|
return nil
|
|
}
|