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
136 lines
5.4 KiB
Go
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
|
|
}
|