feat: 优化任务状态与图片 MCP 提示
This commit is contained in:
@@ -662,6 +662,7 @@ function assertTaskBoardIntegrationContract() {
|
||||
const taskBoardServiceSource = fs.readFileSync(path.join(REPO_DIR, 'lib', 'task-board-service.js'), 'utf8');
|
||||
const taskBoardMcpSource = fs.readFileSync(path.join(REPO_DIR, 'lib', 'task-board-mcp.js'), 'utf8');
|
||||
const taskBoardLifecycleSource = fs.readFileSync(path.join(REPO_DIR, 'lib', 'task-board-lifecycle.js'), 'utf8');
|
||||
const taskBoardClassifierSource = fs.readFileSync(path.join(REPO_DIR, 'lib', 'task-board-classifier.js'), 'utf8');
|
||||
const taskBoardFrontendSource = fs.readFileSync(path.join(PUBLIC_DIR, 'task-board.js'), 'utf8');
|
||||
const taskBoardStyleSource = fs.readFileSync(path.join(PUBLIC_DIR, 'task-board.css'), 'utf8');
|
||||
const trackingIdCount = (indexSource.match(/id="task-tracking-control"/g) || []).length;
|
||||
@@ -682,6 +683,11 @@ function assertTaskBoardIntegrationContract() {
|
||||
const internalMcpSource = extractFunctionSource(serverSource, 'callInternalMcpTool');
|
||||
const composerSource = extractFunctionSource(serverSource, 'listComposerSuggestions');
|
||||
const composerMcpSource = extractFunctionSource(serverSource, 'listComposerMcpItems');
|
||||
const startCodexAppTurnSource = extractFunctionSource(serverSource, 'startCodexAppTurn');
|
||||
const handleMessageSource = extractFunctionSource(serverSource, 'handleMessage');
|
||||
const handleTurnCompleteSource = extractFunctionSource(serverSource, 'handleCodexAppTurnComplete');
|
||||
const handleSteerSource = extractFunctionSource(serverSource, 'handleCodexAppSteerMessage');
|
||||
const saveSessionSource = extractFunctionSource(serverSource, 'saveSession');
|
||||
assert(!serverSource.includes('function taskBoardFacets(') && !queryPayloadSource.includes('facets'), 'Task board queries should not expose retired Agent facets');
|
||||
assert(!filtersSource.includes("'agent'") && !filtersSource.includes('source.agent') && !filtersSource.includes('filters.agent'), 'Task board queries should ignore retired Agent filters');
|
||||
assert(!filtersSource.includes('source.priority') && !filtersSource.includes('filters.priority'), 'Task board queries should not forward the retired priority filter');
|
||||
@@ -738,10 +744,32 @@ function assertTaskBoardIntegrationContract() {
|
||||
'Task status WebSocket and MCP responses should not retain ignored-write branches'
|
||||
);
|
||||
assert(
|
||||
serverSource.includes('ensureTaskBoardMcpToolsFresh(client, session, currentThreadId)')
|
||||
&& serverSource.includes('taskSchema: taskSchemaFingerprint')
|
||||
&& serverSource.includes("client.reloadMcpServers()"),
|
||||
'Codex App turns should invalidate cached MCP tools and carry a schema fingerprint fallback'
|
||||
!serverSource.includes('ensureTaskBoardMcpToolsFresh')
|
||||
&& !serverSource.includes('taskBoardMcpFingerprintBySession')
|
||||
&& !startCodexAppTurnSource.includes('reloadMcpServers')
|
||||
&& !startCodexAppTurnSource.includes('config/mcpServer/reload'),
|
||||
'Automatic task classification must not reload MCP before Codex App turns'
|
||||
);
|
||||
assert(
|
||||
taskBoardClassifierSource.includes("tools: []")
|
||||
&& taskBoardClassifierSource.includes("tool_choice: 'none'")
|
||||
&& taskBoardClassifierSource.includes("type: 'json_schema'")
|
||||
&& taskBoardClassifierSource.includes('唯一职责是分类')
|
||||
&& taskBoardClassifierSource.includes('不要执行、继续、检查或验证任务'),
|
||||
'Task classifier should use a focused no-tool strict JSON request'
|
||||
);
|
||||
assert(
|
||||
handleMessageSource.includes('TASK_STATUS_CLASSIFICATION_EVENTS.USER_MESSAGE_RECEIVED')
|
||||
&& handleTurnCompleteSource.includes('TASK_STATUS_CLASSIFICATION_EVENTS.TURN_COMPLETED')
|
||||
&& handleTurnCompleteSource.includes('!completionError')
|
||||
&& handleTurnCompleteSource.includes('!options.interrupted')
|
||||
&& handleTurnCompleteSource.includes('!entry.userAborted')
|
||||
&& handleSteerSource.includes('TASK_STATUS_CLASSIFICATION_EVENTS.USER_MESSAGE_RECEIVED'),
|
||||
'Codex App classification should run only at accepted user messages and successful turn completion'
|
||||
);
|
||||
assert(
|
||||
saveSessionSource.includes('preserveNewerTaskTrackingForSessionSave(session, targetPath)'),
|
||||
'Ordinary session persistence must preserve a newer task tracking version written by the classifier'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5597,6 +5625,8 @@ function assertCcwebDisplayImageContract() {
|
||||
const { TOOLS, prepareImagePayload } = require(path.join(REPO_DIR, 'lib', 'ccweb-mcp-server'));
|
||||
const imageHandler = server.slice(server.indexOf('function createCcwebDisplayImage'), server.indexOf('function findCcwebPromptMessage'));
|
||||
assert(TOOLS.some((tool) => tool.name === 'ccweb_display_image'), 'ccweb MCP should expose the image display tool');
|
||||
const displayImageTool = TOOLS.find((tool) => tool.name === 'ccweb_display_image');
|
||||
assert(displayImageTool.description === '当你需要输出、显示图片时,请调用该 MCP。', 'Image tool description should state only its responsibility');
|
||||
assert(server.includes("case 'ccweb_display_image':"), 'Internal MCP routing should handle image display calls');
|
||||
assert(!imageHandler.includes("type: 'session_message'"), 'Image tool should not create a separate assistant message');
|
||||
assert(frontend.includes('isCcwebDisplayImageTool'), 'Image tool results should render inside the current assistant bubble');
|
||||
@@ -7133,8 +7163,8 @@ async function main() {
|
||||
await nextMessage(messages, ws, (msg) => msg.type === 'done' && msg.sessionId === codexAppSession.sessionId);
|
||||
const reloadAfterTracking = await postAuthedJson(port, token, `/api/sessions/${codexAppSession.sessionId}/reload-mcp`);
|
||||
assert(
|
||||
Number(reloadAfterTracking.result?.reloadCount || 0) >= baselineMcpReloadCount + 2,
|
||||
'Changing tracking should trigger one implicit Codex App MCP reload before the next turn'
|
||||
Number(reloadAfterTracking.result?.reloadCount || 0) === baselineMcpReloadCount + 1,
|
||||
'Task tracking changes must not trigger an implicit MCP reload; only the explicit reload request should count'
|
||||
);
|
||||
|
||||
ws.send(JSON.stringify({ type: 'composer_suggestions', requestId: 'reg-codexapp-prompt-user-mcp', trigger: '/', query: 'prompt_user', sessionId: codexAppSession.sessionId, agent: 'codexapp' }));
|
||||
|
||||
Reference in New Issue
Block a user