源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
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
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
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package agentruntime
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
activityshared "github.com/tutti-os/tutti/packages/agent/daemon/activity/events"
|
||||
)
|
||||
|
||||
type RootTurnSettlement struct {
|
||||
RoomID string
|
||||
AgentSessionID string
|
||||
TurnID string
|
||||
Outcome string
|
||||
ErrorMessage string
|
||||
}
|
||||
|
||||
// ReconcileRootTurnSettlement applies daemon-owned durable root completion to
|
||||
// the runtime view. It does not report the event back to the daemon: the
|
||||
// caller invokes it only after the atomic durable transition committed.
|
||||
func (c *Controller) ReconcileRootTurnSettlement(settlement RootTurnSettlement) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
roomID := strings.TrimSpace(settlement.RoomID)
|
||||
agentSessionID := strings.TrimSpace(settlement.AgentSessionID)
|
||||
turnID := strings.TrimSpace(settlement.TurnID)
|
||||
if roomID == "" || agentSessionID == "" || turnID == "" {
|
||||
return
|
||||
}
|
||||
key := sessionKey(roomID, agentSessionID)
|
||||
c.mu.Lock()
|
||||
session, ok := c.sessions[key]
|
||||
if !ok {
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if active, exists := c.turns[key]; exists && strings.TrimSpace(active.turnID) == turnID {
|
||||
delete(c.turns, key)
|
||||
}
|
||||
outcome := strings.TrimSpace(settlement.Outcome)
|
||||
session.TurnLifecycle = &TurnLifecycle{Phase: "settled", Outcome: stringPointer(outcome)}
|
||||
session.SubmitAvailability = availableSubmitAvailability()
|
||||
switch outcome {
|
||||
case "failed":
|
||||
session.Status = SessionStatusFailed
|
||||
case "canceled", "interrupted":
|
||||
session.Status = SessionStatusCanceled
|
||||
default:
|
||||
session.Status = SessionStatusReady
|
||||
}
|
||||
session.UpdatedAtUnixMS = unixMS(now())
|
||||
c.sessions[key] = session
|
||||
c.mu.Unlock()
|
||||
|
||||
eventType := EventTurnCompleted
|
||||
switch outcome {
|
||||
case "failed":
|
||||
eventType = EventTurnFailed
|
||||
case "canceled", "interrupted":
|
||||
eventType = EventTurnCanceled
|
||||
}
|
||||
metadata := map[string]any{
|
||||
"daemonRootTurnSettlement": true,
|
||||
}
|
||||
if eventType == EventTurnFailed {
|
||||
// Carry the durable failure reason on the live event so the
|
||||
// visible-error projection can classify and render it; an empty
|
||||
// detail degrades to a generic card with no recoverable signal.
|
||||
if message := strings.TrimSpace(settlement.ErrorMessage); message != "" {
|
||||
metadata["error"] = message
|
||||
metadata["errorMessage"] = message
|
||||
}
|
||||
}
|
||||
event := newTurnActivityEvent(session, eventType, turnID, session.Status, "", "", metadata)
|
||||
if event.Type != "" {
|
||||
if event.Payload.TurnOutcome == "" {
|
||||
event.Payload.TurnOutcome = outcome
|
||||
}
|
||||
c.publish(session, []activityshared.Event{event})
|
||||
}
|
||||
}
|
||||
|
||||
func stringPointer(value string) *string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
return &value
|
||||
}
|
||||
Reference in New Issue
Block a user