mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-08-03 09:48:31 +08:00
When classify_inline_comments is enabled, create_inline_comment buffers calls without confirmed=true. The model frequently re-issues the call with confirmed=true after reading the buffered reply, which posts the comment live but leaves the original buffered entry behind. The post-session replay step then posts it again, so every inline comment lands twice. Reconcile the buffer on a live post: after a confirmed comment is created, remove any buffered entry matching the same path, line, startLine and body so it cannot be replayed. Extracts the reconciliation into src/mcp/inline-comment-buffer.ts (the MCP server module starts a server on import) and adds unit tests. Co-authored-by: archievi <13202986+archievi@users.noreply.github.com>
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
|
|
export type BufferedCommentMatch = {
|
|
path: string;
|
|
line?: number;
|
|
startLine?: number;
|
|
body: string;
|
|
};
|
|
|
|
/**
|
|
* Remove any buffered inline comment that matches an already-posted comment.
|
|
*
|
|
* When a comment is posted live (confirmed=true), an earlier buffered copy of
|
|
* the same comment must be dropped so the post-session replay step does not
|
|
* post it a second time. The model frequently re-issues a buffered call with
|
|
* confirmed=true after reading the "Set confirmed=true to post immediately"
|
|
* reply; previously the original buffered entry was left behind and replayed,
|
|
* producing duplicate inline comments.
|
|
*
|
|
* Entries are matched on path, line, startLine and body. Lines that cannot be
|
|
* parsed are kept untouched.
|
|
*/
|
|
export function removeBufferedComment(
|
|
match: BufferedCommentMatch,
|
|
bufferPath: string,
|
|
): void {
|
|
if (!existsSync(bufferPath)) {
|
|
return;
|
|
}
|
|
|
|
const remaining = readFileSync(bufferPath, "utf8")
|
|
.split("\n")
|
|
.filter((line) => line.trim() !== "")
|
|
.filter((line) => {
|
|
let entry: BufferedCommentMatch;
|
|
try {
|
|
entry = JSON.parse(line);
|
|
} catch {
|
|
// Keep anything we cannot parse rather than silently dropping it.
|
|
return true;
|
|
}
|
|
const isSameComment =
|
|
entry.path === match.path &&
|
|
entry.line === match.line &&
|
|
entry.startLine === match.startLine &&
|
|
entry.body === match.body;
|
|
return !isSameComment;
|
|
});
|
|
|
|
writeFileSync(
|
|
bufferPath,
|
|
remaining.length > 0 ? remaining.join("\n") + "\n" : "",
|
|
);
|
|
}
|