mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Fix Codex MCP duplicate user/assistant message emissions
Root cause: user_message was being emitted from TWO places: 1. agent-manager.recordUserMessage() - called by session.ts before stream() 2. codex-mcp-agent.ts stream() method - was emitting its own user_message Fix: Remove user_message emission from codex-mcp-agent.ts stream() since the agent-manager already handles this. Added explanatory comment. Updated test to expect 0 user_messages from provider (agent-manager handles this through the full stack). Verified via Playwright E2E: created new Codex agent, sent "test fix", confirmed only ONE user message appears in UI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -402,7 +402,7 @@ function getConversationIdFromMetadata(metadata: unknown): string | undefined {
|
||||
|
||||
describe("CodexMcpAgentClient (MCP integration)", () => {
|
||||
test(
|
||||
"emits exactly one user_message and one assistant_message per turn",
|
||||
"provider does not emit user_message (agent-manager handles that), emits exactly one assistant_message",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const restoreSessionDir = useTempCodexSessionDir();
|
||||
@@ -422,7 +422,8 @@ describe("CodexMcpAgentClient (MCP integration)", () => {
|
||||
try {
|
||||
session = await client.createSession(config);
|
||||
|
||||
// Simple prompt that should result in exactly one user message and one assistant message
|
||||
// Simple prompt that should result in exactly one assistant message
|
||||
// NOTE: user_message is NOT emitted by the provider - that's the agent-manager's job
|
||||
const prompt = "Say hello";
|
||||
|
||||
for await (const event of session.stream(prompt)) {
|
||||
@@ -440,10 +441,9 @@ describe("CodexMcpAgentClient (MCP integration)", () => {
|
||||
}
|
||||
}
|
||||
|
||||
// CRITICAL: There should be exactly ONE user_message event
|
||||
expect(userMessages.length).toBe(1);
|
||||
expect(userMessages[0].type).toBe("user_message");
|
||||
expect(userMessages[0].text).toBe(prompt);
|
||||
// Provider should NOT emit user_message - that's handled by agent-manager.recordUserMessage()
|
||||
// This prevents duplicate user messages when running through the full stack.
|
||||
expect(userMessages.length).toBe(0);
|
||||
|
||||
// CRITICAL: There should be exactly ONE assistant_message event (not duplicated)
|
||||
expect(assistantMessages.length).toBe(1);
|
||||
|
||||
@@ -2596,11 +2596,9 @@ class CodexMcpAgentSession implements AgentSession {
|
||||
this.currentAbortController = abortController;
|
||||
|
||||
const promptText = toPromptText(prompt);
|
||||
this.emitEvent({
|
||||
type: "timeline",
|
||||
provider: CODEX_PROVIDER,
|
||||
item: { type: "user_message", text: promptText },
|
||||
});
|
||||
// NOTE: user_message is NOT emitted here because the agent-manager's
|
||||
// recordUserMessage() already handles emitting the user message timeline
|
||||
// event before calling stream(). Emitting here would cause duplicates.
|
||||
|
||||
void this.forwardPrompt(promptText, options, abortController.signal).catch((error) => {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
|
||||
Reference in New Issue
Block a user