fix(codex): improve web rendering for Codex events (#544)

* test(codex): add web event rendering harness

* fix(codex): surface plan updates in web

* fix(codex): render MCP tool calls in web

* fix(codex): improve terminal and context display

* fix(codex): format token usage events

* fix(codex): show status context in web

* fix(codex): preserve tool result errors
This commit is contained in:
CoColate
2026-04-29 17:22:45 +08:00
committed by GitHub
parent a612be50d6
commit e76738aa5a
27 changed files with 1138 additions and 15 deletions
+56 -1
View File
@@ -69,6 +69,32 @@ vi.mock('./codexAppServerClient', () => {
return { turn: { id: turnId } };
}
if (params?.threadId === 'thread-1') {
const commandStart = {
item: {
id: 'cmd-1',
type: 'commandExecution',
command: 'echo ok',
cwd: '/tmp/hapi-update'
}
};
harness.notifications.push({ method: 'item/started', params: commandStart });
this.notificationHandler?.('item/started', commandStart);
this.notificationHandler?.('item/commandExecution/outputDelta', {
itemId: 'cmd-1',
delta: 'ok\n'
});
const commandEnd = {
item: {
id: 'cmd-1',
type: 'commandExecution',
exitCode: 0
}
};
harness.notifications.push({ method: 'item/completed', params: commandEnd });
this.notificationHandler?.('item/completed', commandEnd);
}
const completed = { status: 'Completed', turn: { id: turnId } };
harness.notifications.push({ method: 'turn/completed', params: completed });
this.notificationHandler?.('turn/completed', completed);
@@ -250,7 +276,12 @@ describe('codexRemoteLauncher', () => {
experimentalApi: true
}
}]);
expect(harness.notifications.map((entry) => entry.method)).toEqual(['turn/started', 'turn/completed']);
expect(harness.notifications.map((entry) => entry.method)).toEqual([
'turn/started',
'item/started',
'item/completed',
'turn/completed'
]);
expect(sessionEvents.filter((event) => event.type === 'ready').length).toBeGreaterThanOrEqual(1);
expect(thinkingChanges).toContain(true);
expect(session.thinking).toBe(false);
@@ -286,6 +317,30 @@ describe('codexRemoteLauncher', () => {
expect(session.thinking).toBe(false);
});
it('surfaces Codex bash stdout instead of duplicating raw output json', async () => {
const { session, codexMessages } = createSessionStub();
await codexRemoteLauncher(session as never);
expect(codexMessages).toContainEqual(expect.objectContaining({
type: 'tool-call-result',
callId: 'cmd-1',
output: expect.objectContaining({
command: 'echo ok',
cwd: '/tmp/hapi-update',
stdout: 'ok\n',
exit_code: 0
})
}));
expect(codexMessages).not.toContainEqual(expect.objectContaining({
type: 'tool-call-result',
callId: 'cmd-1',
output: expect.objectContaining({
output: 'ok\n'
})
}));
});
it('clears codex thread state without starting a turn', async () => {
const { session, sessionEvents, resetThreadCalls } = createSessionStub(['/clear', 'next message']);