feat(agents): allow disabling subagent tool feedback
This commit is contained in:
parent
7744e44704
commit
2efdcb7bec
6 changed files with 69 additions and 1 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"max_args_length": 300,
|
"max_args_length": 300,
|
||||||
"separate_messages": false,
|
"separate_messages": false,
|
||||||
|
"subagents": true,
|
||||||
"style": "raw"
|
"style": "raw"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ Debug logs are server-side only. If you want the agent to send a visible notific
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"max_args_length": 300,
|
"max_args_length": 300,
|
||||||
"separate_messages": true,
|
"separate_messages": true,
|
||||||
|
"subagents": true,
|
||||||
"style": "raw"
|
"style": "raw"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,6 +91,7 @@ Set `style` to `working_summary` to use a compact, non-argument progress message
|
||||||
"tool_feedback": {
|
"tool_feedback": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"separate_messages": false,
|
"separate_messages": false,
|
||||||
|
"subagents": true,
|
||||||
"style": "working_summary"
|
"style": "working_summary"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +123,7 @@ The `working_summary` style intentionally does not show raw tool arguments, expl
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `enabled` | bool | `false` | Send a chat notification for each tool call |
|
| `enabled` | bool | `false` | Send a chat notification for each tool call |
|
||||||
| `separate_messages` | bool | `false` | Keep every tool feedback update as a separate chat message instead of reusing a single placeholder/progress message |
|
| `separate_messages` | bool | `false` | Keep every tool feedback update as a separate chat message instead of reusing a single placeholder/progress message |
|
||||||
|
| `subagents` | bool | `true` | Also publish visible tool feedback for subagent turns when `enabled` is true |
|
||||||
| `max_args_length` | int | `300` | Maximum characters of the serialised arguments included in the notification |
|
| `max_args_length` | int | `300` | Maximum characters of the serialised arguments included in the notification |
|
||||||
| `style` | string | `raw` | Feedback format. Use `raw` for the original tool/explanation/argument preview, or `working_summary` for compact progress lines without raw arguments |
|
| `style` | string | `raw` | Feedback format. Use `raw` for the original tool/explanation/argument preview, or `working_summary` for compact progress lines without raw arguments |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2093,6 +2093,29 @@ func TestToolFeedbackArgsPreview_UsesJSONAndTruncates(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShouldPublishToolFeedback_DisablesSubagentFeedback(t *testing.T) {
|
||||||
|
subagents := false
|
||||||
|
cfg := config.DefaultConfig()
|
||||||
|
cfg.Agents.Defaults.ToolFeedback = config.ToolFeedbackConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Subagents: &subagents,
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldPublishToolFeedback(cfg, &turnState{
|
||||||
|
channel: "telegram",
|
||||||
|
sessionKey: "subturn-1",
|
||||||
|
}) {
|
||||||
|
t.Fatal("shouldPublishToolFeedback() = true for disabled subagent feedback, want false")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldPublishToolFeedback(cfg, &turnState{
|
||||||
|
channel: "telegram",
|
||||||
|
sessionKey: "chat-1",
|
||||||
|
}) {
|
||||||
|
t.Fatal("shouldPublishToolFeedback() = false for main turn, want true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type picoInterleavedContentProvider struct {
|
type picoInterleavedContentProvider struct {
|
||||||
calls int
|
calls int
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,14 @@ func shouldPublishToolFeedback(cfg *config.Config, ts *turnState) bool {
|
||||||
if ts == nil || ts.channel == "" || ts.opts.SuppressToolFeedback {
|
if ts == nil || ts.channel == "" || ts.opts.SuppressToolFeedback {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return cfg != nil && cfg.Agents.Defaults.IsToolFeedbackEnabled()
|
if cfg == nil || !cfg.Agents.Defaults.IsToolFeedbackEnabled() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(strings.TrimSpace(ts.sessionKey), "subturn-") &&
|
||||||
|
!cfg.Agents.Defaults.IsSubagentToolFeedbackEnabled() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func toolFeedbackTitleForTurn(ts *turnState) string {
|
func toolFeedbackTitleForTurn(ts *turnState) string {
|
||||||
|
|
|
||||||
|
|
@ -252,6 +252,7 @@ type ToolFeedbackConfig struct {
|
||||||
Enabled bool `json:"enabled" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_ENABLED"`
|
Enabled bool `json:"enabled" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_ENABLED"`
|
||||||
MaxArgsLength int `json:"max_args_length" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_MAX_ARGS_LENGTH"`
|
MaxArgsLength int `json:"max_args_length" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_MAX_ARGS_LENGTH"`
|
||||||
SeparateMessages bool `json:"separate_messages" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_SEPARATE_MESSAGES"`
|
SeparateMessages bool `json:"separate_messages" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_SEPARATE_MESSAGES"`
|
||||||
|
Subagents *bool `json:"subagents,omitempty"`
|
||||||
Style string `json:"style,omitempty" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_STYLE"`
|
Style string `json:"style,omitempty" env:"PICOCLAW_AGENTS_DEFAULTS_TOOL_FEEDBACK_STYLE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,6 +306,13 @@ func (d *AgentDefaults) IsToolFeedbackEnabled() bool {
|
||||||
return d.ToolFeedback.Enabled
|
return d.ToolFeedback.Enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsSubagentToolFeedbackEnabled returns true when subagent turns should publish
|
||||||
|
// visible tool feedback. It defaults to true for backward compatibility when
|
||||||
|
// tool_feedback itself is enabled.
|
||||||
|
func (d *AgentDefaults) IsSubagentToolFeedbackEnabled() bool {
|
||||||
|
return d.ToolFeedback.Subagents == nil || *d.ToolFeedback.Subagents
|
||||||
|
}
|
||||||
|
|
||||||
// IsToolFeedbackSeparateMessagesEnabled returns true when each tool feedback
|
// IsToolFeedbackSeparateMessagesEnabled returns true when each tool feedback
|
||||||
// update should be sent as its own chat message instead of editing a single
|
// update should be sent as its own chat message instead of editing a single
|
||||||
// in-place progress message.
|
// in-place progress message.
|
||||||
|
|
|
||||||
|
|
@ -787,6 +787,9 @@ func TestDefaultConfig_ToolFeedbackDisabled(t *testing.T) {
|
||||||
if cfg.Agents.Defaults.ToolFeedback.Enabled {
|
if cfg.Agents.Defaults.ToolFeedback.Enabled {
|
||||||
t.Fatal("DefaultConfig().Agents.Defaults.ToolFeedback.Enabled should be false")
|
t.Fatal("DefaultConfig().Agents.Defaults.ToolFeedback.Enabled should be false")
|
||||||
}
|
}
|
||||||
|
if !cfg.Agents.Defaults.IsSubagentToolFeedbackEnabled() {
|
||||||
|
t.Fatal("DefaultConfig().Agents.Defaults.IsSubagentToolFeedbackEnabled() should default to true")
|
||||||
|
}
|
||||||
if cfg.Agents.Defaults.ToolFeedback.SeparateMessages {
|
if cfg.Agents.Defaults.ToolFeedback.SeparateMessages {
|
||||||
t.Fatal("DefaultConfig().Agents.Defaults.ToolFeedback.SeparateMessages should be false")
|
t.Fatal("DefaultConfig().Agents.Defaults.ToolFeedback.SeparateMessages should be false")
|
||||||
}
|
}
|
||||||
|
|
@ -813,6 +816,9 @@ func TestLoadConfig_ToolFeedbackDefaultsFalseWhenUnset(t *testing.T) {
|
||||||
if cfg.Agents.Defaults.ToolFeedback.Enabled {
|
if cfg.Agents.Defaults.ToolFeedback.Enabled {
|
||||||
t.Fatal("agents.defaults.tool_feedback.enabled should remain false when unset in config file")
|
t.Fatal("agents.defaults.tool_feedback.enabled should remain false when unset in config file")
|
||||||
}
|
}
|
||||||
|
if !cfg.Agents.Defaults.IsSubagentToolFeedbackEnabled() {
|
||||||
|
t.Fatal("agents.defaults.tool_feedback.subagents should default to true when unset")
|
||||||
|
}
|
||||||
if cfg.Agents.Defaults.ToolFeedback.SeparateMessages {
|
if cfg.Agents.Defaults.ToolFeedback.SeparateMessages {
|
||||||
t.Fatal("agents.defaults.tool_feedback.separate_messages should remain false when unset in config file")
|
t.Fatal("agents.defaults.tool_feedback.separate_messages should remain false when unset in config file")
|
||||||
}
|
}
|
||||||
|
|
@ -841,6 +847,26 @@ func TestLoadConfig_ToolFeedbackStyle(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig_ToolFeedbackSubagentsFalse(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
configPath := filepath.Join(dir, "config.json")
|
||||||
|
if err := os.WriteFile(
|
||||||
|
configPath,
|
||||||
|
[]byte(`{"version":1,"agents":{"defaults":{"tool_feedback":{"enabled":true,"subagents":false}}}}`),
|
||||||
|
0o600,
|
||||||
|
); err != nil {
|
||||||
|
t.Fatalf("WriteFile() error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := LoadConfig(configPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LoadConfig() error: %v", err)
|
||||||
|
}
|
||||||
|
if cfg.Agents.Defaults.IsSubagentToolFeedbackEnabled() {
|
||||||
|
t.Fatal("agents.defaults.tool_feedback.subagents = true, want false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadConfig_WebPreferNativeDefaultsTrueWhenUnset(t *testing.T) {
|
func TestLoadConfig_WebPreferNativeDefaultsTrueWhenUnset(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
configPath := filepath.Join(dir, "config.json")
|
configPath := filepath.Join(dir, "config.json")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue