Files
tutti/services/tuttid/api/daemon_agent_turn_projection.go
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

136 lines
5.4 KiB
Go

package api
import (
"strings"
agentactivitybiz "github.com/tutti-os/tutti/packages/agent/store-sqlite"
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
)
// generatedWorkspaceAgentTurn is the HTTP transport projection for the
// canonical stored turn. Keeping it in api prevents OpenAPI DTO changes from
// implicitly changing the business event protocol.
func generatedWorkspaceAgentTurn(turn agentactivitybiz.Turn) tuttigenerated.WorkspaceAgentTurn {
var capabilityRefs *[]tuttigenerated.WorkspaceAgentCapabilityReference
if len(turn.CapabilityRefs) > 0 {
projected := make([]tuttigenerated.WorkspaceAgentCapabilityReference, 0, len(turn.CapabilityRefs))
for _, reference := range turn.CapabilityRefs {
projected = append(projected, tuttigenerated.WorkspaceAgentCapabilityReference{
Capability: tuttigenerated.WorkspaceAgentCapabilityReferenceCapability(strings.TrimSpace(reference.Capability)),
Source: tuttigenerated.WorkspaceAgentCapabilityReferenceSource(strings.TrimSpace(reference.Source)),
})
}
capabilityRefs = &projected
}
var outcome *tuttigenerated.WorkspaceAgentTurnOutcome
if trimmed := strings.TrimSpace(turn.Outcome); trimmed != "" {
value := tuttigenerated.WorkspaceAgentTurnOutcome(trimmed)
outcome = &value
}
var turnError *tuttigenerated.WorkspaceAgentTurnError
if message := strings.TrimSpace(turn.ErrorMessage); message != "" &&
(turn.Outcome == agentactivitybiz.TurnOutcomeFailed || turn.Outcome == agentactivitybiz.TurnOutcomeInterrupted) {
turnError = &tuttigenerated.WorkspaceAgentTurnError{
Message: message,
Code: optionalStringPointer(turn.ErrorCode),
}
}
var completedCommand *tuttigenerated.WorkspaceAgentCompletedCommand
if kind := strings.TrimSpace(turn.CompletedCommandKind); kind != "" {
completedCommand = &tuttigenerated.WorkspaceAgentCompletedCommand{
Kind: tuttigenerated.WorkspaceAgentCompletedCommandKind(kind),
Status: tuttigenerated.WorkspaceAgentCompletedCommandStatus(strings.TrimSpace(turn.CompletedCommandStatus)),
}
}
var fileChanges *map[string]any
if len(turn.FileChanges) > 0 {
cloned := cloneAgentProjectionPayload(turn.FileChanges)
fileChanges = &cloned
}
var settledAt *int64
if turn.SettledAtUnixMS > 0 {
value := turn.SettledAtUnixMS
settledAt = &value
}
var sourceGoalOperationID *string
if value := strings.TrimSpace(turn.SourceGoalOperationID); value != "" {
sourceGoalOperationID = &value
}
var sourceGoalRevision *int64
if turn.SourceGoalRevision > 0 {
value := turn.SourceGoalRevision
sourceGoalRevision = &value
}
var sourceGoalRepairEpoch *int64
if turn.SourceGoalRepairEpoch > 0 {
value := turn.SourceGoalRepairEpoch
sourceGoalRepairEpoch = &value
}
return tuttigenerated.WorkspaceAgentTurn{
AgentSessionId: strings.TrimSpace(turn.AgentSessionID),
ProviderForkBindingAvailable: turn.ProviderForkBindingAvailable,
ProviderForkBindingState: providerForkBindingState(turn),
CapabilityRefs: capabilityRefs,
CompletedCommand: completedCommand,
Error: turnError,
FileChanges: fileChanges,
Origin: tuttigenerated.WorkspaceAgentTurnOrigin(strings.TrimSpace(turn.Origin)),
Outcome: outcome,
Phase: tuttigenerated.WorkspaceAgentTurnPhase(turn.Phase),
SettledAtUnixMs: settledAt,
SourceGoalOperationId: sourceGoalOperationID,
SourceGoalRepairEpoch: sourceGoalRepairEpoch,
SourceGoalRevision: sourceGoalRevision,
StartedAtUnixMs: turn.StartedAtUnixMS,
TurnId: strings.TrimSpace(turn.TurnID),
UpdatedAtUnixMs: turn.UpdatedAtUnixMS,
}
}
func providerForkBindingState(
turn agentactivitybiz.Turn,
) tuttigenerated.WorkspaceAgentTurnProviderForkBindingState {
if turn.ProviderForkBindingAvailable {
return tuttigenerated.WorkspaceAgentTurnProviderForkBindingStateBound
}
if turn.Phase == agentactivitybiz.TurnPhaseSettled {
return tuttigenerated.WorkspaceAgentTurnProviderForkBindingStateRecoveryRequired
}
return tuttigenerated.WorkspaceAgentTurnProviderForkBindingStateUnavailable
}
func generatedWorkspaceAgentInteraction(interaction agentactivitybiz.Interaction) tuttigenerated.WorkspaceAgentInteraction {
return tuttigenerated.WorkspaceAgentInteraction{
AgentSessionId: strings.TrimSpace(interaction.AgentSessionID),
CreatedAtUnixMs: interaction.CreatedAtUnixMS,
Input: optionalAgentProjectionPayload(interaction.Input),
Kind: tuttigenerated.WorkspaceAgentInteractionKind(interaction.Kind),
Metadata: optionalAgentProjectionPayload(interaction.Metadata),
Output: optionalAgentProjectionPayload(interaction.Output),
RequestId: strings.TrimSpace(interaction.RequestID),
Status: tuttigenerated.WorkspaceAgentInteractionStatus(interaction.Status),
ToolName: optionalStringPointer(interaction.ToolName),
TurnId: strings.TrimSpace(interaction.TurnID),
UpdatedAtUnixMs: interaction.UpdatedAtUnixMS,
}
}
func optionalAgentProjectionPayload(payload map[string]any) *map[string]any {
if len(payload) == 0 {
return nil
}
cloned := cloneAgentProjectionPayload(payload)
return &cloned
}
func cloneAgentProjectionPayload(payload map[string]any) map[string]any {
if payload == nil {
return nil
}
cloned := make(map[string]any, len(payload))
for key, value := range payload {
cloned[key] = value
}
return cloned
}