fix(coding-agent): replaced JSON string equality checks with deep equality

- Changed provider delta input comparisons in `buildResponsesDeltaInput` to use `Bun.deepEquals` instead of stringified JSON checks.
- Updated session message diffing to return early on length changes and compare normalized entries with deep equality.
- Replaced JSON-string assertions in the issue-966 repro test with `Bun.deepEquals` for stable equality checks.
This commit is contained in:
can1357
2026-06-17 13:45:11 +02:00
parent 0d9ec354e7
commit af6e83a651
4 changed files with 14 additions and 12 deletions
@@ -1240,13 +1240,13 @@ export function buildResponsesDeltaInput<TItem>(
if (!Array.isArray(previous.input) || !Array.isArray(current.input)) return null;
const previousWithoutInput = { ...previous, input: undefined, client_metadata: undefined };
const currentWithoutInput = { ...current, input: undefined, client_metadata: undefined };
if (JSON.stringify(previousWithoutInput) !== JSON.stringify(currentWithoutInput)) {
if (!Bun.deepEquals(previousWithoutInput, currentWithoutInput)) {
return null;
}
const baseline = [...previous.input, ...(previousResponseItems ?? [])];
if (current.input.length <= baseline.length) return null;
for (let index = 0; index < baseline.length; index += 1) {
if (JSON.stringify(baseline[index]) !== JSON.stringify(current.input[index])) {
if (!Bun.deepEquals(baseline[index], current.input[index])) {
return null;
}
}
@@ -8709,9 +8709,13 @@ export class AgentSession {
}
#didSessionMessagesChange(previousMessages: AgentMessage[], nextMessages: AgentMessage[]): boolean {
return (
JSON.stringify(previousMessages.map(message => this.#normalizeSessionMessageForProviderReplay(message))) !==
JSON.stringify(nextMessages.map(message => this.#normalizeSessionMessageForProviderReplay(message)))
if (previousMessages.length !== nextMessages.length) return true;
return previousMessages.some(
(message, i) =>
!Bun.deepEquals(
this.#normalizeSessionMessageForProviderReplay(message),
this.#normalizeSessionMessageForProviderReplay(nextMessages[i]),
),
);
}
@@ -56,9 +56,7 @@ async function resolvePersistedBlobRefs(value: unknown, blobStore: BlobStore, ke
}
if (Array.isArray(value)) {
await Promise.all(
value.map(item => resolvePersistedBlobRefs(item, blobStore, key)),
);
await Promise.all(value.map(item => resolvePersistedBlobRefs(item, blobStore, key)));
return;
}
@@ -30,7 +30,7 @@ try {
diffCached: true,
});
const firstStage = await git.diff.changedFiles(dir, { cached: true });
if (JSON.stringify(firstStage) !== JSON.stringify(["new-file.txt"])) {
if (!Bun.deepEquals(firstStage, ["new-file.txt"])) {
throw new Error("unexpected first stage: " + JSON.stringify(firstStage));
}
await git.commit(dir, "feat: add new file");
@@ -39,16 +39,16 @@ try {
diffCached: true,
});
const secondStage = await git.diff.changedFiles(dir, { cached: true });
if (JSON.stringify(secondStage) !== JSON.stringify(["tracked.txt"])) {
if (!Bun.deepEquals(secondStage, ["tracked.txt"])) {
throw new Error("unexpected second stage: " + JSON.stringify(secondStage));
}
await git.commit(dir, "fix: update tracked file");
const log = (await $\`git log --format=%s -2\`.cwd(dir).text()).trim().split("\\n");
if (JSON.stringify(log) !== JSON.stringify(["fix: update tracked file", "feat: add new file"])) {
if (!Bun.deepEquals(log, ["fix: update tracked file", "feat: add new file"])) {
throw new Error("unexpected log: " + JSON.stringify(log));
}
const summary = await git.status.summary(dir);
if (JSON.stringify(summary) !== JSON.stringify({ staged: 0, unstaged: 0, untracked: 0 })) {
if (!Bun.deepEquals(summary, { staged: 0, unstaged: 0, untracked: 0 })) {
throw new Error("unexpected status: " + JSON.stringify(summary));
}
} finally {