feat(cosh-ng): [shell] route unresolved natural-language input to Agent#1742
feat(cosh-ng): [shell] route unresolved natural-language input to Agent#1742SunnyQjm wants to merge 1 commit into
Conversation
|
PR number: #1742 Findings
Structure Review
Remaining Risks / Not Run
Validation
|
3c9def1 to
57cf5f8
Compare
0bd89fd to
193b8ea
Compare
193b8ea to
fc9db9e
Compare
There was a problem hiding this comment.
- 捕获溢出/过期路径下仍累积并重放字节,可能泄露本应仅限卡片生命周期的输入。
- 自然语言路由关闭原始命令时对用户 missing 处理器的约定不够显式,难以区分失败与交给 Agent。
- capture 生命周期状态机较复杂,建议强化代际与 invalidated 不变式的系统化测试覆盖。
🤖 Generated by Qoder • View workflow run
kongche-jbw
left a comment
There was a problem hiding this comment.
审查当前 head fc9db9e 后发现 3 个需要处理的输入所有权与兼容性问题,详见行内评论。当前 CI 虽已通过,但相关测试没有阻止 capture-owned 字节进入 Shell,也未覆盖 UTF-8 字节上限和自然语言命中时的用户 missing handler。
|
|
||
| let replay = std::mem::take(quarantined_suffix); | ||
| if !replay.is_empty() { | ||
| relay_passthrough_input(&replay, relay)?; |
There was a problem hiding this comment.
[P1] 不要把 capture-owned 的剩余字节重放为 Shell 输入
quarantined_suffix 中的字节是在原 capture generation 仍持有输入时读取的;consume_split 遇到第一个提交/取消事件后留下的 remainder 也在其中。这里直接写回 PTY 会让粘贴到自由文本卡片的 answer\n<command>\n 在卡片结束后执行 <command>。overflow 测试甚至明确断言尾部 echo 会运行,因此 overflow/expiry 并没有 fail closed。
建议丢弃仍属于旧 generation 的 remainder;只有能够证明是在所有权切回 Shell 后读取的字节才允许重放。至少应增加多行粘贴不会触发 Shell 命令的回归测试。
| local han_status had_question=0 polite=0 | ||
| local IFS=$' \t\n' | ||
|
|
||
| if [[ -z "$original" || ${#original} -gt 4096 ]]; then |
There was a problem hiding this comment.
[P2] 这里检查的是字符数,不是 PR 声明的字节数
在 UTF-8 locale 下 ${#original} 返回字符数。例如 帮我 加 2000 个汉字是 2003 个字符、6007 字节,但仍会通过此检查并按 Han 规则直达 Agent,突破“超过 4096-byte 不保留、不直达”的边界。
请按字节长度检查(例如在明确的 LC_ALL=C 语义下计算),并补 4096 字节上下的多字节输入测试。
| return 127 | ||
| local intent | ||
| intent="$(_cosh_classify_missing "$original" "$command")" | ||
| if [[ "$intent" == "natural_language" && "${_COSH_AI_ENABLED:-1}" == 1 ]]; then |
There was a problem hiding this comment.
[P2] 自然语言分支绕过了用户的 command-not-found handler
当用户定义了 command_not_found_handle / command_not_found_handler 时,这里直接返回 0,用户 handler 的输出、副作用和返回码都不会发生;只有其他 intent 才走下面的 delegate。当前兼容性测试仅覆盖 terraform plan 这类 ambiguous 输入,没有覆盖 natural-language 命中。
如果目标是保留 native Shell contract,建议检测到用户 handler 时优先 delegate,或要求用户显式 opt-in 才允许 Cosh 绕过它;同时补一个 natural-language + 自定义 handler 的回归测试。
|
PR number: #1742 Findings
Structure Review未发现 blocking package/module/public API 组织问题。变更全部收敛在 Remaining Risks / Not Run
|
What changed
command-not-found.Who are youandJust do itdirectly to Agent without printingcommand not found.Why
The existing fallback could identify failed commands, but English natural-language prompts still leaked through as shell errors. Routing before Shell execution would avoid that error but could also intercept valid commands. This change lets Shell resolve real commands first, then handles only unresolved top-level input.
Related to #1666.
Routing strategy
flowchart TD A["User submits input"] --> B{"Explicit Cosh control?<br/>slash command or ??"} B -->|Yes| C["Handle control or Agent request directly"] B -->|No| D["Shell parses and executes input"] D --> E{"Proven top-level command miss?<br/>exit 127 and matching attempt"} E -->|No| F["Keep normal Shell result<br/>existing non-127 failure policy remains"] E -->|Yes| G{"Ownership and safety gates pass?"} G -->|No| H["Delegate to native or user command-not-found handler"] G -->|Yes| I["Classify the original input"] I --> J{"Command-shaped syntax?"} J -->|Yes| K["intent = command"] J -->|No| L{"Contains valid Han character?"} L -->|Yes| M["intent = natural_language"] L -->|Invalid UTF-8| N["intent = unsafe"] L -->|No| O{"Matches English language patterns?"} O -->|Yes| M O -->|No| P["intent = ambiguous"] M --> Q{"AI enabled?"} Q -->|Yes| R["Direct Agent<br/>suppress command-not-found"] Q -->|No| S["Keep command-not-found"] K --> T["Keep command-not-found<br/>record proven missing input"] N --> T P --> T S --> T T --> U{"Unique typo correction available?<br/>non-manual mode and intervention gates pass"} U -->|Yes| V["Shell rewrite ghost<br/>Tab to accept"] U -->|No| W["Generic Agent diagnosis ghost<br/>Tab to accept"]The classifier is never called for a command that Shell can resolve. Command correction is therefore not attempted for input already classified as natural language; for the remaining proven
command-not-foundcases, a unique correction wins over the generic Agent fallback.Natural-language rules
Rules are evaluated in this order:
command/env/sudo/exec/nohup/time/xargs, shell quoting or operators, control characters, option tokens, and assignmentscommand./script,review --all,review FOO=bar,review this | cat帮我看看当前目录,帮我看 ./日志Who are you,how file,can you check this,service not runningplease explain this,maybe check this,review ./report.log,restart the serviceJust do it,go ahead,try again,thank you,hello thereambiguousok,hello,thanks,just build,go test,kubectl get pods, emoji-only inputImportant boundaries:
review ./report.logand帮我看 ./日志can route directly; a path-like first token such as./scriptremains a command.natural_languageroutes directly only when AI is enabled.command,ambiguous,unsafe, and AI-disabled cases preserve the nativecommand-not-foundresult and can surface correction or Agent ghost suggestions afterward.Real Linux/bash PTY evidence
Who are youis sent directly to Agent without acommand not foundline:The Shell remains usable after Agent returns:
Validation
cargo test -p cosh-shell --lib raw_input:: -- --test-threads=1— 71 passedcargo clippy -p cosh-shell --all-targets -- -D warningscargo build -p cosh-shell --bin cosh-shellcargo fmt --all -- --check./crates/cosh-shell/scripts/check-layout.shgit diff --check