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

129 lines
4.2 KiB
Go

package api
import (
"fmt"
"strings"
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
agentservice "github.com/tutti-os/tutti/services/tuttid/service/agent"
)
const maxWorkspaceAgentJSONSafeInteger = uint64(1<<53 - 1)
func generatedAgentSessionMessages(messages []agentservice.SessionMessage) ([]tuttigenerated.WorkspaceAgentSessionMessage, error) {
result := make([]tuttigenerated.WorkspaceAgentSessionMessage, 0, len(messages))
for _, message := range messages {
// Protocol v2 message ownership: a non-empty turnId attaches the
// message to that turn; an empty stored turn id is projected as null
// (session-level message) instead of being rejected.
var turnID *string
if trimmed := strings.TrimSpace(message.TurnID); trimmed != "" {
turnID = &trimmed
}
sequence, err := generatedWorkspaceAgentSafeInteger("message sequence", message.ID)
if err != nil {
return nil, fmt.Errorf("project workspace agent message %q: %w", message.MessageID, err)
}
version, err := generatedWorkspaceAgentSafeInteger("message version", message.Version)
if err != nil {
return nil, fmt.Errorf("project workspace agent message %q: %w", message.MessageID, err)
}
generated := tuttigenerated.WorkspaceAgentSessionMessage{
AgentSessionId: strings.TrimSpace(message.AgentSessionID),
CompletedAtUnixMs: int64Pointer(message.CompletedAtUnixMS),
CreatedAtUnixMs: int64Pointer(message.CreatedAtUnixMS),
Kind: strings.TrimSpace(message.Kind),
MessageId: strings.TrimSpace(message.MessageID),
OccurredAtUnixMs: normalizedGeneratedMessageOccurredAtUnixMS(message, version),
Payload: clonePayloadPointer(message.Payload),
Role: strings.TrimSpace(message.Role),
Sequence: sequence,
StartedAtUnixMs: int64Pointer(message.StartedAtUnixMS),
Status: stringPointer(strings.TrimSpace(message.Status)),
TurnId: turnID,
UpdatedAtUnixMs: int64Pointer(message.UpdatedAtUnixMS),
Version: version,
}
if message.Semantics != nil {
userVisible := message.Semantics.UserVisibleAssistantResponse
turnSettling := message.Semantics.TurnSettling
generated.Semantics = &tuttigenerated.AgentActivityMessageSemantics{
UserVisibleAssistantResponse: &userVisible,
TurnSettling: &turnSettling,
NoticeCommand: stringPointerIfNotBlank(message.Semantics.NoticeCommand),
NoticeCommandStatus: stringPointerIfNotBlank(message.Semantics.NoticeCommandStatus),
}
}
result = append(result, generated)
}
return result, nil
}
func generatedWorkspaceAgentSafeInteger(field string, value uint64) (int64, error) {
if value > maxWorkspaceAgentJSONSafeInteger {
return 0, fmt.Errorf(
"%s %d exceeds JavaScript safe integer maximum %d",
field,
value,
maxWorkspaceAgentJSONSafeInteger,
)
}
return int64(value), nil
}
func workspaceAgentMessageCursorFromRequest(value int64) (uint64, error) {
if value < 0 || uint64(value) > maxWorkspaceAgentJSONSafeInteger {
return 0, agentservice.ErrInvalidArgument
}
return uint64(value), nil
}
func agentSessionMessageVersionRange(messages []agentservice.SessionMessage) (uint64, uint64) {
var first uint64
var last uint64
for _, message := range messages {
if first == 0 || message.Version < first {
first = message.Version
}
if message.Version > last {
last = message.Version
}
}
return first, last
}
func generatedAgentSessionMessageVersionRange(messages []tuttigenerated.WorkspaceAgentSessionMessage) (int64, int64) {
var first int64
var last int64
for _, message := range messages {
if first == 0 || message.Version < first {
first = message.Version
}
if message.Version > last {
last = message.Version
}
}
return first, last
}
func normalizedGeneratedMessageOccurredAtUnixMS(message agentservice.SessionMessage, version int64) int64 {
return firstPositiveInt64(
message.OccurredAtUnixMS,
message.StartedAtUnixMS,
message.CompletedAtUnixMS,
message.CreatedAtUnixMS,
message.UpdatedAtUnixMS,
version,
1,
)
}
func firstPositiveInt64(values ...int64) int64 {
for _, value := range values {
if value > 0 {
return value
}
}
return 0
}