internal/repl/repl.go 实现交互式 REPL,对标 TypeScript src/screens/REPL.tsx 的非 UI 逻辑部分。

配置结构

type Config struct {
    Client        *api.Client
    Model         string
    SystemPrompt  string   // 覆盖默认 system prompt
    MaxTurns      int
    PermMode      string
    Printer       *output.Printer
    InitialPrompt string   // 启动时自动执行的初始 prompt
}

两种运行方式

Run()(交互模式)

持续读取 stdin,逐行处理,直到 EOF(Ctrl+D)或 Ctrl+C:

printWelcome()
if InitialPrompt != "" → handleInput(InitialPrompt)
loop:
    scanner.Scan()
    handleInput(line)

维护 r.messages []api.MessageParam 跨轮次对话历史。

RunOnce()(print 模式)

单次执行,用于 --print 参数:

  • 添加用户消息到 messages
  • engine.Run() 执行
  • 打印结果
  • 返回

输入分发逻辑

handleInput() 按优先级分发:

输入格式处理方式
! <cmd>直接执行 shell 命令(runBashCommand),不走 LLM
/help, /exit, /clear 等slash 命令(commands.Dispatch)
其他文本追加到 messages,走 LLM 查询

特殊 slash 命令返回值

commands.Dispatch 返回特殊字符串触发 REPL 行为:

返回值效果
\x00CLEAR_HISTORY清空对话历史
\x00EXIT退出 REPL
\x00COMPACT触发 compact(当前返回”未实现”)

流式输出

在交互模式下,文本通过 OnTextDelta 回调实时打印,thinking 内容用 dim gray 颜色区分(ANSI \033[2m):

OnTextDelta: func(delta string) { fmt.Print(delta) },
OnThinkingDelta: func(delta string) {
    fmt.Print("\033[2m" + delta + "\033[0m")
},

! 前缀 Shell 执行

任何以 ! 开头的输入直接通过 sh -c(Unix)或 cmd /C(Windows)执行,stdin/stdout/stderr 直传终端,不进入 LLM。

相关页面