refactor(codex): extract session management and launcher logic into separate modules

Reorganized runCodex.ts to improve maintainability by extracting:
- CodexSession class for session lifecycle management
- CodexLocalLauncher and CodexRemoteLauncher for mode-specific initialization
- CodexEventConverter for MCP message handling and UI buffer updates
- CodexSessionScanner for resume file discovery
- emitReadyIfIdle utility for ready event emission

Added codexSessionId field to metadata schema for session tracking.
Updated UI components to work with refactored architecture.
This commit is contained in:
weishu
2025-12-22 19:14:47 +08:00
parent 0c16b7b215
commit 4290f539bd
15 changed files with 1606 additions and 661 deletions
@@ -0,0 +1,85 @@
import { describe, expect, it } from 'vitest';
import { convertCodexEvent } from './codexEventConverter';
describe('convertCodexEvent', () => {
it('extracts session_meta id', () => {
const result = convertCodexEvent({
type: 'session_meta',
payload: { id: 'session-123' }
});
expect(result).toEqual({ sessionId: 'session-123' });
});
it('converts agent_message events', () => {
const result = convertCodexEvent({
type: 'event_msg',
payload: { type: 'agent_message', message: 'hello' }
});
expect(result?.message).toMatchObject({
type: 'message',
message: 'hello'
});
});
it('converts reasoning events', () => {
const result = convertCodexEvent({
type: 'event_msg',
payload: { type: 'agent_reasoning', text: 'thinking' }
});
expect(result?.message).toMatchObject({
type: 'reasoning',
message: 'thinking'
});
});
it('converts reasoning delta events', () => {
const result = convertCodexEvent({
type: 'event_msg',
payload: { type: 'agent_reasoning_delta', delta: 'step' }
});
expect(result?.message).toEqual({
type: 'reasoning-delta',
delta: 'step'
});
});
it('converts function_call items', () => {
const result = convertCodexEvent({
type: 'response_item',
payload: {
type: 'function_call',
name: 'ToolName',
call_id: 'call-1',
arguments: '{"foo":"bar"}'
}
});
expect(result?.message).toMatchObject({
type: 'tool-call',
name: 'ToolName',
callId: 'call-1',
input: { foo: 'bar' }
});
});
it('converts function_call_output items', () => {
const result = convertCodexEvent({
type: 'response_item',
payload: {
type: 'function_call_output',
call_id: 'call-2',
output: { ok: true }
}
});
expect(result?.message).toMatchObject({
type: 'tool-call-result',
callId: 'call-2',
output: { ok: true }
});
});
});