Skip to content

[Bug] Windows 10 Edit 工具总是失败 #1217

Description

@v7deep

What happened? / 问题描述

不清楚算不算bug, 但确实很难受,Edit 工具总是失败。我是用的模型是 Claude Opus 5.5
Image

Steps to reproduce / 复现步骤

编辑文件时,经常会失败,并且是频繁的失败

Expected behavior / 预期行为

因为能正常编辑,而不是一直失败

Actual behavior / 实际行为

不清楚算不算bug, 但确实很难受,Edit 工具总是失败。我是用的模型是 Claude Opus 5.5
Image

App version / 应用版本

0.15.10

Operating system / 操作系统

Windows

Extra environment / 其他环境信息

PI-Desktop 0.15.10 · win32 x64 · protocol 11 · host 0.15.10

Logs / 日志

completed","sessionId":"58a54d6b-54e1-48ac-b5c6-9ab4afe60c97","turnId":"fdd70a87-e164-4ac5-b45c-f8373dc40b28","toolCallId":"toolu_bdrk_013H26opPXGr2DYofdjZXMi6","data":{"toolName":"Read","outcome":"success","durationMs":2011,"result":{"type":"object","fields":["content","details","isError"],"fieldCount":3,"isError":false,"contentBlocks":1,"detailFields":["content","fileBytes","lineCount","notice","offset","path","root","tag","totalLines","truncated"]}}}
{"ts":"2026-09-29T08:05:31.454Z","level":"error","channel":"app","category":"tool","event":"tool.execution.failed","message":"tool execution failed","sessionId":"58a54d6b-54e1-48ac-b5c6-9ab4afe60c97","turnId":"fdd70a87-e164-4ac5-b45c-f8373dc40b28","toolCallId":"toolu_bdrk_01QUYqdG5keM8FsVd632GkT9","data":{"toolName":"Edit","outcome":"error","durationMs":1,"result":{"type":"object","fields":["content","details"],"fieldCount":2,"contentBlocks":1,"detailFields":[]}}}
{"ts":"2026-09-29T08:05:49.500Z","level":"error","channel":"app","category":"tool","event":"tool.execution.failed","message":"tool execution failed","sessionId":"58a54d6b-54e1-48ac-b5c6-9ab4afe60c97","turnId":"fdd70a87-e164-4ac5-b45c-f8373dc40b28","toolCallId":"toolu_bdrk_0172atYTHmrJrLignkLtQ6oR","data":{"toolName":"Edit","outcome":"error","durationMs":1,"result":{"type":"object","fields":["content","details"],"fieldCount":2,"contentBlocks":1,"detailFields":[]}}}

Screenshots / 截图

No response

Activity

  1. v7deep commented on Sep 30, 2026

    @v7deep
    Author

    这是使用AI分析出来的结果: (我觉得不太适合直接PR,给维护者一个参考吧)

    Image
    *** Begin Patch
    *** Update File: crates/host-core/src/tools/mod.rs
    @@
     fn tool_edit(
    @@
     ) -> Result<Value, hashline::ToolError> {
    @@
    -    let tag = args.get("tag").and_then(|v| v.as_str()).ok_or_else(|| {
    -        hashline::ToolError::new(
    -            "EDIT_TAG_REQUIRED",
    -            "tag required; pass the 4-hex tag from the latest Read, Grep, Write, or Edit",
    -        )
    -    })?;
    -    let ops = args
    -        .get("ops")
    -        .and_then(|v| v.as_str())
    -        .ok_or_else(|| hashline::ToolError::new("INVALID_ARGUMENT", "ops required"))?;
    +    // Claude and a few OpenAI-compatible clients still emit the legacy
    +    // old_string/new_string shape despite receiving the line-anchored schema.
    +    // Adapt that shape at the boundary so a stale client cannot turn every
    +    // Edit into an opaque INVALID_ARGUMENT. The live file is still passed
    +    // through apply_edit below, so the normal hashline write/review path is
    +    // preserved.
    +    let legacy_old = args.get("old_string").and_then(Value::as_str);
    +    let legacy_new = args.get("new_string").and_then(Value::as_str);
    +    let live_for_legacy = if legacy_old.is_some() || legacy_new.is_some() {
    +        Some(std::fs::read(&resolved).map_err(|e| {
    +            if e.kind() == std::io::ErrorKind::NotFound {
    +                hashline::ToolError::new("FILE_NOT_FOUND", format!("File not found: {path}"))
    +            } else {
    +                hashline::ToolError::new("TOOL_FAILED", format!("read failed: {e}"))
    +            }
    +        })?)
    +    } else {
    +        None
    +    };
    +    let (tag, ops) = match (
    +        args.get("tag").and_then(Value::as_str),
    +        args.get("ops").and_then(Value::as_str),
    +        legacy_old,
    +        legacy_new,
    +        live_for_legacy.as_deref(),
    +    ) {
    +        (Some(tag), Some(ops), _, _, _) => (tag.to_string(), ops.to_string()),
    +        (None, None, Some(old), Some(new), Some(bytes)) => {
    +            let file = hashline::normalize_file(bytes);
    +            let tag = hashline::tag_of_lf_text(&file.text);
    +            let matches: Vec<_> = file
    +                .text
    +                .match_indices(old)
    +                .map(|(start, _)| start)
    +                .collect();
    +            if matches.len() != 1 {
    +                return Err(hashline::ToolError::new(
    +                    "EDIT_LEGACY_MATCH_FAILED",
    +                    format!("old_string must match exactly once; found {} matches", matches.len()),
    +                ));
    +            }
    +            let start = matches[0];
    +            let first_line = file.text[..start].bytes().filter(|b| *b == b'\n').count() + 1;
    +            let old_lines = old.lines().count().max(1);
    +            let mut ops = format!("PUT {first_line}.={}:\n", first_line + old_lines - 1);
    +            for line in new.split('\n') {
    +                ops.push('+');
    +                ops.push_str(line);
    +                ops.push('\n');
    +            }
    +            (tag, ops)
    +        }
    +        (None, _, _, _, _) => {
    +            return Err(hashline::ToolError::new(
    +                "EDIT_TAG_REQUIRED",
    +                "tag required; pass the 4-hex tag from the latest Read, Grep, Write, or Edit",
    +            ));
    +        }
    +        (_, None, _, _, _) => {
    +            return Err(hashline::ToolError::new("INVALID_ARGUMENT", "ops required"));
    +        }
    +        _ => {
    +            return Err(hashline::ToolError::new(
    +                "INVALID_ARGUMENT",
    +                "Edit requires either path/tag/ops or path/old_string/new_string",
    +            ));
    +        }
    +    };
    @@
    -        tag,
    -        ops,
    +        &tag,
    +        &ops,
    *** End Patch
    
  2. added a commit that references this issue on Oct 1, 2026
    ecaf4c6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions