codexmobile-relay / server /codex-runner-event-format.js
Codex
deploy: CodexMobile Relay
90f0300
Raw
History Blame Contribute Delete
3.98 kB
export function textFromContent(content) {
if (typeof content === 'string') {
return content;
}
if (!Array.isArray(content)) {
return '';
}
return content
.map((part) => {
if (typeof part === 'string') {
return part;
}
if (part?.type === 'output_text' || part?.type === 'input_text' || part?.type === 'text') {
return part.text || '';
}
return part?.text || '';
})
.filter(Boolean)
.join('\n');
}
export function contentFromItem(item) {
if (!item) {
return '';
}
const contentText = textFromContent(item.content);
if (contentText) {
return contentText;
}
if (typeof item.text === 'string') {
return item.text;
}
if (typeof item.aggregated_output === 'string') {
return item.aggregated_output;
}
if (typeof item.message === 'string') {
return item.message;
}
return '';
}
export function statusLabel(kind, status = 'running') {
const done = status === 'completed';
const failed = status === 'failed';
const labels = {
turn: done ? '任务已完成' : failed ? '任务失败' : '正在处理',
reasoning: done ? '思考完成' : '正在思考',
agent_message: '正在回复',
message: '正在回复',
command_execution: done ? '命令已完成' : failed ? '命令失败' : '正在执行命令',
file_change: done ? '文件已修改' : failed ? '文件修改失败' : '正在修改文件',
mcp_tool_call: done ? '工具调用完成' : failed ? '工具调用失败' : '正在调用工具',
web_search: done ? '搜索完成' : failed ? '搜索失败' : '正在搜索',
todo_list: done ? '计划已更新' : '正在规划',
image_generation_call: done ? '图片生成完成' : failed ? '图片生成失败' : '正在生成图片',
custom_tool_call: done ? '工具调用完成' : failed ? '工具调用失败' : '正在调用工具',
function_call: done ? '工具调用完成' : failed ? '工具调用失败' : '正在调用工具',
error: '出现错误'
};
return labels[kind] || (done ? '已完成' : failed ? '失败' : '正在处理');
}
export function compactStatusLabel(content, fallback = '正在处理') {
const label = String(content || '')
.replace(/\s+/g, ' ')
.trim();
if (!label) {
return fallback;
}
return label.length > 68 ? `${label.slice(0, 68)}...` : label;
}
export function detailFromItem(item) {
if (!item) {
return '';
}
if (item.command) {
return item.command;
}
if (item.query) {
return item.query;
}
if (item.tool || item.server) {
return [item.server, item.tool].filter(Boolean).join(' / ');
}
if (Array.isArray(item.changes)) {
return item.changes.map((change) => `${change.kind || 'update'} ${change.path}`).join('\n');
}
if (item.message) {
return item.message;
}
return contentFromItem(item);
}
export function eventItem(event) {
if (event.item) {
return event.item;
}
if (event.payload && (event.type === 'response_item' || event.type === 'event_msg')) {
return event.payload;
}
return null;
}
export function eventStatus(event, item) {
if (item?.status) {
return item.status === 'in_progress' ? 'running' : item.status;
}
if (event.type === 'item.completed') {
return 'completed';
}
if (event.type === 'item.started' || event.type === 'item.updated') {
return 'running';
}
if (event.type === 'event_msg' && item?.type?.endsWith('_end')) {
return item.exit_code || item.exit_code === 0 ? (item.exit_code === 0 ? 'completed' : 'failed') : 'completed';
}
if (event.type === 'response_item') {
return 'completed';
}
return 'running';
}
export function emitStatus(emit, { sessionId, turnId, kind, status = 'running', label, detail = '' }) {
emit({
type: 'status-update',
sessionId,
turnId,
kind,
status,
label: label || statusLabel(kind, status),
detail,
timestamp: new Date().toISOString()
});
}