3 Commits
v0.3.1 ... main

Author SHA1 Message Date
5494a296d9 docs: 更新文档记录 v0.2.7 升级和 /context 命令
- agents.md: 添加上下文监控功能说明和输出示例
- changelog.md: 新增 v0.3.1 版本记录
- 更新目前进度列表
2026-05-03 02:45:22 +08:00
532466c343 feat: 添加 /context 命令显示会话上下文使用情况
- 集成 picoclaw v0.2.7 的上下文统计功能
- 显示消息数、token 使用量、压缩阈值和剩余空间
- 在 interactiveMode 和 simpleInteractiveMode 中均支持
2026-05-03 02:43:27 +08:00
e3f902d25d chore: 升级 picoclaw 依赖至 v0.2.7
- 更新 github.com/sipeed/picoclaw v0.2.6 → v0.2.7
- 配置版本从 v2 升级至 v3
- 同步更新相关间接依赖(golang.org/x/*, modernc.org/sqlite 等)
2026-05-03 02:05:13 +08:00
5 changed files with 150 additions and 35 deletions

View File

@@ -53,33 +53,6 @@
## 实现进度
### v0.2.0 已完成功能
1. **TTS 语音朗读**
- 集成 mimo-tts clientTCP 连接)
- 配置文件开关tts.enabled
- 命令行切换(/tts on/off/status
- 临时 TTS 前缀(`T 消息`
- 动态提示符显示状态(👀 🔊)
- 静默失败处理(网络异常时仅记录日志)
2. **流式输出(新流程)**
- 等待 AI 返回完整响应
- Markdown 转译
- 模拟流式输出(从配置读取速度)
- 效果更好,无残留问题
3. **Markdown 渲染**
- 使用 glamour 库渲染 Markdown
- 支持多种主题dark, light, dracula, tokyo-night 等)
- 通过 project.config.yml 配置主题
4. **项目配置**
- 通过 project.config.yml 统一管理配置项
- 支持流式速度、渲染主题、Logo、TTS 等配置
---
### v0.3.0 进度
1. **数据库层**
@@ -117,6 +90,11 @@
- 退出时自动导出
- 手动导出
8. **上下文监控**
- 新增 `/context` 命令
- 显示会话 token 使用情况
- 显示压缩阈值和剩余空间
---
## 项目配置
@@ -210,6 +188,22 @@ tts:
| `/tts status` | 显示 TTS 状态 |
| `T 消息` | 临时开启 TTS 并发送消息 |
### 上下文监控
| 输入 | 行为 |
|------|------|
| `/context` | 显示当前会话 token 使用情况 |
输出示例:
```
上下文使用情况
消息数: 2
已用: ~5663 / 131072 tokens (5%)
压缩阈值: 98304 tokens
压缩进度: 5%
剩余: ~92641 tokens
```
### 动态提示符
- 关闭:`👀 `

View File

@@ -2,6 +2,20 @@
## 版本记录
### v0.3.1 (2026-05-03)
- **升级 picoclaw 至 v0.2.7**
- 配置版本从 v2 升级至 v3
- 适配配置结构变更Bindings → Dispatch, channels → channel_list
- 同步更新相关间接依赖
- **新增 `/context` 命令**
- 显示当前会话上下文窗口使用情况
- 包含消息数、token 使用量、压缩阈值和剩余空间
- 在 interactiveMode 和 simpleInteractiveMode 中均支持
---
### v0.3.0 (2026-04-27)
- **Session 创建逻辑优化**
@@ -153,6 +167,8 @@
- [x] UI 状态合并显示
- [x] LLM 生成摘要(文言文风格)
- [x] Session 自动创建逻辑
- [x] 升级 picoclaw 至 v0.2.7
- [x] 实现 `/context` 命令
---

View File

@@ -156,6 +156,11 @@ func interactiveMode(agentLoop *agent.AgentLoop, sessionKey string) {
continue
}
if strings.HasPrefix(input, "/context") {
handleContextCommand(agentLoop, sessionKey)
continue
}
if isTempTTS {
enabled := internal.ToggleTTS()
if enabled {
@@ -224,6 +229,11 @@ func simpleInteractiveMode(agentLoop *agent.AgentLoop, sessionKey string) {
continue
}
if strings.HasPrefix(input, "/context") {
handleContextCommand(agentLoop, sessionKey)
continue
}
if isTempTTS {
internal.ToggleTTS()
}
@@ -513,3 +523,80 @@ func handleSessionsCommand() {
fmt.Printf(" %s | %d 条消息 | %s\n", s.UUID[:8], len(s.ChatIDs), summary)
}
}
func handleContextCommand(agentLoop *agent.AgentLoop, sessionKey string) {
if agentLoop == nil {
fmt.Println("无法获取上下文信息")
return
}
cfg := agentLoop.GetConfig()
if cfg == nil {
fmt.Println("无法获取配置信息")
return
}
registry := agentLoop.GetRegistry()
if registry == nil {
fmt.Println("无法获取代理注册信息")
return
}
instance := registry.GetDefaultAgent()
if instance == nil {
fmt.Println("无可用代理")
return
}
contextWindow := instance.ContextWindow
if contextWindow <= 0 {
fmt.Println("上下文窗口大小未知")
return
}
history := instance.Sessions.GetHistory(sessionKey)
historyTokens := 0
for _, m := range history {
historyTokens += agent.EstimateMessageTokens(m)
}
systemTokens := 0
if instance.ContextBuilder != nil {
summary := instance.Sessions.GetSummary(sessionKey)
systemTokens = instance.ContextBuilder.EstimateSystemTokens(summary, nil)
}
toolTokens := 0
if instance.Tools != nil {
toolDefs := instance.Tools.ToProviderDefs()
toolTokens = agent.EstimateToolDefsTokens(toolDefs)
}
usedTokens := historyTokens + systemTokens + toolTokens
effectiveWindow := contextWindow - instance.MaxTokens
if effectiveWindow < 0 {
effectiveWindow = contextWindow
}
compressAt := effectiveWindow
usedPercent := 0
if compressAt > 0 {
usedPercent = usedTokens * 100 / compressAt
}
if usedPercent > 100 {
usedPercent = 100
}
remaining := compressAt - usedTokens
if remaining < 0 {
remaining = 0
}
fmt.Println("上下文使用情况")
fmt.Printf("消息数: %d\n", len(history))
fmt.Printf("已用: ~%d / %d tokens (%d%%)\n", usedTokens, contextWindow, usedPercent)
fmt.Printf("压缩阈值: %d tokens\n", compressAt)
fmt.Printf("压缩进度: %d%%\n", usedPercent)
fmt.Printf("剩余: ~%d tokens\n", remaining)
}

16
go.mod
View File

@@ -10,7 +10,7 @@ require (
github.com/ergochat/readline v0.1.3
github.com/google/uuid v1.6.0
github.com/muesli/termenv v0.16.0
github.com/sipeed/picoclaw v0.2.6
github.com/sipeed/picoclaw v0.2.7
github.com/tursodatabase/libsql-client-go v0.0.0-00010101000000-000000000000
gopkg.in/yaml.v3 v3.0.1
)
@@ -58,7 +58,7 @@ require (
github.com/github/copilot-sdk/go v0.2.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab // indirect
github.com/gomarkdown/markdown v0.0.0-20260411013819-759bbc3e3207 // indirect
github.com/google/jsonschema-go v0.4.2 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/h2non/filetype v1.1.3 // indirect
@@ -91,17 +91,17 @@ require (
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
golang.org/x/net v0.52.0 // indirect
golang.org/x/crypto v0.50.0 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/term v0.41.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/term v0.42.0 // indirect
golang.org/x/text v0.36.0 // indirect
golang.org/x/time v0.15.0 // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.48.0 // indirect
modernc.org/sqlite v1.48.2 // indirect
)

18
go.sum
View File

@@ -103,6 +103,8 @@ github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63Y
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab h1:VYNivV7P8IRHUam2swVUNkhIdp0LRRFKe4hXNnoZKTc=
github.com/gomarkdown/markdown v0.0.0-20260217112301-37c66b85d6ab/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/gomarkdown/markdown v0.0.0-20260411013819-759bbc3e3207 h1:p7t34F7K4OCRQblcDhNJnP46Uaarz3z2cLcvOZYxWn8=
github.com/gomarkdown/markdown v0.0.0-20260411013819-759bbc3e3207/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
@@ -165,6 +167,8 @@ github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfv
github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
github.com/sipeed/picoclaw v0.2.6 h1:MqV6hidBW2WVPqE+nmIkjO3sJI/ng0nrAyFDJVHUOBg=
github.com/sipeed/picoclaw v0.2.6/go.mod h1:gl9BuZhxUIvrJM1oQXw4Xa8wlmarGGz1y1z6XdcMu3Y=
github.com/sipeed/picoclaw v0.2.7 h1:x5ER0dI36BsOlY9EgjWna+Wyha+wtEb33RDaI8lfBvQ=
github.com/sipeed/picoclaw v0.2.7/go.mod h1:SaynnnhxN0+Ze9LCyrZcxmMO3IjVE76IgSEidPVwSB8=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@@ -197,12 +201,19 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
@@ -212,12 +223,17 @@ golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -249,6 +265,8 @@ modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.48.0 h1:ElZyLop3Q2mHYk5IFPPXADejZrlHu7APbpB0sF78bq4=
modernc.org/sqlite v1.48.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
modernc.org/sqlite v1.48.2 h1:5CnW4uP8joZtA0LedVqLbZV5GD7F/0x91AXeSyjoh5c=
modernc.org/sqlite v1.48.2/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=