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

143 lines
4.8 KiB
Go

package agenthost
import (
"strings"
storesqlite "github.com/tutti-os/tutti/packages/agent/store-sqlite"
)
func normalizeOptionalPromptContent(content []PromptContentBlock) ([]PromptContentBlock, string, error) {
if len(content) == 0 {
return nil, "", nil
}
return normalizePromptContent(content)
}
func createPreparationInput(workspaceID string, input CreateSessionInput) RuntimePreparationInput {
return RuntimePreparationInput{
WorkspaceID: workspaceID, AgentSessionID: input.AgentSessionID, AgentTargetID: input.AgentTargetID,
Provider: input.Provider, Cwd: value(input.Cwd), Title: value(input.Title), PermissionModeID: value(input.PermissionModeID),
PlanMode: valueBool(input.PlanMode), BrowserUse: valueBoolDefault(input.BrowserUse, true), ComputerUse: valueBoolDefault(input.ComputerUse, true), CodexSaverMode: valueBool(input.CodexSaverMode), RTKSaverMode: valueBool(input.RTKSaverMode),
ProviderTargetRef: cloneMap(input.ProviderTargetRef), Model: value(input.Model), ReasoningEffort: value(input.ReasoningEffort),
ConversationDetailMode: input.ConversationDetailMode, Metadata: cloneMap(input.Metadata), RuntimeContext: cloneMap(input.RuntimeContext),
}
}
func resumePreparationInput(session storesqlite.Session, settings ComposerSettings) RuntimePreparationInput {
return RuntimePreparationInput{
WorkspaceID: session.WorkspaceID, AgentSessionID: session.ID, AgentTargetID: session.AgentTargetID,
Provider: session.Provider, Cwd: session.Cwd, Title: session.Title, PermissionModeID: settings.PermissionModeID,
PlanMode: settings.PlanMode, BrowserUse: valueBoolDefault(settings.BrowserUse, true), ComputerUse: valueBoolDefault(settings.ComputerUse, true), CodexSaverMode: settings.CodexSaverMode, RTKSaverMode: settings.RTKSaverMode,
Model: settings.Model, ReasoningEffort: settings.ReasoningEffort, ConversationDetailMode: settings.ConversationDetailMode,
RuntimeContext: cloneMap(session.InternalRuntimeContext), SessionOrigin: session.Origin,
ProviderSessionID: session.ProviderSessionID, CreatedAtUnixMS: session.CreatedAtUnixMS,
UpdatedAtUnixMS: session.UpdatedAtUnixMS, Visible: session.Metadata.Visible, Settings: settings,
SessionMetadata: session.Metadata,
}
}
func overlayRuntimeContext(base map[string]any, overlay map[string]any) map[string]any {
result := cloneMap(base)
if len(overlay) == 0 {
return result
}
if result == nil {
result = make(map[string]any, len(overlay))
}
for key, value := range cloneMap(overlay) {
baseMap, baseIsMap := result[key].(map[string]any)
overlayMap, overlayIsMap := value.(map[string]any)
if baseIsMap && overlayIsMap {
result[key] = overlayRuntimeContext(baseMap, overlayMap)
continue
}
result[key] = value
}
return result
}
func composerSettingsFromMap(values map[string]any) ComposerSettings {
result := ComposerSettings{}
result.CodexSaverMode, _ = values["codexSaverMode"].(bool)
result.RTKSaverMode, _ = values["rtkSaverMode"].(bool)
result.Model, _ = values["model"].(string)
result.PermissionModeID, _ = values["permissionModeId"].(string)
result.PlanMode, _ = values["planMode"].(bool)
if value, ok := values["browserUse"].(bool); ok {
result.BrowserUse = &value
}
if value, ok := values["computerUse"].(bool); ok {
result.ComputerUse = &value
}
result.ReasoningEffort, _ = values["reasoningEffort"].(string)
result.Speed, _ = values["speed"].(string)
result.ConversationDetailMode, _ = values["conversationDetailMode"].(string)
return result
}
func lifecycleFromTurn(turn storesqlite.Turn) TurnLifecycle {
result := TurnLifecycle{Phase: turn.Phase}
if turnID := strings.TrimSpace(turn.TurnID); turnID != "" && turn.Phase != "settled" {
result.ActiveTurnID = &turnID
}
if turn.Outcome != "" {
outcome := turn.Outcome
result.Outcome = &outcome
}
if turn.CompletedCommandKind != "" || turn.CompletedCommandStatus != "" {
result.CompletedCommand = &CompletedCommand{Kind: turn.CompletedCommandKind, Status: turn.CompletedCommandStatus}
}
return result
}
func imageOnlyDisplayText(content []PromptContentBlock) string {
count := 0
for _, block := range content {
if block.Type == "image" {
count++
}
}
if count == 1 {
return "[Image]"
}
if count > 1 {
return "[Images]"
}
return ""
}
func value(input *string) string {
if input == nil {
return ""
}
return strings.TrimSpace(*input)
}
func valueBool(input *bool) bool { return input != nil && *input }
func valueBoolDefault(input *bool, fallback bool) bool {
if input == nil {
return fallback
}
return *input
}
func boolPointer(value bool) *bool { return &value }
func cloneStringPointer(value *string) *string {
if value == nil {
return nil
}
cloned := *value
return &cloned
}
func firstMap(values ...map[string]any) map[string]any {
for _, value := range values {
if len(value) > 0 {
return value
}
}
return nil
}