diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 05ccbe449..cfffce606 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -81,6 +81,7 @@ type processOptions struct { ForcedSkills []string // Skills explicitly requested for this message SystemPromptOverride string // Override the default system prompt (Used by SubTurns) Media []string // media:// refs from inbound message + IsVoice bool // True if this message comes from an audio/voice call InitialSteeringMessages []providers.Message // Steering messages from refactor/agent DefaultResponse string // Response when LLM returns empty EnableSummary bool // Whether to trigger summarization @@ -1311,17 +1312,25 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage) "route_channel": route.Channel, }) + isVoice := msg.Metadata != nil && msg.Metadata["is_voice"] == "true" + var systemPromptOverride string + if isVoice { + systemPromptOverride = "You are a helpful AI assistant. The user is speaking to you over voice chat. Reply in a concise, conversational, and natural oral style suitable for text-to-speech. Get straight to the point. Do not use Markdown, emojis, asterisks, or code blocks." + } + opts := processOptions{ - SessionKey: sessionKey, - Channel: msg.Channel, - ChatID: msg.ChatID, - SenderID: msg.SenderID, - SenderDisplayName: msg.Sender.DisplayName, - UserMessage: msg.Content, - Media: msg.Media, - DefaultResponse: defaultResponse, - EnableSummary: true, - SendResponse: false, + SessionKey: sessionKey, + Channel: msg.Channel, + ChatID: msg.ChatID, + SenderID: msg.SenderID, + SenderDisplayName: msg.Sender.DisplayName, + UserMessage: msg.Content, + SystemPromptOverride: systemPromptOverride, + Media: msg.Media, + IsVoice: isVoice, + DefaultResponse: defaultResponse, + EnableSummary: true, + SendResponse: false, } // context-dependent commands check their own Runtime fields and report @@ -1640,7 +1649,10 @@ func (al *AgentLoop) runTurn(ctx context.Context, ts *turnState) (turnResult, er messages = resolveMediaRefs(messages, al.mediaStore, maxMediaSize) if !ts.opts.NoHistory { - toolDefs := ts.agent.Tools.ToProviderDefs() + var toolDefs []providers.ToolDefinition + if !ts.opts.IsVoice { + toolDefs = ts.agent.Tools.ToProviderDefs() + } if isOverContextBudget(ts.agent.ContextWindow, messages, toolDefs, ts.agent.MaxTokens) { logger.WarnCF("agent", "Proactive compression: context budget exceeded before LLM call", map[string]any{"session_key": ts.sessionKey}) @@ -1779,7 +1791,10 @@ turnLoop: }) gracefulTerminal, _ := ts.gracefulInterruptRequested() - providerToolDefs := ts.agent.Tools.ToProviderDefs() + var providerToolDefs []providers.ToolDefinition + if !ts.opts.IsVoice { + providerToolDefs = ts.agent.Tools.ToProviderDefs() + } // Native web search support (from HEAD) _, hasWebSearch := ts.agent.Tools.Get("web_search") diff --git a/pkg/utils/string.go b/pkg/utils/string.go index dbaafdb7f..99337b557 100644 --- a/pkg/utils/string.go +++ b/pkg/utils/string.go @@ -65,3 +65,8 @@ func DerefStr(s *string, fallback string) string { } return *s } + +// IsTruncationDisabled returns whether truncation is disabled globally +func IsTruncationDisabled() bool { +return disableTruncation.Load() +}