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

105 lines
2.9 KiB
Go

package agentruntime
import (
"context"
"errors"
"strings"
)
var ErrEffectiveHistoryUnsupported = errors.New("agent provider does not support effective history mutation")
type EffectiveHistoryInput struct {
RoomID string
AgentSessionID string
Provider string
}
func (c *Controller) SupportsEffectiveHistory(
_ context.Context,
input EffectiveHistoryInput,
) (bool, error) {
if c == nil {
return false, nil
}
provider := strings.TrimSpace(input.Provider)
if provider == "" {
if session, found := c.get(
strings.TrimSpace(input.RoomID),
strings.TrimSpace(input.AgentSessionID),
); found {
provider = strings.TrimSpace(session.Provider)
}
}
if provider == "" {
return false, nil
}
_, supported := c.adapter(provider).(EffectiveHistoryAdapter)
return supported, nil
}
func (c *Controller) ReadEffectiveHistory(
ctx context.Context,
input EffectiveHistoryInput,
) (EffectiveHistorySnapshot, error) {
session, adapter, release, err := c.prepareEffectiveHistoryCommand(ctx, input)
if err != nil {
return EffectiveHistorySnapshot{}, err
}
defer release()
return adapter.ReadEffectiveHistory(ctx, session)
}
func (c *Controller) RollbackLatestTurn(
ctx context.Context,
input EffectiveHistoryInput,
) (HistoryMutationResult, error) {
session, adapter, release, err := c.prepareEffectiveHistoryCommand(ctx, input)
if err != nil {
return HistoryMutationResult{
Disposition: DispatchDispositionNotDispatched,
}, err
}
defer release()
return adapter.RollbackLatestTurn(ctx, session)
}
func (c *Controller) prepareEffectiveHistoryCommand(
ctx context.Context,
input EffectiveHistoryInput,
) (Session, EffectiveHistoryAdapter, func(), error) {
input.RoomID = strings.TrimSpace(input.RoomID)
input.AgentSessionID = strings.TrimSpace(input.AgentSessionID)
if c == nil || input.RoomID == "" || input.AgentSessionID == "" {
return Session{}, nil, nil, ErrSessionNotFound
}
release, err := c.acquireLifecycleLockContext(ctx, input.RoomID, input.AgentSessionID)
if err != nil {
return Session{}, nil, nil, err
}
fail := func(err error) (Session, EffectiveHistoryAdapter, func(), error) {
release()
return Session{}, nil, nil, err
}
if c.HasActiveTurn(input.RoomID, input.AgentSessionID) {
return fail(ErrSessionActiveTurn)
}
session, rawAdapter, err := c.sessionAndAdapter(input.RoomID, input.AgentSessionID)
if err != nil {
return fail(err)
}
if input.Provider != "" && strings.TrimSpace(session.Provider) != strings.TrimSpace(input.Provider) {
return fail(errors.New("provider changed while preparing effective history command"))
}
adapter, ok := rawAdapter.(EffectiveHistoryAdapter)
if !ok {
return fail(ErrEffectiveHistoryUnsupported)
}
if err := c.ensureLiveAdapterSession(ctx, session, rawAdapter); err != nil {
return fail(err)
}
if refreshed, found := c.get(input.RoomID, input.AgentSessionID); found {
session = refreshed
}
return session, adapter, release, nil
}