chore: rebuild CentOS7 release package
This commit is contained in:
@@ -22,6 +22,8 @@ const RUNTIME_STREAM_DELTA_MAX_CHARS = readPositiveIntEnv('CC_WEB_CODEX_APP_STRE
|
||||
const RUNTIME_MAX_TOOL_CALLS = readPositiveIntEnv('CC_WEB_CODEX_APP_RUNTIME_MAX_TOOL_CALLS', 120, { min: 1, max: 1000 });
|
||||
const RUNTIME_TRUNCATED_HEAD = '[cc-web: 前文过长,已保留尾部以保护服务稳定性]\n';
|
||||
const RUNTIME_TRUNCATED_TAIL = '\n[cc-web: 内容过长,已截断以保护服务稳定性]';
|
||||
const CODEX_APP_PLAN_ITEM_TYPES = new Set(['plan', 'plan_list', 'planlist', 'todo', 'todo_list', 'todolist', 'task_list']);
|
||||
const CODEX_APP_PLAN_TOOL_NAMES = new Set(['update_plan', 'plan', 'plan_list', 'todo_list', 'updateplan', 'todolist']);
|
||||
|
||||
function createCodexAppRuntime(deps = {}) {
|
||||
const {
|
||||
@@ -131,6 +133,123 @@ function createCodexAppRuntime(deps = {}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function normalizeIdentifier(value) {
|
||||
return String(value || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '_')
|
||||
.replace(/^_+|_+$/g, '');
|
||||
}
|
||||
|
||||
function isPlanToolName(value) {
|
||||
const name = normalizeIdentifier(value);
|
||||
return CODEX_APP_PLAN_TOOL_NAMES.has(name) || name.endsWith('_update_plan');
|
||||
}
|
||||
|
||||
function isPlanLikeItem(item) {
|
||||
if (!item || typeof item !== 'object') return false;
|
||||
if (CODEX_APP_PLAN_ITEM_TYPES.has(normalizeIdentifier(item.type))) return true;
|
||||
return isPlanToolName(item.tool || item.name || item.functionName || item.function?.name);
|
||||
}
|
||||
|
||||
function parseMaybeJsonValue(value) {
|
||||
if (typeof value !== 'string') return value;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed || !/^[{[]/.test(trimmed)) return value;
|
||||
try {
|
||||
return JSON.parse(trimmed);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function extractPlanEntries(value, depth = 0) {
|
||||
if (value === null || value === undefined || depth > 3) return null;
|
||||
const source = parseMaybeJsonValue(value);
|
||||
if (Array.isArray(source)) return source;
|
||||
if (!source || typeof source !== 'object') return null;
|
||||
const keys = ['plan', 'items', 'todos', 'tasks', 'steps'];
|
||||
for (const key of keys) {
|
||||
if (Array.isArray(source[key])) return source[key];
|
||||
}
|
||||
const nestedKeys = ['arguments', 'input', 'params', 'payload', 'structuredContent', 'result'];
|
||||
for (const key of nestedKeys) {
|
||||
const nested = extractPlanEntries(source[key], depth + 1);
|
||||
if (nested) return nested;
|
||||
}
|
||||
if (Array.isArray(source.contentItems)) {
|
||||
for (const part of source.contentItems) {
|
||||
const text = typeof part?.text === 'string' ? part.text : '';
|
||||
const nested = extractPlanEntries(text, depth + 1);
|
||||
if (nested) return nested;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function planEntryCompleted(entry) {
|
||||
if (!entry || typeof entry !== 'object') return false;
|
||||
if (entry.completed === true || entry.done === true) return true;
|
||||
const status = normalizeIdentifier(entry.status || entry.state);
|
||||
return ['completed', 'complete', 'done', 'success', 'succeeded'].includes(status);
|
||||
}
|
||||
|
||||
function planEntryText(entry) {
|
||||
if (typeof entry === 'string') return entry;
|
||||
if (!entry || typeof entry !== 'object') return '';
|
||||
return entry.step || entry.text || entry.title || entry.name || entry.description || entry.task || entry.item || entry.content || '';
|
||||
}
|
||||
|
||||
function normalizeTodoListFromPlanItem(item) {
|
||||
if (!isPlanLikeItem(item)) return null;
|
||||
const candidates = [
|
||||
item.arguments,
|
||||
item.input,
|
||||
item.params,
|
||||
item.payload,
|
||||
item.structuredContent,
|
||||
item.result?.structuredContent,
|
||||
item.result,
|
||||
item,
|
||||
];
|
||||
let entries = null;
|
||||
for (const candidate of candidates) {
|
||||
entries = extractPlanEntries(candidate);
|
||||
if (entries) break;
|
||||
}
|
||||
if (!Array.isArray(entries)) return null;
|
||||
const items = entries
|
||||
.map((entry) => {
|
||||
const text = truncateEnd(planEntryText(entry), RUNTIME_TOOL_INPUT_MAX_CHARS);
|
||||
if (!text) return null;
|
||||
return {
|
||||
text,
|
||||
completed: planEntryCompleted(entry),
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
return {
|
||||
id: item.id || item.itemId || item.planId || 'codex-app-plan',
|
||||
type: 'todo_list',
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
function planUpdateItemFromParams(params = {}) {
|
||||
const item = params.item && typeof params.item === 'object' ? { ...params.item } : {};
|
||||
return {
|
||||
...params,
|
||||
...item,
|
||||
id: item.id || params.itemId || params.id || params.planId || 'codex-app-plan',
|
||||
type: item.type || params.type || 'planList',
|
||||
status: item.status || params.status || 'inProgress',
|
||||
plan: item.plan || params.plan,
|
||||
items: item.items || params.items,
|
||||
todos: item.todos || params.todos,
|
||||
tasks: item.tasks || params.tasks,
|
||||
};
|
||||
}
|
||||
|
||||
function codexAppErrorMessage(value) {
|
||||
if (!value) return '';
|
||||
if (typeof value === 'string') return value;
|
||||
@@ -178,6 +297,7 @@ function createCodexAppRuntime(deps = {}) {
|
||||
}
|
||||
|
||||
function itemKind(item) {
|
||||
if (normalizeTodoListFromPlanItem(item)) return 'todo_list';
|
||||
switch (item?.type) {
|
||||
case 'commandExecution':
|
||||
return 'command_execution';
|
||||
@@ -203,6 +323,7 @@ function createCodexAppRuntime(deps = {}) {
|
||||
}
|
||||
|
||||
function itemName(item) {
|
||||
if (normalizeTodoListFromPlanItem(item)) return 'PlanList';
|
||||
switch (item?.type) {
|
||||
case 'commandExecution':
|
||||
return 'CommandExecution';
|
||||
@@ -227,6 +348,8 @@ function createCodexAppRuntime(deps = {}) {
|
||||
|
||||
function itemInput(item) {
|
||||
if (!item) return null;
|
||||
const todoList = normalizeTodoListFromPlanItem(item);
|
||||
if (todoList) return todoList;
|
||||
switch (item.type) {
|
||||
case 'commandExecution':
|
||||
return { command: truncateEnd(item.command || '', RUNTIME_TOOL_INPUT_MAX_CHARS) };
|
||||
@@ -292,6 +415,14 @@ function createCodexAppRuntime(deps = {}) {
|
||||
|
||||
function itemMeta(item) {
|
||||
if (!item) return null;
|
||||
if (normalizeTodoListFromPlanItem(item)) {
|
||||
return {
|
||||
kind: 'todo_list',
|
||||
title: 'Plan List',
|
||||
subtitle: item.explanation || item.title || item.tool || '',
|
||||
status: item.status || null,
|
||||
};
|
||||
}
|
||||
switch (item.type) {
|
||||
case 'commandExecution':
|
||||
return {
|
||||
@@ -346,6 +477,8 @@ function createCodexAppRuntime(deps = {}) {
|
||||
|
||||
function itemResult(item) {
|
||||
if (!item) return '';
|
||||
const todoList = normalizeTodoListFromPlanItem(item);
|
||||
if (todoList) return JSON.stringify(todoList, null, 2);
|
||||
switch (item.type) {
|
||||
case 'commandExecution':
|
||||
return truncateEnd(item.aggregatedOutput || '', RUNTIME_TOOL_RESULT_MAX_CHARS);
|
||||
@@ -390,7 +523,7 @@ function createCodexAppRuntime(deps = {}) {
|
||||
toolCall.name = itemName(item);
|
||||
toolCall.kind = kind;
|
||||
toolCall.meta = itemMeta(item) || toolCall.meta || null;
|
||||
if (toolCall.input == null) toolCall.input = itemInput(item);
|
||||
if (toolCall.input == null || kind === 'todo_list') toolCall.input = itemInput(item);
|
||||
return toolCall;
|
||||
}
|
||||
|
||||
@@ -608,6 +741,22 @@ function createCodexAppRuntime(deps = {}) {
|
||||
return { done: false };
|
||||
}
|
||||
|
||||
case 'plan/updated':
|
||||
case 'turn/plan/updated':
|
||||
case 'item/plan/updated':
|
||||
case 'item/todoList/updated': {
|
||||
const item = planUpdateItemFromParams(params);
|
||||
const todoList = normalizeTodoListFromPlanItem(item);
|
||||
if (!todoList) return { done: false };
|
||||
updateToolResult(entry, sessionId, todoList.id, JSON.stringify(todoList, null, 2), false, {
|
||||
name: 'PlanList',
|
||||
kind: 'todo_list',
|
||||
input: todoList,
|
||||
meta: itemMeta(item),
|
||||
});
|
||||
return { done: false };
|
||||
}
|
||||
|
||||
case 'item/reasoning/summaryTextDelta':
|
||||
case 'item/reasoning/textDelta': {
|
||||
const itemId = params.itemId;
|
||||
|
||||
Reference in New Issue
Block a user