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
129 lines
4.2 KiB
Go
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
|
|
}
|