mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 21:57:29 +08:00
make autonomy proactive messaging strategy configurable
This commit is contained in:
@@ -770,18 +770,21 @@ func buildHeartbeatService(cfg *config.Config, msgBus *bus.MessageBus) *heartbea
|
||||
func buildAutonomyEngine(cfg *config.Config, msgBus *bus.MessageBus) *autonomy.Engine {
|
||||
a := cfg.Agents.Defaults.Autonomy
|
||||
return autonomy.NewEngine(autonomy.Options{
|
||||
Enabled: a.Enabled,
|
||||
TickIntervalSec: a.TickIntervalSec,
|
||||
MinRunIntervalSec: a.MinRunIntervalSec,
|
||||
MaxPendingDurationSec: a.MaxPendingDurationSec,
|
||||
MaxConsecutiveStalls: a.MaxConsecutiveStalls,
|
||||
MaxDispatchPerTick: a.MaxDispatchPerTick,
|
||||
NotifyCooldownSec: a.NotifyCooldownSec,
|
||||
QuietHours: a.QuietHours,
|
||||
UserIdleResumeSec: a.UserIdleResumeSec,
|
||||
Enabled: a.Enabled,
|
||||
TickIntervalSec: a.TickIntervalSec,
|
||||
MinRunIntervalSec: a.MinRunIntervalSec,
|
||||
MaxPendingDurationSec: a.MaxPendingDurationSec,
|
||||
MaxConsecutiveStalls: a.MaxConsecutiveStalls,
|
||||
MaxDispatchPerTick: a.MaxDispatchPerTick,
|
||||
NotifyCooldownSec: a.NotifyCooldownSec,
|
||||
QuietHours: a.QuietHours,
|
||||
UserIdleResumeSec: a.UserIdleResumeSec,
|
||||
WaitingResumeDebounceSec: a.WaitingResumeDebounceSec,
|
||||
Workspace: cfg.WorkspacePath(),
|
||||
DefaultNotifyChannel: a.NotifyChannel,
|
||||
DefaultNotifyChatID: a.NotifyChatID,
|
||||
ImportantKeywords: cfg.Agents.Defaults.Texts.AutonomyImportantKeywords,
|
||||
CompletionTemplate: cfg.Agents.Defaults.Texts.AutonomyCompletionTemplate,
|
||||
BlockedTemplate: cfg.Agents.Defaults.Texts.AutonomyBlockedTemplate,
|
||||
Workspace: cfg.WorkspacePath(),
|
||||
DefaultNotifyChannel: a.NotifyChannel,
|
||||
DefaultNotifyChatID: a.NotifyChatID,
|
||||
}, msgBus)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,10 @@
|
||||
"unsupported_action": "unsupported action",
|
||||
"system_rewrite_template": "Rewrite the following internal system update in concise user-facing language:\n\n%s",
|
||||
"runtime_compaction_note": "[runtime-compaction] removed %d old messages, kept %d recent messages",
|
||||
"startup_compaction_note": "[startup-compaction] removed %d old messages, kept %d recent messages"
|
||||
"startup_compaction_note": "[startup-compaction] removed %d old messages, kept %d recent messages",
|
||||
"autonomy_important_keywords": ["urgent", "重要", "付款", "payment", "上线", "release", "deadline", "截止"],
|
||||
"autonomy_completion_template": "✅ 已完成:%s\n下一步:如需我继续处理后续,直接回复“继续 %s”",
|
||||
"autonomy_blocked_template": "⚠️ 任务受阻:%s\n原因:%s\n建议:回复“继续 %s”我会按当前状态重试。"
|
||||
},
|
||||
"context_compaction": {
|
||||
"enabled": true,
|
||||
|
||||
@@ -33,6 +33,9 @@ type Options struct {
|
||||
QuietHours string
|
||||
UserIdleResumeSec int
|
||||
WaitingResumeDebounceSec int
|
||||
ImportantKeywords []string
|
||||
CompletionTemplate string
|
||||
BlockedTemplate string
|
||||
}
|
||||
|
||||
type taskState struct {
|
||||
@@ -385,16 +388,20 @@ func (e *Engine) dispatchTask(st *taskState) {
|
||||
func (e *Engine) sendCompletionNotification(st *taskState) {
|
||||
e.writeReflectLog("complete", st, "task marked completed")
|
||||
e.writeTriggerAudit("complete", st, "")
|
||||
if !isHighValueCompletion(st) {
|
||||
if !e.isHighValueCompletion(st) {
|
||||
return
|
||||
}
|
||||
if !e.shouldNotify("done:" + st.ID) {
|
||||
return
|
||||
}
|
||||
tpl := strings.TrimSpace(e.opts.CompletionTemplate)
|
||||
if tpl == "" {
|
||||
tpl = "✅ 已完成:%s\n下一步:如需我继续处理后续,直接回复“继续 %s”"
|
||||
}
|
||||
e.bus.PublishOutbound(bus.OutboundMessage{
|
||||
Channel: e.opts.DefaultNotifyChannel,
|
||||
ChatID: e.opts.DefaultNotifyChatID,
|
||||
Content: fmt.Sprintf("✅ 已完成:%s\n下一步:如需我继续处理后续,直接回复“继续 %s”", shortTask(st.Content), shortTask(st.Content)),
|
||||
Content: fmt.Sprintf(tpl, shortTask(st.Content), shortTask(st.Content)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -404,10 +411,14 @@ func (e *Engine) sendFailureNotification(st *taskState, reason string) {
|
||||
if !e.shouldNotify("blocked:" + st.ID) {
|
||||
return
|
||||
}
|
||||
tpl := strings.TrimSpace(e.opts.BlockedTemplate)
|
||||
if tpl == "" {
|
||||
tpl = "⚠️ 任务受阻:%s\n原因:%s\n建议:回复“继续 %s”我会按当前状态重试。"
|
||||
}
|
||||
e.bus.PublishOutbound(bus.OutboundMessage{
|
||||
Channel: e.opts.DefaultNotifyChannel,
|
||||
ChatID: e.opts.DefaultNotifyChatID,
|
||||
Content: fmt.Sprintf("⚠️ 任务受阻:%s\n原因:%s\n建议:回复“继续 %s”我会按当前状态重试。", shortTask(st.Content), strings.TrimSpace(reason), shortTask(st.Content)),
|
||||
Content: fmt.Sprintf(tpl, shortTask(st.Content), strings.TrimSpace(reason), shortTask(st.Content)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -754,7 +765,7 @@ func min(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
func isHighValueCompletion(st *taskState) bool {
|
||||
func (e *Engine) isHighValueCompletion(st *taskState) bool {
|
||||
if st == nil {
|
||||
return false
|
||||
}
|
||||
@@ -765,8 +776,13 @@ func isHighValueCompletion(st *taskState) bool {
|
||||
return true
|
||||
}
|
||||
s := strings.ToLower(strings.TrimSpace(st.Content))
|
||||
for _, k := range []string{"urgent", "重要", "付款", "payment", "上线", "release", "deadline", "截止"} {
|
||||
if strings.Contains(s, k) {
|
||||
keywords := e.opts.ImportantKeywords
|
||||
if len(keywords) == 0 {
|
||||
keywords = []string{"urgent", "重要", "付款", "payment", "上线", "release", "deadline", "截止"}
|
||||
}
|
||||
for _, k := range keywords {
|
||||
kk := strings.ToLower(strings.TrimSpace(k))
|
||||
if kk != "" && strings.Contains(s, kk) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,18 +60,21 @@ type AutonomyConfig struct {
|
||||
}
|
||||
|
||||
type AgentTextConfig struct {
|
||||
NoResponseFallback string `json:"no_response_fallback"`
|
||||
ThinkOnlyFallback string `json:"think_only_fallback"`
|
||||
MemoryRecallKeywords []string `json:"memory_recall_keywords"`
|
||||
LangUsage string `json:"lang_usage"`
|
||||
LangInvalid string `json:"lang_invalid"`
|
||||
LangUpdatedTemplate string `json:"lang_updated_template"`
|
||||
SubagentsNone string `json:"subagents_none"`
|
||||
SessionsNone string `json:"sessions_none"`
|
||||
UnsupportedAction string `json:"unsupported_action"`
|
||||
SystemRewriteTemplate string `json:"system_rewrite_template"`
|
||||
RuntimeCompactionNote string `json:"runtime_compaction_note"`
|
||||
StartupCompactionNote string `json:"startup_compaction_note"`
|
||||
NoResponseFallback string `json:"no_response_fallback"`
|
||||
ThinkOnlyFallback string `json:"think_only_fallback"`
|
||||
MemoryRecallKeywords []string `json:"memory_recall_keywords"`
|
||||
LangUsage string `json:"lang_usage"`
|
||||
LangInvalid string `json:"lang_invalid"`
|
||||
LangUpdatedTemplate string `json:"lang_updated_template"`
|
||||
SubagentsNone string `json:"subagents_none"`
|
||||
SessionsNone string `json:"sessions_none"`
|
||||
UnsupportedAction string `json:"unsupported_action"`
|
||||
SystemRewriteTemplate string `json:"system_rewrite_template"`
|
||||
RuntimeCompactionNote string `json:"runtime_compaction_note"`
|
||||
StartupCompactionNote string `json:"startup_compaction_note"`
|
||||
AutonomyImportantKeywords []string `json:"autonomy_important_keywords"`
|
||||
AutonomyCompletionTemplate string `json:"autonomy_completion_template"`
|
||||
AutonomyBlockedTemplate string `json:"autonomy_blocked_template"`
|
||||
}
|
||||
|
||||
type HeartbeatConfig struct {
|
||||
@@ -324,9 +327,12 @@ func DefaultConfig() *Config {
|
||||
SubagentsNone: "No subagents.",
|
||||
SessionsNone: "No sessions.",
|
||||
UnsupportedAction: "unsupported action",
|
||||
SystemRewriteTemplate: "Rewrite the following internal system update in concise user-facing language:\n\n%s",
|
||||
RuntimeCompactionNote: "[runtime-compaction] removed %d old messages, kept %d recent messages",
|
||||
StartupCompactionNote: "[startup-compaction] removed %d old messages, kept %d recent messages",
|
||||
SystemRewriteTemplate: "Rewrite the following internal system update in concise user-facing language:\n\n%s",
|
||||
RuntimeCompactionNote: "[runtime-compaction] removed %d old messages, kept %d recent messages",
|
||||
StartupCompactionNote: "[startup-compaction] removed %d old messages, kept %d recent messages",
|
||||
AutonomyImportantKeywords: []string{"urgent", "重要", "付款", "payment", "上线", "release", "deadline", "截止"},
|
||||
AutonomyCompletionTemplate: "✅ 已完成:%s\n下一步:如需我继续处理后续,直接回复“继续 %s”",
|
||||
AutonomyBlockedTemplate: "⚠️ 任务受阻:%s\n原因:%s\n建议:回复“继续 %s”我会按当前状态重试。",
|
||||
},
|
||||
ContextCompaction: ContextCompactionConfig{
|
||||
Enabled: true,
|
||||
|
||||
@@ -138,6 +138,15 @@ func Validate(cfg *Config) []error {
|
||||
errs = append(errs, fmt.Errorf("agents.defaults.texts.startup_compaction_note must contain two %%d placeholders"))
|
||||
}
|
||||
}
|
||||
if len(texts.AutonomyImportantKeywords) == 0 {
|
||||
errs = append(errs, fmt.Errorf("agents.defaults.texts.autonomy_important_keywords must contain at least one keyword"))
|
||||
}
|
||||
if strings.Count(strings.TrimSpace(texts.AutonomyCompletionTemplate), "%s") < 2 {
|
||||
errs = append(errs, fmt.Errorf("agents.defaults.texts.autonomy_completion_template must contain two %%s placeholders"))
|
||||
}
|
||||
if strings.Count(strings.TrimSpace(texts.AutonomyBlockedTemplate), "%s") < 3 {
|
||||
errs = append(errs, fmt.Errorf("agents.defaults.texts.autonomy_blocked_template must contain three %%s placeholders"))
|
||||
}
|
||||
|
||||
if cfg.Agents.Defaults.ContextCompaction.Enabled {
|
||||
cc := cfg.Agents.Defaults.ContextCompaction
|
||||
|
||||
Reference in New Issue
Block a user