Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

72 lines
3.1 KiB
Go

package agentruntime
import (
"strings"
activityshared "github.com/tutti-os/tutti/packages/agent/daemon/activity/events"
)
// stampAdapterTurnLifecycleEvents stamps an adapter-origin TurnLifecycle
// snapshot onto every turn.* event in the batch (ADR 0008). Every such event
// is emitted by the owning adapter at one of its own turn transition points,
// so the snapshot is that transition serialized exactly once; events that
// already carry a snapshot (controller-stamped submit events) are left
// untouched. nextSeq must return a per-session monotonic sequence number.
func stampAdapterTurnLifecycleEvents(events []activityshared.Event, nextSeq func() uint64) []activityshared.Event {
for index := range events {
snapshot, ok := adapterSnapshotForTurnEvent(events[index])
if !ok {
continue
}
if _, stamped := activityshared.TurnLifecycleSnapshotFromEvent(events[index]); stamped {
continue
}
snapshot.Origin = activityshared.TurnLifecycleOriginAdapter
snapshot.Seq = nextSeq()
activityshared.StampTurnLifecycleSnapshot(&events[index], snapshot)
}
return events
}
// adapterSnapshotForTurnEvent translates the turn transition an event states
// into the full lifecycle snapshot for that moment.
func adapterSnapshotForTurnEvent(event activityshared.Event) (activityshared.TurnLifecycleSnapshot, bool) {
turnID := strings.TrimSpace(event.Payload.TurnID)
switch event.Type {
case activityshared.EventTurnStarted, activityshared.EventRootProviderTurnStarted:
return activityshared.TurnLifecycleSnapshot{
ActiveTurnID: turnID,
Phase: string(activityshared.TurnPhaseRunning),
}, true
case activityshared.EventTurnUpdated:
switch strings.TrimSpace(event.Payload.TurnPhase) {
case string(activityshared.TurnPhaseSubmitted):
return activityshared.TurnLifecycleSnapshot{ActiveTurnID: turnID, Phase: string(activityshared.TurnPhaseSubmitted)}, true
case string(activityshared.TurnPhaseWorking), string(activityshared.TurnPhaseRunning), "streaming":
return activityshared.TurnLifecycleSnapshot{ActiveTurnID: turnID, Phase: string(activityshared.TurnPhaseRunning)}, true
case string(activityshared.TurnPhaseWaitingApproval), string(activityshared.TurnPhaseWaiting):
return activityshared.TurnLifecycleSnapshot{ActiveTurnID: turnID, Phase: string(activityshared.TurnPhaseWaitingApproval)}, true
case string(activityshared.TurnPhaseWaitingInput):
return activityshared.TurnLifecycleSnapshot{ActiveTurnID: turnID, Phase: string(activityshared.TurnPhaseWaitingInput)}, true
default:
return activityshared.TurnLifecycleSnapshot{}, false
}
case activityshared.EventTurnCompleted:
outcome := strings.TrimSpace(event.Payload.TurnOutcome)
if outcome == "" {
outcome = string(activityshared.TurnOutcomeCompleted)
}
return activityshared.TurnLifecycleSnapshot{
Phase: string(activityshared.TurnPhaseSettled),
Outcome: outcome,
}, true
case activityshared.EventTurnFailed:
return activityshared.TurnLifecycleSnapshot{
Phase: string(activityshared.TurnPhaseSettled),
Outcome: string(activityshared.TurnOutcomeFailed),
}, true
default:
return activityshared.TurnLifecycleSnapshot{}, false
}
}