core: prevent duplicate user messages in ACP clients (#22468)
This commit is contained in:
parent
a8f9f6b705
commit
b1312a3181
2 changed files with 46 additions and 0 deletions
|
|
@ -453,6 +453,12 @@ export namespace ACP {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ACP clients already know the prompt they just submitted, so replaying
|
||||||
|
// live user parts duplicates the message. We still replay user history in
|
||||||
|
// loadSession() and forkSession() via processMessage().
|
||||||
|
if (part.type !== "text" && part.type !== "file") return
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,46 @@ describe("acp.agent event subscription", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("does not emit user_message_chunk for live prompt parts", async () => {
|
||||||
|
await using tmp = await tmpdir()
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const { agent, controller, sessionUpdates, stop } = createFakeAgent()
|
||||||
|
const cwd = "/tmp/opencode-acp-test"
|
||||||
|
const sessionId = await agent.newSession({ cwd, mcpServers: [] } as any).then((x) => x.sessionId)
|
||||||
|
|
||||||
|
controller.push({
|
||||||
|
directory: cwd,
|
||||||
|
payload: {
|
||||||
|
type: "message.part.updated",
|
||||||
|
properties: {
|
||||||
|
sessionID: sessionId,
|
||||||
|
time: Date.now(),
|
||||||
|
part: {
|
||||||
|
id: "part_1",
|
||||||
|
sessionID: sessionId,
|
||||||
|
messageID: "msg_user",
|
||||||
|
type: "text",
|
||||||
|
text: "hello",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 20))
|
||||||
|
|
||||||
|
expect(
|
||||||
|
sessionUpdates
|
||||||
|
.filter((u) => u.sessionId === sessionId)
|
||||||
|
.some((u) => u.update.sessionUpdate === "user_message_chunk"),
|
||||||
|
).toBe(false)
|
||||||
|
|
||||||
|
stop()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test("keeps concurrent sessions isolated when message.part.delta events are interleaved", async () => {
|
test("keeps concurrent sessions isolated when message.part.delta events are interleaved", async () => {
|
||||||
await using tmp = await tmpdir()
|
await using tmp = await tmpdir()
|
||||||
await Instance.provide({
|
await Instance.provide({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue