# pi-typeless-input

对 Typeless 语音转文字输入做去抖合并的 pi 扩展。

## 问题背景

我是 pi 和 Typeless 的重度用户。pi 是终端里的 AI 编码助手，Typeless 是语音转文字工具——两者各自都是非常出色的生产力工具。

麻烦出现在把手机也拉进这个组合之后。

想象这个场景：躺在沙发上，用手机的 Termius SSH 到服务器，tmux 里跑着 pi TUI。打字不方便，于是打开 Typeless 语音输入，对着手机说了一段话。

然后噩梦开始了。

你的一段话噼里啪啦变成了五六条独立消息。agent 被第一句没头没尾的话触发，后面的段落又各自为战，场面一片混乱。

更隐蔽的是另一种情况：如果语音识别出的最后一段文本**末尾没有 `\n`**，这段文字既不会触发发送，也不会被合并进来——它就静静躺在编辑器里，等你发现时，前面的内容早就发出去了。

### 这是谁的锅？

严格来说，谁都没有错。

pi 的 TUI 里 Enter 就是"发送"，这是明确的、正确的交互设计，不是 bug。Typeless 把语音转成分段的、带换行符的文本，也是它该做的正确行为。

问题出在**手机 SSH 客户端的粘贴行为**上。桌面终端（比如 iTerm）收到粘贴内容时，会把它原样塞进编辑器，不会因为里面有 `\n` 就逐行触发 Enter。而手机 SSH 客户端（比如 Termius）粘贴时，会把内容里的每个换行符当成一次真实的 Enter 按键——对 pi 的 TUI 来说，这等于连按了好几次"发送"。

所以真正的缺口在**移动端 SSH 链路**这一环：桌面链路上的这些行为各自都对，但组合起来没人负责，在手机上就露出了缝隙。

这个扩展就是来补这个缺口的。它从 pi 端做补救，让手机上的语音输入也能像在桌面上一样流畅。

## 解决方案

本扩展的思路很简单：粘贴进来的多段文本会在极短时间内连续到达，那就等它们都到齐了再处理。

- **300ms 去抖**：把连续到达的多段输入攒在一起。
- **合并多段**：拼回一条完整的消息。
- **捕获编辑器尾部**：把那段没有 `\n`、留在编辑器里的最后一段也捞出来，一起合并。
- **放回编辑器**：合并结果不直接发送，而是放回编辑器，让你审阅一遍，确认无误后按 Enter 发出。

最终效果：不管语音转文字的输出带不带末尾换行符，你说的所有段落都能合并成一条消息，不会再被拆得七零八落。

具体行为：

- **单行输入**：自动发出，几乎无感知。
- **多行输入**：合并后放回编辑器，由用户确认后按 Enter 发送。
- **末尾没有换行符的行**：自动从编辑器捕获合并，不会丢失。

## 安装

```bash
pi install npm:pi-typeless-input
```

或通过 git 安装：

```bash
pi install git:github.com/wolido/pi-typeless-input
```

## 本地试用

```bash
pi -e /home/ecs-user/pi-workspace/pi-typeless-input/extensions/voice-merge.ts
```

## 工作原理

扩展监听 `input` 事件，对 300ms 窗口内连续到达的输入做去抖合并：

1. 仅 TUI 模式下生效（不影响子 agent 等 print 模式）
2. 单行 → `sendUserMessage` 自动发出，agent 忙碌时转为 followUp
3. 多行 → 读取编辑器尾部内容（捕获无 `\n` 的行），合并后 `setEditorText` 放回编辑器

## 配置

当前去抖窗口为 `DEBOUNCE_MS = 300`（毫秒），如需调整请 fork 后修改 `extensions/voice-merge.ts`。

## 依赖

- `@earendil-works/pi-coding-agent`（peer dependency）

## 许可证

MIT © wolido
