Skip to content

fix(agent-core): refuse multi-line empty Edit deletions - #2511

Open
mangeshraut712 wants to merge 5 commits into
MoonshotAI:mainfrom
mangeshraut712:cursor/fix-edit-refuse-large-delete-7813
Open

mangeshraut712 wants to merge 5 commits into
MoonshotAI:mainfrom
mangeshraut712:cursor/fix-edit-refuse-large-delete-7813

Conversation

@mangeshraut712

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • pnpm exec vitest run test/tools/edit.test.ts in packages/agent-core (23 passed)
  • pnpm exec vitest run test/app/edit/tools/edit.test.ts in packages/agent-core-v2 (26 passed)

Fixes #2427

@changeset-bot

changeset-bot Bot commented Aug 1, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2ba98cb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 097b1774d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/agent-core-v2/src/app/edit/editService.ts Outdated
Comment thread packages/agent-core-v2/src/app/edit/editService.ts
@pkg-pr-new

pkg-pr-new Bot commented Aug 1, 2026 •

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@b2db743
npx https://pkg.pr.new/@moonshot-ai/kimi-code@b2db743

commit: b2db743

@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from 097b177 to eb224a2 Compare August 1, 2026 18:20
@mangeshraut712

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main and refreshed the agent-core-v2 inline tools_snapshot hashes for the new Edit allow_large_delete field (fixes the shard-2 snapshot mismatches).

CI is currently stuck in action_required (fork workflow re-approval after the force-push). A maintainer click on "Approve and run workflows" should unblock it — local edit + snapshot tests pass.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 380b0df96d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .changeset/edit-refuse-large-delete.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a17e3b9f8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/agent-core-v2/src/agent/tools/edit/edit.ts
@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from 2f08cd7 to 51cc962 Compare August 30, 2026 13:10
@mangeshraut712

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main — merge conflicts are gone. CI is waiting on Approve and run workflows from a maintainer (fork PR).

@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from c6652fd to 1a45ffa Compare September 2, 2026 05:34
@mangeshraut712

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main. Mergeability is MERGEABLE / UNSTABLE — GitHub still needs a maintainer to approve fork-PR workflows so CI can run.

@mangeshraut712

Copy link
Copy Markdown
Contributor Author

rebase it

@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch 2 times, most recently from 744fcd0 to 1ee01a3 Compare September 6, 2026 14:30
@mangeshraut712
mangeshraut712 force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from 1ee01a3 to 4aeab95 Compare September 6, 2026 14:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 403a94d376

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

export function isOversizedEmptyDeletion(oldString: string, newString: string): boolean {
return newString.trim().length === 0 && countEditLines(oldString) >= LARGE_DELETE_MIN_OLD_LINES;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require opt-in for cumulative replace_all deletions

When replace_all=true, this predicate considers only one occurrence of old_string. For example, a two-line string appearing twice passes the guard and both matches are erased with an empty new_string, deleting four lines without allow_large_delete=true. Both engine implementations have this behavior, so the guard should account for the matched occurrence count or total resulting deletion before permitting the edit.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed: replace_all empty deletes now pass the matched occurrence count into the guard. Multi-line old_strings still accumulate (linesPerMatch * count); a one-line token is not scaled into a multi-line span.

@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch 3 times, most recently from 8cc1aee to bf501f5 Compare September 16, 2026 05:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf501f5b79

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +78 to +80
if (input.allow_large_delete !== true && isOversizedEmptyDeletion(input.old_string, input.new_string)) {
return { ok: false, error: oversizedDeletionMessage(input.path) };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check for a match before refusing the deletion

When replace_all is false and a stale or mistyped old_string spans three or more lines with an empty new_string, this branch returns the large-deletion refusal before countOccurrences runs, even though nothing can be deleted. This suppresses the newly strengthened old_string not found recovery guidance and may prompt the model to retry with allow_large_delete=true instead of rereading; perform the existence and uniqueness checks before applying the deletion guard.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed: countOccurrences (and the uniqueness check) now run before the large-delete refusal, so a stale or duplicate multi-line old_string gets not-found / not-unique guidance instead of allow_large_delete.

Comment on lines +33 to +35
newString.trim().length === 0 &&
occurrenceCount > 0 &&
countEditLines(oldString) * occurrenceCount >= LARGE_DELETE_MIN_OLD_LINES

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid counting repeated single-line matches as multiple lines

For a replace_all deletion of a one-line token occurring at least three times—for example removing ", " from "a, b, c, d"—multiplying its one-line count by the occurrence count classifies the edit as a multi-line deletion. The tool documentation says the opt-in is for deleting a multi-line span, and the resulting error incorrectly says that old_string itself spans three or more lines, so ordinary single-line bulk removals are refused unless the model supplies a misleading override; determine the affected spans from actual line boundaries rather than treating every occurrence as another line.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed: the guard uses countEditLines(old_string) and only multiplies by occurrence count when that span is already multi-line. replace_all of a one-line token (including the , × N case) is allowed without allow_large_delete.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@mangeshraut712

Copy link
Copy Markdown
Contributor Author

Following up on the earlier rebases. This is mergeable and still needs a maintainer review: multi-line empty Edit deletions are refused. I will leave the branch as it is unless you want a change.

@mangeshraut712
mangeshraut712 force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from b1c9995 to b2db743 Compare September 29, 2026 11:08
Guard Edit against accidental +0/−N wipeouts when new_string is empty
across 3+ lines unless allow_large_delete is set. Strengthen the
old_string-not-found recovery guidance so the model rereads a large
enough region instead of looping short Reads (fixes MoonshotAI#2427).
Count matched occurrences when guarding empty replace_all edits so a
short old_string cannot delete 3+ lines without allow_large_delete.
Match and uniqueness checks run before refusing an empty deletion.
replace_all still accumulates multi-line matches, but a one-line token
is not treated as a multi-line span.
Re-record loop and tool inline snapshots so they include the post-rebase
tool list and allow_large_delete hashes.
@cursor
cursor Bot force-pushed the cursor/fix-edit-refuse-large-delete-7813 branch from b2db743 to 2ba98cb Compare September 30, 2026 08:44

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Edit 失败后陷入死循环:反复"Edit 失败 → 重读 → 再失败",并逐步删空了被编辑文件的多个章节

1 participant