mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-04-17 19:11:33 +00:00
193 lines
6.1 KiB
JavaScript
193 lines
6.1 KiB
JavaScript
/**
|
|
* Codex (OpenAI) provider adapter.
|
|
*
|
|
* Normalizes Codex SDK session history into NormalizedMessage format.
|
|
* @module adapters/codex
|
|
*/
|
|
|
|
import { createNormalizedMessage, generateMessageId } from '../types.js';
|
|
|
|
const PROVIDER = 'codex';
|
|
|
|
/**
|
|
* Normalize a raw Codex JSONL message into NormalizedMessage(s).
|
|
* @param {object} raw - A single parsed message from Codex JSONL
|
|
* @param {string} sessionId
|
|
* @returns {import('../types.js').NormalizedMessage[]}
|
|
*/
|
|
export function normalizeCodexHistoryEntry(raw, sessionId) {
|
|
const ts = raw.timestamp || new Date().toISOString();
|
|
const baseId = raw.uuid || generateMessageId('codex');
|
|
|
|
// User message
|
|
if (raw.message?.role === 'user') {
|
|
const content = typeof raw.message.content === 'string'
|
|
? raw.message.content
|
|
: Array.isArray(raw.message.content)
|
|
? raw.message.content.map(p => typeof p === 'string' ? p : p?.text || '').filter(Boolean).join('\n')
|
|
: String(raw.message.content || '');
|
|
if (!content.trim()) return [];
|
|
return [createNormalizedMessage({
|
|
id: baseId,
|
|
sessionId,
|
|
timestamp: ts,
|
|
provider: PROVIDER,
|
|
kind: 'text',
|
|
role: 'user',
|
|
content,
|
|
})];
|
|
}
|
|
|
|
// Assistant message
|
|
if (raw.message?.role === 'assistant') {
|
|
const content = typeof raw.message.content === 'string'
|
|
? raw.message.content
|
|
: Array.isArray(raw.message.content)
|
|
? raw.message.content.map(p => typeof p === 'string' ? p : p?.text || '').filter(Boolean).join('\n')
|
|
: '';
|
|
if (!content.trim()) return [];
|
|
return [createNormalizedMessage({
|
|
id: baseId,
|
|
sessionId,
|
|
timestamp: ts,
|
|
provider: PROVIDER,
|
|
kind: 'text',
|
|
role: 'assistant',
|
|
content,
|
|
})];
|
|
}
|
|
|
|
// Thinking/reasoning
|
|
if (raw.type === 'thinking' || raw.isReasoning) {
|
|
return [createNormalizedMessage({
|
|
id: baseId,
|
|
sessionId,
|
|
timestamp: ts,
|
|
provider: PROVIDER,
|
|
kind: 'thinking',
|
|
content: raw.message?.content || '',
|
|
})];
|
|
}
|
|
|
|
// Tool use
|
|
if (raw.type === 'tool_use' || raw.toolName) {
|
|
return [createNormalizedMessage({
|
|
id: baseId,
|
|
sessionId,
|
|
timestamp: ts,
|
|
provider: PROVIDER,
|
|
kind: 'tool_use',
|
|
toolName: raw.toolName || 'Unknown',
|
|
toolInput: raw.toolInput,
|
|
toolId: raw.toolCallId || baseId,
|
|
})];
|
|
}
|
|
|
|
// Tool result
|
|
if (raw.type === 'tool_result') {
|
|
return [createNormalizedMessage({
|
|
id: baseId,
|
|
sessionId,
|
|
timestamp: ts,
|
|
provider: PROVIDER,
|
|
kind: 'tool_result',
|
|
toolId: raw.toolCallId || '',
|
|
content: raw.output || '',
|
|
isError: Boolean(raw.isError),
|
|
})];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Normalize a raw Codex event (history JSONL or transformed SDK event) into NormalizedMessage(s).
|
|
* @param {object} raw - A history entry (has raw.message.role) or transformed SDK event (has raw.type)
|
|
* @param {string} sessionId
|
|
* @returns {import('../types.js').NormalizedMessage[]}
|
|
*/
|
|
export function normalizeMessage(raw, sessionId) {
|
|
// History format: has message.role
|
|
if (raw.message?.role) {
|
|
return normalizeCodexHistoryEntry(raw, sessionId);
|
|
}
|
|
|
|
const ts = raw.timestamp || new Date().toISOString();
|
|
const baseId = raw.uuid || generateMessageId('codex');
|
|
|
|
// SDK event format (output of transformCodexEvent)
|
|
if (raw.type === 'item') {
|
|
switch (raw.itemType) {
|
|
case 'agent_message':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'text', role: 'assistant', content: raw.message?.content || '',
|
|
})];
|
|
case 'reasoning':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'thinking', content: raw.message?.content || '',
|
|
})];
|
|
case 'command_execution':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: 'Bash', toolInput: { command: raw.command },
|
|
toolId: baseId,
|
|
output: raw.output, exitCode: raw.exitCode, status: raw.status,
|
|
})];
|
|
case 'file_change':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: 'FileChanges', toolInput: raw.changes,
|
|
toolId: baseId, status: raw.status,
|
|
})];
|
|
case 'mcp_tool_call':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: raw.tool || 'MCP', toolInput: raw.arguments,
|
|
toolId: baseId, server: raw.server, result: raw.result,
|
|
error: raw.error, status: raw.status,
|
|
})];
|
|
case 'web_search':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: 'WebSearch', toolInput: { query: raw.query },
|
|
toolId: baseId,
|
|
})];
|
|
case 'todo_list':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: 'TodoList', toolInput: { items: raw.items },
|
|
toolId: baseId,
|
|
})];
|
|
case 'error':
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'error', content: raw.message?.content || 'Unknown error',
|
|
})];
|
|
default:
|
|
// Unknown item type — pass through as generic tool_use
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'tool_use', toolName: raw.itemType || 'Unknown',
|
|
toolInput: raw.item || raw, toolId: baseId,
|
|
})];
|
|
}
|
|
}
|
|
|
|
if (raw.type === 'turn_complete') {
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'complete',
|
|
})];
|
|
}
|
|
if (raw.type === 'turn_failed') {
|
|
return [createNormalizedMessage({
|
|
id: baseId, sessionId, timestamp: ts, provider: PROVIDER,
|
|
kind: 'error', content: raw.error?.message || 'Turn failed',
|
|
})];
|
|
}
|
|
|
|
return [];
|
|
}
|