chore: rebuild release package

This commit is contained in:
shiyue
2026-07-17 11:29:51 +08:00
parent 5c3401292d
commit fa15b54469
8 changed files with 448 additions and 7 deletions

View File

@@ -10075,7 +10075,7 @@ function handleCodexAppTurnComplete(sessionId, options = {}) {
}
if (session && (assistantContent.trim() || assistantToolCalls.length > 0) && !hasCodexAppTurnMessage(session, turnKey)) {
session.messages.push({
const assistantMessage = {
role: 'assistant',
content: assistantContent,
toolCalls: assistantToolCalls,
@@ -10084,7 +10084,21 @@ function handleCodexAppTurnComplete(sessionId, options = {}) {
codexAppThreadId: entry.threadId || null,
codexAppTurnId: entry.turnId || null,
interrupted: !!options.interrupted,
});
};
const beforeUserMessage = options.beforeUserMessage;
const beforeUserMessageIndex = beforeUserMessage
? session.messages.findIndex((message) => (
message?.role === 'user'
&& message.timestamp === beforeUserMessage.timestamp
&& message.content === beforeUserMessage.content
))
: -1;
if (beforeUserMessageIndex >= 0) {
// stale steer 已先持久化用户消息,把旧 turn 输出恢复到该消息之前。
session.messages.splice(beforeUserMessageIndex, 0, assistantMessage);
} else {
session.messages.push(assistantMessage);
}
session.updated = new Date().toISOString();
if (!entry.ws) session.hasUnread = true;
saveSession(session);
@@ -10095,7 +10109,9 @@ function handleCodexAppTurnComplete(sessionId, options = {}) {
if (entry.crossConversationReplyRequestId) {
completeCrossConversationReply(entry.crossConversationReplyRequestId, entry, session);
}
flushPendingCrossConversationReplies(sessionId);
if (!options.deferPendingCrossConversationFlush) {
flushPendingCrossConversationReplies(sessionId);
}
plog(completionError ? 'WARN' : 'INFO', 'codex_app_turn_complete', {
sessionId: sessionId.slice(0, 8),
threadId: entry.threadId || null,
@@ -10140,6 +10156,10 @@ function handleCodexAppTurnFailure(sessionId, err) {
handleCodexAppTurnComplete(sessionId, { error: entry.lastError });
}
function isCodexAppNoActiveTurnError(err) {
return /\bno active turn to steer\b/i.test(String(err?.message || err || ''));
}
function handleCodexAppSteerMessage(ws, msg, options = {}) {
const sessionId = sanitizeId(msg?.sessionId || '');
const entry = activeCodexAppTurns.get(sessionId);
@@ -10231,6 +10251,42 @@ function handleCodexAppSteerMessage(ws, msg, options = {}) {
message: `已引导对话: ${previewInlineText(textValue)}`,
});
}).catch((err) => {
if (isCodexAppNoActiveTurnError(err) && activeCodexAppTurns.get(sessionId) === entry) {
// app-server 已确认旧 turn 不存在:先收敛旧输出,再复用已持久化的消息直接启动新 turn。
handleCodexAppTurnComplete(sessionId, {
beforeUserMessage: {
timestamp: persistedUserMessage.timestamp,
content: persistedUserMessage.content,
},
deferPendingCrossConversationFlush: true,
});
const refreshedSession = loadSession(sessionId);
const restarted = refreshedSession
&& isCodexAppSession(refreshedSession)
&& !activeCodexAppTurns.has(sessionId)
? handleCodexAppMessage(ws, refreshedSession, runtimeTextValue, [], {
mcpContext: entry.mcpContext || options.mcpContext || {},
})
: null;
if (restarted?.ok) {
wsSend(entry.ws || ws, {
type: 'resume_generating',
sessionId,
text: '',
toolCalls: [],
});
sendSteerStatus('inserted', '已转为新对话');
wsSend(entry.ws || ws, {
type: 'system_message',
sessionId,
tone: 'info',
transient: true,
autoDismissMs: 5000,
message: '检测到上一轮已结束,已自动开始新一轮对话。',
});
return;
}
}
sendSteerStatus('failed', '插入失败');
wsSend(entry.ws || ws, {
type: 'error',