fix: 流式模式自动执行 + 改进命令提取正则

This commit is contained in:
chinadoiphin
2025-12-16 20:38:18 +08:00
parent bafb8ce795
commit 2a33b15f09
2 changed files with 78 additions and 9 deletions

View File

@@ -364,7 +364,59 @@ func handleStream(c *gin.Context, cursorReq browser.CursorChatRequest, model str
responseText := fullResponse.String()
toolCalls, _ := toolParser.ParseToolCalls(responseText)
if len(toolCalls) > 0 {
// 如果没有工具调用,检查是否是拒绝响应,自动执行
if len(toolCalls) == 0 && tools.DetectRefusal(responseText) {
if cmd := tools.ExtractCommandFromRefusal(responseText); cmd != "" {
// 自动执行提取的命令
output, execErr := toolExecutor.Execute("bash", map[string]interface{}{
"command": cmd,
})
resultText := output
isError := false
if execErr != nil {
resultText = execErr.Error()
isError = true
}
// 发送工具调用块
toolID := "toolu_" + generateID()
stopReason = "tool_use"
c.Writer.WriteString("event: content_block_start\n")
c.Writer.WriteString(fmt.Sprintf(`data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"%s","name":"bash","input":{}}}`+"\n\n", toolID))
flusher.Flush()
inputJSON, _ := json.Marshal(map[string]string{"command": cmd})
c.Writer.WriteString("event: content_block_delta\n")
c.Writer.WriteString(fmt.Sprintf(`data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"%s"}}`+"\n\n", escapeJSON(string(inputJSON))))
flusher.Flush()
c.Writer.WriteString("event: content_block_stop\n")
c.Writer.WriteString(`data: {"type":"content_block_stop","index":1}` + "\n\n")
flusher.Flush()
// 发送执行结果作为新的文本块
statusEmoji := "✅"
if isError {
statusEmoji = "❌"
}
resultMsg := fmt.Sprintf("\n\n%s 已自动执行:\n```\n%s\n```\n结果:\n```\n%s\n```", statusEmoji, cmd, resultText)
resultJSON, _ := json.Marshal(resultMsg)
c.Writer.WriteString("event: content_block_start\n")
c.Writer.WriteString(`data: {"type":"content_block_start","index":2,"content_block":{"type":"text","text":""}}` + "\n\n")
flusher.Flush()
c.Writer.WriteString("event: content_block_delta\n")
c.Writer.WriteString(`data: {"type":"content_block_delta","index":2,"delta":{"type":"text_delta","text":` + string(resultJSON) + `}}` + "\n\n")
flusher.Flush()
c.Writer.WriteString("event: content_block_stop\n")
c.Writer.WriteString(`data: {"type":"content_block_stop","index":2}` + "\n\n")
flusher.Flush()
}
} else if len(toolCalls) > 0 {
stopReason = "tool_use"
// 发送工具调用块
for i, call := range toolCalls {

View File

@@ -136,19 +136,36 @@ func DetectRefusal(response string) bool {
// ExtractCommandFromRefusal 从拒绝响应中提取建议的命令
func ExtractCommandFromRefusal(response string) string {
// 匹配代码块中的命令
codeBlockRe := regexp.MustCompile("```(?:bash|sh)?\\s*\\n([^`]+)\\n```")
codeBlockRe := regexp.MustCompile("```(?:bash|sh)?\\s*\\n?([^`]+)\\n?```")
if matches := codeBlockRe.FindStringSubmatch(response); len(matches) > 1 {
return strings.TrimSpace(matches[1])
cmd := strings.TrimSpace(matches[1])
if cmd != "" {
return cmd
}
}
// 匹配单行命令
// 匹配常见命令模式(每行检查)
lines := strings.Split(response, "\n")
cmdPatterns := []*regexp.Regexp{
regexp.MustCompile(`(?m)^\s*(cat|echo|mkdir|touch|rm|cp|mv|ls|cd|pwd)\s+.+$`),
regexp.MustCompile(`(?m)^\s*(\S+)\s+>\s+\S+`),
// echo "xxx" > file
regexp.MustCompile(`^\s*(echo\s+.+\s*>\s*\S+)`),
// cat > file << 'EOF' 或 cat > file
regexp.MustCompile(`^\s*(cat\s+.+\s*>\s*\S+)`),
// 常见命令开头
regexp.MustCompile(`^\s*((?:echo|cat|mkdir|touch|rm|cp|mv|ls|pwd|cd|chmod|chown)\s+.+)$`),
// 任何 > 重定向
regexp.MustCompile(`^\s*(\S+\s+["'][^"']+["']\s*>\s*\S+)`),
}
for _, re := range cmdPatterns {
if matches := re.FindString(response); matches != "" {
return strings.TrimSpace(matches)
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
for _, re := range cmdPatterns {
if matches := re.FindStringSubmatch(line); len(matches) > 1 {
return strings.TrimSpace(matches[1])
}
}
}