chore: rebuild CentOS7 release package
This commit is contained in:
@@ -364,6 +364,62 @@ function completeTurn(thread, turnId, text, status = 'completed') {
|
||||
thread.steers = [];
|
||||
}
|
||||
|
||||
function completeGoalBackgroundTurn(thread, objective) {
|
||||
const turnId = `goal-turn-${crypto.randomUUID()}`;
|
||||
const text = `Goal background output: ${objective}`;
|
||||
thread.activeTurnId = turnId;
|
||||
send({
|
||||
method: 'turn/started',
|
||||
params: {
|
||||
threadId: thread.id,
|
||||
turn: { id: turnId, status: 'running', items: [] },
|
||||
},
|
||||
});
|
||||
send({
|
||||
method: 'item/agentMessage/delta',
|
||||
params: {
|
||||
threadId: thread.id,
|
||||
turnId,
|
||||
itemId: 'goal-agent-msg',
|
||||
delta: text,
|
||||
},
|
||||
});
|
||||
send({
|
||||
method: 'item/completed',
|
||||
params: {
|
||||
threadId: thread.id,
|
||||
turnId,
|
||||
completedAtMs: Date.now(),
|
||||
item: {
|
||||
id: 'goal-agent-msg',
|
||||
type: 'agentMessage',
|
||||
text,
|
||||
status: 'completed',
|
||||
},
|
||||
},
|
||||
});
|
||||
send({
|
||||
method: 'thread/tokenUsage/updated',
|
||||
params: {
|
||||
threadId: thread.id,
|
||||
turnId,
|
||||
tokenUsage: tokenUsage(text),
|
||||
},
|
||||
});
|
||||
send({
|
||||
method: 'turn/completed',
|
||||
params: {
|
||||
threadId: thread.id,
|
||||
turn: {
|
||||
id: turnId,
|
||||
status: 'completed',
|
||||
items: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
thread.activeTurnId = null;
|
||||
}
|
||||
|
||||
function requestClient(method, params, callback) {
|
||||
const id = `mock-server-request-${nextServerRequestId++}`;
|
||||
pendingServerRequests.set(id, callback);
|
||||
@@ -874,6 +930,9 @@ function handleRequest(message) {
|
||||
});
|
||||
setTimeout(() => {
|
||||
send({ id, result: { goal: thread.goal } });
|
||||
if (params.objective) {
|
||||
setTimeout(() => completeGoalBackgroundTurn(thread, objective), 50);
|
||||
}
|
||||
}, 250);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -738,6 +738,10 @@ function assertSessionSwitchResilienceContract() {
|
||||
/const flushedSessionResume = flushedSessionSwitch \? false : flushPendingSessionResume\(\);[\s\S]*?requestSessionResume\(currentSessionId/.test(frontendSource),
|
||||
'Frontend should resume the current running session after auth without forcing load_session'
|
||||
);
|
||||
assert(
|
||||
frontendSource.includes("send({ type: 'abort', sessionId: currentSessionId })"),
|
||||
'Frontend abort button should explicitly target the current session'
|
||||
);
|
||||
assert(
|
||||
/case 'background_done':[\s\S]*?if \(isNearBottom\(\)\)[\s\S]*?openSession\(msg\.sessionId,\s*\{ forceSync: true, blocking: false \}\)[\s\S]*?send\(\{ type: 'list_sessions' \}\)/.test(frontendSource),
|
||||
'Frontend should not auto-rerender the current session on background_done while the user is reading history'
|
||||
@@ -775,6 +779,12 @@ function assertSessionSwitchResilienceContract() {
|
||||
assert(serverSource.includes("case 'resume_session':"), 'Server should accept lightweight resume_session requests');
|
||||
assert(serverSource.includes('function handleResumeSession'), 'Server should implement lightweight running-session resume');
|
||||
assert(serverSource.includes('function attachActiveRuntimeToWs'), 'Server should share runtime re-attach logic without sending session_info first');
|
||||
assert(/case 'abort':\s*handleAbort\(ws, msg\);/.test(serverSource), 'Server should pass abort request metadata to handleAbort');
|
||||
assert(/function handleAbort\(ws, msg = \{\}\)/.test(serverSource), 'Server handleAbort should accept the abort request payload');
|
||||
assert(
|
||||
/function bindAbortSessionToWs\(sessionId, ws\)[\s\S]*?entry\.ws = ws/.test(serverSource),
|
||||
'Server abort should rebind the target running session to the current WebSocket before stopping'
|
||||
);
|
||||
assert(serverSource.includes('WS_HEARTBEAT_MAX_MISSES'), 'Server should tolerate missed WebSocket pongs before terminating');
|
||||
assert(serverSource.includes('function markWsActivity'), 'Server should mark WebSocket activity on send/message/pong');
|
||||
assert(
|
||||
@@ -1796,6 +1806,13 @@ async function main() {
|
||||
assert(codexAppGoalRunningList.sessions.some((session) => session.id === codexAppSession.sessionId && session.isRunning), 'Codex App /goal RPC should mark the session running while waiting for app-server');
|
||||
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 || ''));
|
||||
assert(/Goal active/.test(codexAppGoalSet.message || ''), 'Codex App /goal should set an active goal');
|
||||
const codexAppGoalBackgroundDelta = await nextMessage(messages, ws, (msg) => (
|
||||
msg.type === 'text_delta' &&
|
||||
msg.sessionId === codexAppSession.sessionId &&
|
||||
/Goal background output: improve benchmark coverage/.test(msg.text || '')
|
||||
), 5000);
|
||||
assert(/Goal background output/.test(codexAppGoalBackgroundDelta.text || ''), 'Codex App /goal background turn should stream through the active session');
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId, 5000);
|
||||
const codexAppGoalIdleList = await nextMessage(messages, ws, (msg) => (
|
||||
msg.type === 'session_list' &&
|
||||
Array.isArray(msg.sessions) &&
|
||||
@@ -1819,6 +1836,10 @@ async function main() {
|
||||
assert(/\/goal <目标描述>/.test(codexAppGoalEmpty.message || ''), 'Codex App /goal should show usage when no goal exists');
|
||||
const storedCodexAppAfterGoal = JSON.parse(fs.readFileSync(path.join(sessionsDir, `${codexAppSession.sessionId}.json`), 'utf8'));
|
||||
assert(!storedCodexAppAfterGoal.messages.some((message) => message.role === 'user' && /^\/goal/.test(String(message.content || ''))), 'Codex App /goal slash commands should not be persisted as normal user messages');
|
||||
assert(storedCodexAppAfterGoal.messages.some((message) => (
|
||||
message.role === 'assistant' &&
|
||||
/Goal background output: improve benchmark coverage/.test(String(message.content || ''))
|
||||
)), 'Codex App /goal background turn should be routed and persisted as an assistant message');
|
||||
|
||||
ws.send(JSON.stringify({ type: 'message', text: 'codexapp runtime warning prompt', sessionId: codexAppSession.sessionId, mode: 'yolo', agent: 'codexapp' }));
|
||||
const codexAppRuntimeWarning = await nextMessage(messages, ws, (msg) => (
|
||||
@@ -2174,11 +2195,13 @@ async function main() {
|
||||
targetConversationId: codexAppSession.sessionId,
|
||||
content: 'running codexapp target should reject this',
|
||||
},
|
||||
});
|
||||
assert(codexAppRunningMcp.status === 400 && codexAppRunningMcp.body?.code === 'target_running', 'MCP cross send should reject running Codex App targets');
|
||||
await sleep(150);
|
||||
ws.send(JSON.stringify({ type: 'abort' }));
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId);
|
||||
});
|
||||
assert(codexAppRunningMcp.status === 400 && codexAppRunningMcp.body?.code === 'target_running', 'MCP cross send should reject running Codex App targets');
|
||||
await sleep(150);
|
||||
ws.send(JSON.stringify({ type: 'detach_view' }));
|
||||
await sleep(50);
|
||||
ws.send(JSON.stringify({ type: 'abort', sessionId: codexAppSession.sessionId }));
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId);
|
||||
|
||||
const claudeAttachment = await uploadAttachment(port, token, {
|
||||
filename: 'claude-test.png',
|
||||
|
||||
Reference in New Issue
Block a user