This commit is contained in:
178
taolun.md
178
taolun.md
@@ -205,4 +205,180 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
|
||||
3. 换行控制:
|
||||
- "思考完成." 后需要两个换行符(一个换行 + 一个空行)
|
||||
- 流式输出完成后也需要空行分隔
|
||||
- 流式输出完成后也需要空行分隔
|
||||
|
||||
---
|
||||
|
||||
### 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 渲染会显著增加行数和字符数
|
||||
Reference in New Issue
Block a user