修复: 缓存原子写与 fork 关系持久化,优化摘要重试

- 原子写: 新增 atomicWriteFile,缓存/收藏/forks 改为临时文件+rename,避免崩溃损坏
- fork 关系: executeFork 记录待绑定项,扫描后按 cwd+时间窗口匹配新会话并持久化
- 摘要重试: 去掉 needDetail 反复刷新逻辑,仅对未生成摘要的会话触发,避免浪费 claude -p 调用
- 脚本转义: pwsh/bash 的 Prompt 回显段转义双引号与 $,防止注入和语法错误
- 输入限制: 工作空间数字输入限制 4 位,避免无限增长
- 品牌统一: 底部版本号文案 绝尘 → U-TABS
This commit is contained in:
lxy
2026-07-01 01:29:01 +08:00
parent baec416df7
commit 45e32193af
6 changed files with 156 additions and 34 deletions
+17 -8
View File
@@ -5,7 +5,7 @@ import (
"os"
"time"
"charm.land/bubbletea/v2"
tea "charm.land/bubbletea/v2"
)
// Model 主模型
@@ -20,16 +20,17 @@ type Model struct {
history HistoryState
pendingCmd string
update UpdateState
wsFocus int // workspace 焦点列: 0=tabs 1=list
wsTabCur int // tabs 列光标 (0..len(Groups), 最后一个是历史入口)
forkMode bool // 分叉输入模式
wsFocus int // workspace 焦点列: 0=tabs 1=list
wsTabCur int // tabs 列光标 (0..len(Groups), 最后一个是历史入口)
forkMode bool // 分叉输入模式
forkBuf string // 分叉方向提示输入
// 性能缓存
allSessionsCache []*Session // "全部" tab 会话切片缓存
allSessionsDirty bool // 缓存是否需要重建
cacheDirty bool // session-cache.json 是否需要写盘
summaryCount int // 本次会话已生成的摘要数
allSessionsCache []*Session // "全部" tab 会话切片缓存
allSessionsDirty bool // 缓存是否需要重建
cacheDirty bool // session-cache.json 是否需要写盘
summaryCount int // 本次会话已生成的摘要数
pendingForks []pendingFork // executeFork 留下的待绑定项,扫描后解析
}
func NewModel() *Model {
@@ -76,6 +77,12 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
}
// 处理 executeFork 留下的待绑定 fork
if len(m.pendingForks) > 0 {
resolvePendingForks(m.pendingForks, m.history.Projects)
m.pendingForks = nil
m.cacheDirty = true
}
total := 0
for _, pd := range msg.Projects {
total += len(pd.Sessions)
@@ -114,6 +121,8 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
return m, nil
case tea.QuitMsg:
// 最终落盘:扫描未完成时 Cache 可能为 nil,此时无数据可写,
// 已生成的摘要会在下次启动扫描时由 cache 维护
m.flushCache()
return m, tea.Quit
}