chore: rebuild CentOS7 release package
This commit is contained in:
@@ -24,6 +24,7 @@ if (args[0] !== 'app-server') {
|
||||
|
||||
const threads = new Map();
|
||||
const pendingServerRequests = new Map();
|
||||
const resumeMismatchThreads = new Set();
|
||||
let nextServerRequestId = 1;
|
||||
let mcpReloadCount = 0;
|
||||
|
||||
@@ -64,6 +65,12 @@ function tokenUsage(text) {
|
||||
};
|
||||
}
|
||||
|
||||
function retryScenarioKey(text, marker) {
|
||||
return new RegExp(marker.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i').test(String(text || ''))
|
||||
? marker
|
||||
: String(text || '');
|
||||
}
|
||||
|
||||
function collaborationSummary(params = {}) {
|
||||
const collaborationMode = params.collaborationMode;
|
||||
const settings = collaborationMode?.settings || {};
|
||||
@@ -623,8 +630,9 @@ function startTurn(params) {
|
||||
}
|
||||
|
||||
if (/codexapp capacity retry/i.test(text)) {
|
||||
const attempts = (thread.capacityRetryAttempts.get(text) || 0) + 1;
|
||||
thread.capacityRetryAttempts.set(text, attempts);
|
||||
const retryKey = retryScenarioKey(text, 'codexapp capacity retry');
|
||||
const attempts = (thread.capacityRetryAttempts.get(retryKey) || 0) + 1;
|
||||
thread.capacityRetryAttempts.set(retryKey, attempts);
|
||||
if (attempts <= 2) {
|
||||
if (attempts === 2) emitPartialCapacityOutput(thread, turnId);
|
||||
emitCapacityError(thread, turnId);
|
||||
@@ -633,8 +641,9 @@ function startTurn(params) {
|
||||
}
|
||||
|
||||
if (/codexapp reconnect retry/i.test(text)) {
|
||||
const attempts = (thread.reconnectRetryAttempts.get(text) || 0) + 1;
|
||||
thread.reconnectRetryAttempts.set(text, attempts);
|
||||
const retryKey = retryScenarioKey(text, 'codexapp reconnect retry');
|
||||
const attempts = (thread.reconnectRetryAttempts.get(retryKey) || 0) + 1;
|
||||
thread.reconnectRetryAttempts.set(retryKey, attempts);
|
||||
if (attempts === 1) {
|
||||
emitPartialCapacityOutput(thread, turnId);
|
||||
send({
|
||||
@@ -650,6 +659,17 @@ function startTurn(params) {
|
||||
}
|
||||
}
|
||||
|
||||
if (/codexapp retry thread mismatch/i.test(text)) {
|
||||
const retryKey = retryScenarioKey(text, 'codexapp retry thread mismatch');
|
||||
const attempts = (thread.capacityRetryAttempts.get(retryKey) || 0) + 1;
|
||||
thread.capacityRetryAttempts.set(retryKey, attempts);
|
||||
if (attempts === 1) {
|
||||
resumeMismatchThreads.add(thread.id);
|
||||
emitCapacityError(thread, turnId);
|
||||
return { turn: { id: turnId, status: 'running', items: [] } };
|
||||
}
|
||||
}
|
||||
|
||||
if (/collaboration/i.test(text)) {
|
||||
completeTurn(thread, turnId, `collaboration mode: ${collaborationSummary(params)}`);
|
||||
return { turn: { id: turnId, status: 'running', items: [] } };
|
||||
@@ -787,6 +807,11 @@ function handleRequest(message) {
|
||||
return;
|
||||
}
|
||||
if (method === 'thread/resume') {
|
||||
if (params.threadId && resumeMismatchThreads.delete(params.threadId)) {
|
||||
const thread = ensureThread(null, params);
|
||||
send({ id, result: { thread: threadPayload(thread), model: params.model || 'gpt-5.5', cwd: thread.cwd, modelProvider: 'mock', approvalPolicy: params.approvalPolicy || 'never', approvalsReviewer: 'user', sandbox: params.sandbox || 'danger-full-access' } });
|
||||
return;
|
||||
}
|
||||
const thread = ensureThread(params.threadId, params);
|
||||
send({ id, result: { thread: threadPayload(thread), model: params.model || 'gpt-5.5', cwd: thread.cwd, modelProvider: 'mock', approvalPolicy: params.approvalPolicy || 'never', approvalsReviewer: 'user', sandbox: params.sandbox || 'danger-full-access' } });
|
||||
return;
|
||||
|
||||
@@ -1311,17 +1311,21 @@ async function main() {
|
||||
/自动重试/.test(msg.message || '')
|
||||
), 10000);
|
||||
assert(/Codex 服务暂时繁忙/.test(codexAppCapacityRetryNotice.message || ''), 'Codex App transient capacity failure should announce automatic retry');
|
||||
assert(/第 1\/2 次/.test(codexAppCapacityRetryNotice.message || ''), 'Codex App transient retry should start at attempt 1');
|
||||
assert(/从中断处继续/.test(codexAppCapacityRetryNotice.message || ''), 'Codex App retry after a started turn should announce continuation mode');
|
||||
const codexAppPartialCapacityRetryNotice = await nextMessage(messages, ws, (msg) => (
|
||||
msg.type === 'system_message' &&
|
||||
msg.sessionId === codexAppSession.sessionId &&
|
||||
/自动重试/.test(msg.message || '')
|
||||
), 10000);
|
||||
assert(/第 2\/2 次/.test(codexAppPartialCapacityRetryNotice.message || ''), 'Codex App transient retry should continue after partial output');
|
||||
assert(/从中断处继续/.test(codexAppPartialCapacityRetryNotice.message || ''), 'Codex App partial-output retry should stay in continuation mode');
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId, 20000);
|
||||
const storedCodexAppAfterCapacityRetry = JSON.parse(fs.readFileSync(path.join(sessionsDir, `${codexAppSession.sessionId}.json`), 'utf8'));
|
||||
const codexAppCapacityRetryUsers = storedCodexAppAfterCapacityRetry.messages.filter((message) => message.role === 'user' && message.content === codexAppRetryText);
|
||||
assert(codexAppCapacityRetryUsers.length === 1, 'Codex App transient retry should not duplicate the user message');
|
||||
assert(storedCodexAppAfterCapacityRetry.messages.some((message) => message.role === 'assistant' && /codexapp capacity retry prompt/.test(String(message.content || ''))), 'Codex App transient retry should persist the successful assistant response');
|
||||
assert(storedCodexAppAfterCapacityRetry.messages.some((message) => message.role === 'assistant' && /继续上一轮/.test(String(message.content || ''))), 'Codex App transient retry should ask the model to continue instead of replaying the original prompt');
|
||||
|
||||
const codexAppReconnectRetryText = 'codexapp reconnect retry prompt';
|
||||
ws.send(JSON.stringify({ type: 'message', text: codexAppReconnectRetryText, sessionId: codexAppSession.sessionId, mode: 'yolo', agent: 'codexapp' }));
|
||||
@@ -1331,11 +1335,40 @@ async function main() {
|
||||
/自动重试/.test(msg.message || '')
|
||||
), 10000);
|
||||
assert(/Codex 服务暂时繁忙/.test(codexAppReconnectRetryNotice.message || ''), 'Codex App reconnect failure should announce automatic retry');
|
||||
assert(/第 1\/2 次/.test(codexAppReconnectRetryNotice.message || ''), 'Codex App retry counter should reset after the previous retry succeeds');
|
||||
assert(/从中断处继续/.test(codexAppReconnectRetryNotice.message || ''), 'Codex App reconnect retry after a started turn should announce continuation mode');
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId, 20000);
|
||||
const storedCodexAppAfterReconnectRetry = JSON.parse(fs.readFileSync(path.join(sessionsDir, `${codexAppSession.sessionId}.json`), 'utf8'));
|
||||
const codexAppReconnectRetryUsers = storedCodexAppAfterReconnectRetry.messages.filter((message) => message.role === 'user' && message.content === codexAppReconnectRetryText);
|
||||
assert(codexAppReconnectRetryUsers.length === 1, 'Codex App reconnect retry should not duplicate the user message');
|
||||
assert(storedCodexAppAfterReconnectRetry.messages.some((message) => message.role === 'assistant' && /codexapp reconnect retry prompt/.test(String(message.content || ''))), 'Codex App reconnect retry should persist the successful assistant response');
|
||||
assert(storedCodexAppAfterReconnectRetry.messages.some((message) => message.role === 'assistant' && /继续上一轮/.test(String(message.content || ''))), 'Codex App reconnect retry should continue the interrupted turn instead of replaying the original prompt');
|
||||
|
||||
const codexAppThreadBeforeMismatch = storedCodexAppAfterReconnectRetry.codexAppThreadId;
|
||||
assert(codexAppThreadBeforeMismatch, 'Codex App retry mismatch regression needs an existing app-server thread');
|
||||
const codexAppRetryMismatchText = 'codexapp retry thread mismatch prompt';
|
||||
ws.send(JSON.stringify({ type: 'message', text: codexAppRetryMismatchText, sessionId: codexAppSession.sessionId, mode: 'yolo', agent: 'codexapp' }));
|
||||
const codexAppRetryMismatchNotice = await nextMessage(messages, ws, (msg) => (
|
||||
msg.type === 'system_message' &&
|
||||
msg.sessionId === codexAppSession.sessionId &&
|
||||
/自动重试/.test(msg.message || '')
|
||||
), 10000);
|
||||
assert(/Codex 服务暂时繁忙/.test(codexAppRetryMismatchNotice.message || ''), 'Codex App thread mismatch retry should first announce automatic retry');
|
||||
assert(/第 1\/2 次/.test(codexAppRetryMismatchNotice.message || ''), 'Codex App retry counter should reset for the next independent retryable turn');
|
||||
assert(/从中断处继续/.test(codexAppRetryMismatchNotice.message || ''), 'Codex App thread mismatch retry should also be a continuation retry');
|
||||
const codexAppRetryMismatchError = await nextMessage(messages, ws, (msg) => (
|
||||
msg.type === 'error' &&
|
||||
msg.sessionId === codexAppSession.sessionId &&
|
||||
/不同线程/.test(msg.message || '') &&
|
||||
/上下文丢失/.test(msg.message || '')
|
||||
), 20000);
|
||||
assert(/已停止/.test(codexAppRetryMismatchError.message || ''), 'Codex App retry should stop when resume returns a different thread');
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId, 20000);
|
||||
const storedCodexAppAfterRetryMismatch = JSON.parse(fs.readFileSync(path.join(sessionsDir, `${codexAppSession.sessionId}.json`), 'utf8'));
|
||||
assert(storedCodexAppAfterRetryMismatch.codexAppThreadId === codexAppThreadBeforeMismatch, 'Codex App retry mismatch must not replace the persisted app-server thread id');
|
||||
const codexAppRetryMismatchUsers = storedCodexAppAfterRetryMismatch.messages.filter((message) => message.role === 'user' && message.content === codexAppRetryMismatchText);
|
||||
assert(codexAppRetryMismatchUsers.length === 1, 'Codex App retry mismatch should not duplicate the user message');
|
||||
assert(!storedCodexAppAfterRetryMismatch.messages.some((message) => message.role === 'assistant' && /codexapp retry thread mismatch prompt/.test(String(message.content || ''))), 'Codex App retry mismatch should not persist a successful assistant response on the wrong thread');
|
||||
|
||||
ws.send(JSON.stringify({ type: 'message', text: '/goal improve benchmark coverage', sessionId: codexAppSession.sessionId, mode: 'yolo', agent: 'codexapp' }));
|
||||
const codexAppGoalSet = await nextMessage(messages, ws, (msg) => msg.type === 'system_message' && msg.sessionId === codexAppSession.sessionId && /Goal active/.test(msg.message || '') && /improve benchmark coverage/.test(msg.message || ''));
|
||||
|
||||
Reference in New Issue
Block a user