Files
Agent-System-Backend/internal/runmgr/genui_auto.go
T
weichenandCursor 6ff7fa9bd7
ci / vet-and-test (pull_request) Successful in 1m4s
Add Generative UI auto-present opt-in with budget and cooldown
Why: Known-boundary follow-up: owner opt-in auto page suggestions on
semantic task events without self-trigger from surface revisions.
Evidence: go test ./internal/genui/ ./internal/runmgr/ ./internal/settings/ ./internal/app/
Impact: Default-off settings key; material/plan/todo/document hooks nudge present.
Refs: docs/proposals/2026-10-12-generative-ui-auto-trigger.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 03:44:47 +00:00

85 lines
2.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package runmgr
import (
"agent-system-backend/internal/genui"
core "agent-system-core"
)
// SetGenUIAuto 注入自动建议闸门(组合根装配;nil 关闭)。
func (m *Manager) SetGenUIAuto(a GenUIAutoTrigger) { m.genuiAuto = a }
func genUIAutoReminderText() string { return genui.AutoReminder }
// maybeGenUIAuto:语义事件钩子入口。会话忙碌时只追加 system 消息供下一轮消费;
// 空闲时启动短 notice-run 让模型有机会立即 present。
func (m *Manager) maybeGenUIAuto(owner, convID, reason string) {
if m == nil || m.genuiAuto == nil {
return
}
ok, _ := m.genuiAuto.Try(owner, convID, reason)
if !ok {
return
}
go m.deliverGenUIAutoReminder(owner, convID, reason)
}
func (m *Manager) deliverGenUIAutoReminder(owner, convID, reason string) {
text := "<system-reminder>\n" + genUIAutoReminderText() + "\n(trigger=" + reason + ")\n</system-reminder>"
msg := core.Message{
ConversationID: convID, Role: core.RoleSystem,
Parts: []core.Part{{Type: core.PartText, Text: text}},
}
if err := m.st.AppendMessage(&msg); err != nil {
return
}
m.convMu.Lock()
busy := m.convActive[convID]
m.convMu.Unlock()
if busy {
return
}
conv, err := m.st.GetConversation(owner, convID)
if err != nil {
return
}
if err := m.claimConversation(convID); err != nil {
return
}
if _, err := m.startClaimedRun(conv, msg, nil, nil, nil); err != nil {
m.releaseConversation(convID)
}
}
func planStageChanged(prev, next core.PlanSnapshot) bool {
pm := map[string]string{}
for _, s := range prev.Steps {
pm[s.ID] = string(s.Status)
}
for _, s := range next.Steps {
if pm[s.ID] != string(s.Status) {
return true
}
}
// 新增步骤也视为阶段组织变化
if len(next.Steps) > len(prev.Steps) {
return true
}
return false
}
func todoStageChanged(prev, next core.TodoList) bool {
pm := map[string]string{}
for _, t := range prev.Items {
pm[t.ID] = string(t.Status)
}
for _, t := range next.Items {
if pm[t.ID] != string(t.Status) {
return true
}
}
if len(next.Items) > len(prev.Items) {
return true
}
return false
}