feat: 添加 Markdown 终端渲染支持(glamour)

This commit is contained in:
2026-04-12 02:26:17 +08:00
parent c1b4f59704
commit 1568c63462
6 changed files with 221 additions and 11 deletions

View File

@@ -7,6 +7,7 @@ import (
"strings"
"github.com/hxclaw/hxclaw/cmd/hxclaw/internal"
"github.com/muesli/termenv"
"github.com/sipeed/picoclaw/pkg/agent"
"github.com/sipeed/picoclaw/pkg/bus"
"github.com/sipeed/picoclaw/pkg/logger"
@@ -160,15 +161,15 @@ func runWithStreaming(agentLoop *agent.AgentLoop, input, sessionKey string) {
var printedLen int
firstToken := true
_, err := sp.ChatStream(ctx, messages, toolDefs, agentInstance.Model, nil, func(accumulated string) {
// 检测到第一个 token 时,停止 spinner
if firstToken && len(accumulated) > 0 {
spinner.Stop()
firstToken = false
}
if len(accumulated) > printedLen {
fmt.Print(accumulated[printedLen:])
newText := accumulated[printedLen:]
fmt.Print(newText)
os.Stdout.Sync()
result.WriteString(accumulated[printedLen:])
result.WriteString(newText)
printedLen = len(accumulated)
}
})
@@ -178,21 +179,38 @@ func runWithStreaming(agentLoop *agent.AgentLoop, input, sessionKey string) {
return
}
fmt.Println()
fmt.Println()
// 将用户消息和回复保存到 session
if result.Len() > 0 {
allOutput := result.String()
rendered := internal.RenderMarkdown(allOutput)
if rendered != allOutput && rendered != "" {
// 计算流式输出的行数,清除
lines := strings.Count(allOutput, "\n") + 1
output := termenv.DefaultOutput()
output.CursorUp(1)
output.ClearLine()
output.ClearLines(lines)
fmt.Print(rendered)
fmt.Println()
fmt.Println()
} else {
fmt.Println()
fmt.Println()
}
agentInstance.Sessions.AddMessage(sessionKey, "user", input)
agentInstance.Sessions.AddMessage(sessionKey, "assistant", result.String())
agentInstance.Sessions.AddMessage(sessionKey, "assistant", allOutput)
}
} else {
// 回退到普通模式
response, err := agentLoop.ProcessDirect(ctx, input, sessionKey)
if err != nil {
fmt.Printf("错误: %v\n", err)
return
}
fmt.Printf("\n%s %s\n\n", Logo, response)
rendered := internal.RenderMarkdown(response)
if rendered != "" && rendered != response {
fmt.Printf("\n%s\n\n", rendered)
} else {
fmt.Printf("\n%s %s\n\n", Logo, response)
}
}
}