Repository navigation
【BUG】heredoc / 单行命令含 ! 会导致整个命令行挂死 #10636
Replies: 1 comment
|
This is fixed on master, and the fix is not in rc.3. Commit Your layer 1 is unchanged: Two details from your report I would keep verbatim, because they are what makes it diagnosable: the marker |
Uh oh!
There was an error while loading. Please reload this page.
调研闭环。以下是基于
deepseek-harness源码的系统性定位报告。Bug 报告:bash 工具遇
!字符挂死 300 秒一句话结论
命令投递层用 ANSI-C 引用(
$'...')包裹模型命令,但受控 shell 是交互式 bash(history expansion 默认开启),$'...'不像单引号那样豁免!——含!的整行被 bash 以event not found整行丢弃;丢弃后的提示符不带完成检测标记,工具层又没有对此状态的早退,三者叠加导致空转到 300s 超时。最小复现(已实证)
命令
printf 'p4-start %s p4-end\n' '!'被投递层包成(tool-bash-persistent/src/index.ts:82wrapCommand):喂给与生产完全同构的
bash --noprofile --norc -i(PS1=dsh>、PROMPT_COMMAND 发 OSC 133;D),输出逐字:START printf、
eval、END printf 全部未执行。三层根因
层 1|触发层:
quoteForBash的引用形式不防 history expansionpackages/shell/tool-bash-persistent/src/index.ts:74-78\和',唯独没处理!;--noprofile --norc -i启动(terminal-bash/src/config.ts:65)——交互模式,histexpand 默认开,初始化序列(index.ts:273 只有stty -echo)没关它;!后跟\'被当作事件标识符!\,查找失败 → 打印event not found→ 丢弃整行。bash 的历史扩展对单引号内字符豁免,对$'...'不豁免。层 2|放大层:丢弃行后的提示符缺少完成标记
packages/terminal/terminal-bash/src/index.ts:83-87、sanitize.ts:6\033]133;D;<exit>\007,sanitizer 只认这个 OSC 为 prompt;dsh>,之后的正常命令才带标记);session.tspollReadiness 的stdin_read分支(:567-571,要求 promptSeen && promptTextSeen)永不满足,只剩inferred_idle(:596)兜底结算。层 3|空转层:工具循环对
inferred_idle无早退packages/shell/tool-bash-persistent/src/index.ts:321-389inferred_idle不在任何返回分支里 → 每 25ms 空转一轮直到 300s deadline → 走 timeout 分支 →shells.reset()杀掉整个 shell。连锁效应(解释现场所有怪象)
set +H自救无效:跨调用的set +H被 timeout 后的 shell reset 抹掉;同行的set +H无效——expansion 发生在读行时,行内语句还没执行;dsh>:丢弃行后 bash 停在无标记提示符,后续调用/空轮产生的提示符文本进 scrollback;超时后partialOutput找不到 START 标记(整行被丢弃,START printf 也没跑),回退 scrollback 尾部 → 模型只看到一串dsh>,真正的错误消息event not found被 scrollback 上限截掉(LOST_PREFIX_MESSAGE正是现场看到的「beginning was dropped」)。修复方案(B、C 已复现验证通过)
quoteForBash改用传统单引号引用('…'+'\'')替代$'...'——历史扩展对单引号内容豁免stty -echo处)追加一条set +H,交互 shell 全程关闭 histexpand——agent 场景本就用不到它executeCommand循环对连续 N 轮inferred_idle且无输出增长加早退,报文识别event not found特征提示模型「命令行被 shell 丢弃,检查!字符」inferred_idle+ 前台=shell 本身即「回到提示符」建议:C 一行根治(B 作为纵深防御一起上,注意
$'...'换'...'需保留对\r/\n字面量的处理);D/E 让任何未来的「行被丢弃」类故障快速失败而非烧 300 秒。附注:本机 PATH 解析到
/bin/bash3.2.57(macOS 系统 bash),复现与生产行为一致;bash 5.x 上$'...'是否豁免!未在本机验证,修复不应依赖版本行为。All reactions