116 lines
2.1 KiB
Go
116 lines
2.1 KiB
Go
package tui
|
|
|
|
import (
|
|
"time"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/voocel/ainovel-cli/app"
|
|
)
|
|
|
|
// 消息类型
|
|
type (
|
|
eventMsg app.UIEvent
|
|
snapshotMsg app.UISnapshot
|
|
doneMsg struct{}
|
|
askUserMsg askUserRequest
|
|
startResultMsg struct{ err error }
|
|
steerResultMsg struct{}
|
|
spinnerTickMsg time.Time
|
|
streamDeltaMsg string // 流式 token 增量
|
|
streamClearMsg struct{} // 清空流式缓冲(新消息开始)
|
|
)
|
|
|
|
// --- Cmd 函数 ---
|
|
|
|
func listenEvents(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
ev, ok := <-rt.Events()
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return eventMsg(ev)
|
|
}
|
|
}
|
|
|
|
func listenDone(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
<-rt.Done()
|
|
return doneMsg{}
|
|
}
|
|
}
|
|
|
|
func tickSnapshot(rt *app.Runtime) tea.Cmd {
|
|
return tea.Tick(3*time.Second, func(t time.Time) tea.Msg {
|
|
return snapshotMsg(rt.Snapshot())
|
|
})
|
|
}
|
|
|
|
func fetchSnapshot(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
return snapshotMsg(rt.Snapshot())
|
|
}
|
|
}
|
|
|
|
func checkResume(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
label, err := rt.Resume()
|
|
if err != nil {
|
|
return startResultMsg{err: err}
|
|
}
|
|
if label != "" {
|
|
return startResultMsg{err: nil}
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func startRuntime(rt *app.Runtime, prompt string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := rt.Start(prompt)
|
|
return startResultMsg{err: err}
|
|
}
|
|
}
|
|
|
|
func steerRuntime(rt *app.Runtime, text string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
rt.Steer(text)
|
|
return steerResultMsg{}
|
|
}
|
|
}
|
|
|
|
func tickSpinner() tea.Cmd {
|
|
return tea.Tick(350*time.Millisecond, func(t time.Time) tea.Msg {
|
|
return spinnerTickMsg(t)
|
|
})
|
|
}
|
|
|
|
func listenStream(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
delta, ok := <-rt.Stream()
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return streamDeltaMsg(delta)
|
|
}
|
|
}
|
|
|
|
func listenStreamClear(rt *app.Runtime) tea.Cmd {
|
|
return func() tea.Msg {
|
|
_, ok := <-rt.StreamClear()
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return streamClearMsg{}
|
|
}
|
|
}
|
|
|
|
func listenAskUser(bridge *askUserBridge) tea.Cmd {
|
|
return func() tea.Msg {
|
|
req, ok := <-bridge.requests
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return askUserMsg(req)
|
|
}
|
|
}
|