From 3f9443c14b3f699617cef645dc1798bc1d6e924d Mon Sep 17 00:00:00 2001 From: titor Date: Wed, 15 Apr 2026 06:14:54 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E8=AE=A8=E8=AE=BA?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=EF=BC=8C=E6=B7=BB=E5=8A=A0=20v0.1.0=20?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E7=9F=A5=E8=AF=86=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taolun.md | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/taolun.md b/taolun.md index c0b838b..8bc970a 100644 --- a/taolun.md +++ b/taolun.md @@ -205,4 +205,180 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 3. 换行控制: - "思考完成." 后需要两个换行符(一个换行 + 一个空行) - - 流式输出完成后也需要空行分隔 \ No newline at end of file + - 流式输出完成后也需要空行分隔 + +--- + +### 13. 重绘残留问题与新流程 + +#### 问题描述 + +之前的流程: +1. 流式实时打印 token(边收边打) +2. 完成后 Markdown 重绘 +3. 问题:重绘有残留 + +#### 解决方案:等待完整响应后输出 + +改进后的流程: +1. AI 返回完整数据 ← 等待时间 +2. Markdown 转译 +3. 模拟流式输出(从配置读取速度) + +效果更好,无残留问题。 + +#### 配置化 + +使用 `project.config.yml` 统一管理配置: +```yaml +streaming: + line_delay_ms: 1000 # 每行输出后的延迟(毫秒) + last_line_delay_ms: 600 # 最后一行延迟(毫秒) + +markdown: + glamour_style: dark + wrap_width: 0 # 自动获取终端宽度 + +ui: + logo: "🦐" + user_prefix: "👀 " # 用户输入前缀 +``` + +--- + +### 14. 按行延迟输出的实现 + +#### 核心逻辑 + +```go +func outputLineByLine(text string) { + lines := strings.Split(text, "\n") + totalLines := len(lines) + + cfg := internal.GetProjectConfig() + lineDelay := time.Duration(cfg.Streaming.LineDelayMs) * time.Millisecond + lastLineDelay := time.Duration(cfg.Streaming.LastLineDelayMs) * time.Millisecond + + for i, line := range lines { + if line == "" { + fmt.Println() + continue + } + fmt.Println(line) + + if i < totalLines-1 { + time.Sleep(lineDelay) + } else { + time.Sleep(lastLineDelay) + } + } + fmt.Println() +} +``` + +特点: +- 空行直接跳过 +- 每行输出后延迟可配置 +- 最后一行延迟可单独配置 + +--- + +### 15. 工具调用结果显示问题 + +#### 问题 + +使用 `ChatStream` 时,工具调用结果不显示。 + +#### 原因分析 + +1. 工具调用结果不在流式响应中返回,而是通过 `bus.PublishOutbound()` 单独发送 +2. `ChatStream` 的 `onChunk` 回调只处理文本内容,不处理工具调用 +3. 工具调用在 `runTurn` 循环中执行,结果通过消息总线发送 + +#### 解决方案 + +回退使用 `ProcessDirect`,因为它会正确处理: +- 工具调用流程 +- 工具结果显示 +- Markdown 渲染和按行输出 + +--- + +### 16. 状态栏优化 + +#### 改动内容 + +- 图标:`▣` +- 图标颜色:`#f0c75e` +- 文字颜色:`#2b2e32` +- 内容:只显示耗时,如 `▣ 耗时: 2.3s` + +#### 之前 vs 之后 + +- 之前:`▣ Tokens: 120 · 耗时: 2.3s · 总Tokens: 350` +- 之后:`▣ 耗时: 2.3s` + +--- + +### 17. 项目配置文件详解 + +#### project.config.yml 结构 + +```yaml +# hxclaw 项目配置文件 + +# 模拟流式输出配置 +streaming: + line_delay_ms: 1000 # 每行输出后的延迟(毫秒) + last_line_delay_ms: 600 # 最后一行延迟(毫秒) + +# Markdown 渲染配置 +markdown: + glamour_style: dark # 渲染主题:dark, light, dracula, tokyo-night 等 + wrap_width: 0 # 自动换行宽度(0=自动获取终端宽度) + +# UI 配置 +ui: + logo: "🦐" # Logo + user_prefix: "👀 " # 用户输入前缀 +``` + +#### 配置加载优先级 + +1. 环境变量 `HXCLAW_CONFIG` 指定路径 +2. 项目根目录 `project.config.yml` + +#### 代码实现 + +```go +// internal/config.go +type ProjectConfig struct { + Streaming StreamingConfig `yaml:"streaming"` + Markdown MarkdownConfig `yaml:"markdown"` + UI UIConfig `yaml:"ui"` +} + +func getConfigPath() string { + if path := os.Getenv("HXCLAW_CONFIG"); path != "" { + return path + } + return filepath.Join(".", "project.config.yml") +} +``` + +--- + +### 18. 行业经验参考 + +#### CLI 动画最佳实践 + +- 帧率:75ms/帧(约 13fps)- GitHub Copilot CLI +- Spinner 动画:70-120ms - ora 库 +- AI 流式输出:30-80ms/字符或行 +- 总动画时长:控制在 3 秒内 - Copilot CLI 原则 + +#### 关键结论 + +- 人眼需要约 30-50ms 才能感知单次视觉变化 +- 空白字符不应逐个输出,应批量处理 +- 终端宽度 100% 时 Markdown 渲染会显著增加行数和字符数 \ No newline at end of file