mirror of
https://github.com/7836246/cursor2api.git
synced 2026-09-03 07:20:02 +08:00
fix: 流式模式自动执行 + 改进命令提取正则
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user