fix(agent): gate pico interim publish for internal turns
This commit is contained in:
parent
58f634b582
commit
bd88385923
2 changed files with 64 additions and 13 deletions
|
|
@ -88,6 +88,7 @@ type processOptions struct {
|
||||||
DefaultResponse string // Response when LLM returns empty
|
DefaultResponse string // Response when LLM returns empty
|
||||||
EnableSummary bool // Whether to trigger summarization
|
EnableSummary bool // Whether to trigger summarization
|
||||||
SendResponse bool // Whether to send response via bus
|
SendResponse bool // Whether to send response via bus
|
||||||
|
AllowInterimPicoPublish bool // Whether pico tool-call interim text can be published when SendResponse is false
|
||||||
SuppressToolFeedback bool // Whether to suppress inline tool feedback messages
|
SuppressToolFeedback bool // Whether to suppress inline tool feedback messages
|
||||||
NoHistory bool // If true, don't load session history (for heartbeat)
|
NoHistory bool // If true, don't load session history (for heartbeat)
|
||||||
SkipInitialSteeringPoll bool // If true, skip the steering poll at loop start (used by Continue)
|
SkipInitialSteeringPoll bool // If true, skip the steering poll at loop start (used by Continue)
|
||||||
|
|
@ -1398,18 +1399,19 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
opts := processOptions{
|
opts := processOptions{
|
||||||
SessionKey: sessionKey,
|
SessionKey: sessionKey,
|
||||||
Channel: msg.Channel,
|
Channel: msg.Channel,
|
||||||
ChatID: msg.ChatID,
|
ChatID: msg.ChatID,
|
||||||
MessageID: msg.MessageID,
|
MessageID: msg.MessageID,
|
||||||
ReplyToMessageID: inboundMetadata(msg, metadataKeyReplyToMessage),
|
ReplyToMessageID: inboundMetadata(msg, metadataKeyReplyToMessage),
|
||||||
SenderID: msg.SenderID,
|
SenderID: msg.SenderID,
|
||||||
SenderDisplayName: msg.Sender.DisplayName,
|
SenderDisplayName: msg.Sender.DisplayName,
|
||||||
UserMessage: msg.Content,
|
UserMessage: msg.Content,
|
||||||
Media: msg.Media,
|
Media: msg.Media,
|
||||||
DefaultResponse: defaultResponse,
|
DefaultResponse: defaultResponse,
|
||||||
EnableSummary: true,
|
EnableSummary: true,
|
||||||
SendResponse: false,
|
SendResponse: false,
|
||||||
|
AllowInterimPicoPublish: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// context-dependent commands check their own Runtime fields and report
|
// context-dependent commands check their own Runtime fields and report
|
||||||
|
|
@ -2253,7 +2255,7 @@ turnLoop:
|
||||||
}
|
}
|
||||||
logger.DebugCF("agent", "LLM response", llmResponseFields)
|
logger.DebugCF("agent", "LLM response", llmResponseFields)
|
||||||
|
|
||||||
if al.bus != nil && ts.channel == "pico" && len(response.ToolCalls) > 0 {
|
if al.bus != nil && ts.channel == "pico" && len(response.ToolCalls) > 0 && ts.opts.AllowInterimPicoPublish {
|
||||||
if strings.TrimSpace(response.Content) != "" {
|
if strings.TrimSpace(response.Content) != "" {
|
||||||
outCtx, outCancel := context.WithTimeout(turnCtx, 3*time.Second)
|
outCtx, outCancel := context.WithTimeout(turnCtx, 3*time.Second)
|
||||||
err := al.bus.PublishOutbound(outCtx, bus.OutboundMessage{
|
err := al.bus.PublishOutbound(outCtx, bus.OutboundMessage{
|
||||||
|
|
|
||||||
|
|
@ -2844,6 +2844,55 @@ func TestRun_PicoPublishesAssistantContentDuringToolCallsWithoutFinalDuplicate(t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunAgentLoop_PicoSkipsInterimPublishWhenNotAllowed(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
cfg := &config.Config{
|
||||||
|
Agents: config.AgentsConfig{
|
||||||
|
Defaults: config.AgentDefaults{
|
||||||
|
Workspace: tmpDir,
|
||||||
|
ModelName: "test-model",
|
||||||
|
MaxTokens: 4096,
|
||||||
|
MaxToolIterations: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBus := bus.NewMessageBus()
|
||||||
|
provider := &picoInterleavedContentProvider{}
|
||||||
|
al := NewAgentLoop(cfg, msgBus, provider)
|
||||||
|
|
||||||
|
agent := al.GetRegistry().GetDefaultAgent()
|
||||||
|
if agent == nil {
|
||||||
|
t.Fatal("expected default agent")
|
||||||
|
}
|
||||||
|
agent.Tools.Register(&toolLimitTestTool{})
|
||||||
|
|
||||||
|
response, err := al.runAgentLoop(context.Background(), agent, processOptions{
|
||||||
|
SessionKey: "agent:main:pico:session-1",
|
||||||
|
Channel: "pico",
|
||||||
|
ChatID: "session-1",
|
||||||
|
UserMessage: "run with tools",
|
||||||
|
DefaultResponse: defaultResponse,
|
||||||
|
EnableSummary: false,
|
||||||
|
SendResponse: false,
|
||||||
|
AllowInterimPicoPublish: false,
|
||||||
|
SuppressToolFeedback: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("runAgentLoop() error = %v", err)
|
||||||
|
}
|
||||||
|
if response != "final model text" {
|
||||||
|
t.Fatalf("runAgentLoop() response = %q, want %q", response, "final model text")
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case outbound := <-msgBus.OutboundChan():
|
||||||
|
t.Fatalf("unexpected outbound message when interim publish disabled: %+v", outbound)
|
||||||
|
case <-time.After(200 * time.Millisecond):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestResolveMediaRefs_ResolvesToBase64(t *testing.T) {
|
func TestResolveMediaRefs_ResolvesToBase64(t *testing.T) {
|
||||||
store := media.NewFileMediaStore()
|
store := media.NewFileMediaStore()
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue