Bounce prose questions only when they ask the human to decide
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"g.fc.run/misc/byre/internal/api"
|
||||
@@ -30,6 +31,9 @@ var (
|
||||
inlineCode = regexp.MustCompile("`[^`\n]*`")
|
||||
quoted = regexp.MustCompile(`"[^"\n]*"|“[^”\n]*”`)
|
||||
blockquote = regexp.MustCompile(`(?m)^\s*>.*$`)
|
||||
tableRow = regexp.MustCompile(`(?m)^\s*\|.*$`)
|
||||
details = regexp.MustCompile(`(?s)<details>.*?</details>`)
|
||||
paragraphs = regexp.MustCompile(`\n\s*\n`)
|
||||
endsQuestion = regexp.MustCompile(`\?[*_)\]]*(\s|$)`)
|
||||
)
|
||||
|
||||
@@ -38,7 +42,10 @@ func asksQuestion(text string) bool {
|
||||
text = inlineCode.ReplaceAllString(text, "")
|
||||
text = quoted.ReplaceAllString(text, "")
|
||||
text = blockquote.ReplaceAllString(text, "")
|
||||
return endsQuestion.MatchString(text)
|
||||
text = tableRow.ReplaceAllString(text, "")
|
||||
text = details.ReplaceAllString(text, "")
|
||||
paras := paragraphs.Split(strings.TrimSpace(text), -1)
|
||||
return endsQuestion.MatchString(paras[len(paras)-1])
|
||||
}
|
||||
|
||||
func (m *Manager) bounceProseQuestion(l *live) claude.HookFunc {
|
||||
@@ -51,21 +58,46 @@ func (m *Manager) bounceProseQuestion(l *live) claude.HookFunc {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !m.takeBounce(l, in.LastAssistantMessage) {
|
||||
return map[string]any{}, nil
|
||||
bounce, err := m.takeBounce(ctx, l, in.LastAssistantMessage)
|
||||
if err != nil || !bounce {
|
||||
return map[string]any{}, err
|
||||
}
|
||||
err = m.emit(ctx, l, "byre", "user.message", map[string]any{"text": proseQuestionNudge, "mid_turn": true, "bounce": true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return map[string]any{"decision": "block", "reason": proseQuestionNudge}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) takeBounce(l *live, final string) bool {
|
||||
func (m *Manager) takeBounce(ctx context.Context, l *live, final string) (bool, error) {
|
||||
if !asksQuestion(final) {
|
||||
return false, nil
|
||||
}
|
||||
first, err := m.store.FirstPrompt(ctx, l.taskID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if strings.Contains(first, discussPrompt) {
|
||||
return false, nil
|
||||
}
|
||||
open, err := m.store.ListInbox(ctx, store.InboxFilter{TaskID: l.taskID, State: api.Open})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, item := range open {
|
||||
if item.Kind == api.Question {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if l.asked || l.bounced || l.compacting || !asksQuestion(final) {
|
||||
return false
|
||||
if l.asked || l.bounced || l.compacting {
|
||||
return false, nil
|
||||
}
|
||||
l.bounced = true
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *Manager) taskGuidance(ctx context.Context, task api.Task) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user