跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

Dual Output 双通道接入

保留终端交互,同时通过独立 JSONL 通道观察会话与接收外部输入。

Dual Output 给交互 TUI 增加机器可读的旁路。终端仍在 stdout 正常绘制,外部程序从独立通道读事件,并可通过另一个文件提交提示或审批决定。

它适合嵌入 IDE、Web 聊天面板、审计记录器和会话观察器。纯批处理先看无头输出;此处的重点是保留交互终端与同步事件流。

选择输出通道

参数用途与限制
--json-fd N向调用方已打开的描述符写事件;N 至少为 3
--json-file PATH向普通文件、FIFO 或 /dev/fd/N 写事件
--input-file PATH监听外部程序追加的 JSONL 命令;必须用普通文件

前两个输出参数互斥,同时传入会在 TUI 启动前被 CLI 拒绝。0、1、2 留给程序自身输入输出,不能用于旁路。

普通 Node child_process.spawn 可通过 stdio 数组传入 fd 3。node-pty、bun-pty 等嵌入方式不提供同样的额外 stdio 配置,使用 --json-file 更合适。不要仅把程序 stdout 重定向后再解析 ANSI 来还原对话。

用普通文件试接入

以下路径仅用于本机演示。正式嵌入为每个会话创建独立目录和文件;官方建议使用 XDG_RUNTIME_DIR 或权限为 0700 的临时目录,避免多个会话混用事件与审批通道。

touch /tmp/qwen-events.jsonl /tmp/qwen-input.jsonl
qwen --json-file /tmp/qwen-events.jsonl --input-file /tmp/qwen-input.jsonl

另一个终端观察事件:

tail -f /tmp/qwen-events.jsonl

再向输入文件追加一条完整记录:

echo '{"type":"submit","text":"Explain this repo"}' >> /tmp/qwen-input.jsonl

输入是追加日志,不应把输入文件当作只存“最新一条”的 JSON 对象。生产消费者也需要记录读取偏移并持续跟踪追加;一次普通文件 read stream 到达 EOF,不能替代长期 tail。

固定配置

{
  "dualOutput": {
    "jsonFile": "/tmp/qwen-events.jsonl",
    "inputFile": "/tmp/qwen-input.jsonl"
  }
}

CLI 路径优先于对应 settings 值。json-fd 没有持久设置项,因为描述符由本次父进程分配。配置需重启生效;没有参数或设置时,旁路默认关闭。

FIFO 的适用边界

FIFO 仅用于输出。input-file 的监听依赖 stat.size,FIFO 的该值通常为零,不能接收命令。

官方 FIFO 专节说明使用 O_RDWR | O_NONBLOCK,并在消费者迟迟不读取、管道或内部缓冲超限时关闭旁路;同页早段还保留了另一套 ENXIO 回退描述。接入时以当前实现和实际启动验证为准,不依赖这段冲突说明来保证所有平台的阻塞行为。

事件消费者断开造成 EPIPE、输出写入异常或缓冲超限会停用旁路,TUI 继续运行,不自动重连。内部缓冲超过约 1MB 是文档给出的关闭条件之一,不能把 FIFO 当作无限排队缓存。无效 fd 或无法打开输出路径也会警告后继续运行 TUI。

下一步

事件握手、权限决策与关闭判定见Dual Output 协议。结构化通道包含实际对话与工具结果,应按会话数据处理;可写输入通道还具备提交消息和批准工具的能力。