feat: support MCP elicitation and rebuild release

This commit is contained in:
shiyue
2026-08-24 17:39:41 +08:00
parent dd233a40e8
commit bd20a79d4b
69 changed files with 8978 additions and 13 deletions

View File

@@ -0,0 +1,84 @@
'use strict';
/** Gitea 会话展示契约回归:不启动 server只校验数据协议和脱敏链路。 */
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { normalizeWebhookEvent } = require('../lib/gitea-webhook');
const { buildWorkflowPrompt } = require('../lib/gitea-workflow-codex');
const serverSource = fs.readFileSync(path.join(__dirname, '..', 'server.js'), 'utf8');
const appSource = fs.readFileSync(path.join(__dirname, '..', 'public', 'app.js'), 'utf8');
const styleSource = fs.readFileSync(path.join(__dirname, '..', 'public', 'style.css'), 'utf8');
function fixturePayload() {
return {
repository: {
owner: { login: 'shiyue' },
name: 'kan',
full_name: 'shiyue/kan',
clone_url: 'https://gitea.example/shiyue/kan.git',
},
issue: { number: 1, title: '这里是测试bot' },
comment: {
id: 9,
body: '@codexbot 再测试一次',
user: { login: 'alice' },
},
sender: { login: 'alice' },
};
}
function run() {
const event = normalizeWebhookEvent({
payload: fixturePayload(),
headers: { 'x-gitea-event': 'issue_comment' },
botIdentity: { login: 'codexbot' },
});
assert.equal(event.ignored, false);
assert.equal(event.resource.title, '这里是测试bot');
assert.equal(event.mention.instruction, '再测试一次');
const prompt = buildWorkflowPrompt({
taskId: 'task-ui',
turnId: 'turn-ui',
resourceKey: 'default:shiyue/kan:issue:1',
workspacePath: '/home/hdzx/giteabot/shiyue/kan',
instruction: event.mention.instruction,
});
assert.match(prompt, /工作区:\/home\/hdzx\/giteabot\/shiyue\/kan/);
assert.match(prompt, /用户指令:\n再测试一次/);
assert.match(prompt, /final 隐藏标记/);
// Codex 仍接收 runtimeText历史用户消息使用 displayText避免内部 Prompt 进入用户气泡。
assert.match(serverSource, /const displayText = giteaDisplayMessage\(task, event\)/);
assert.match(serverSource, /text: displayText, mode: 'yolo', agent: 'codexapp'/);
assert.match(serverSource, /runtimeText: prompt/);
assert.match(serverSource, /content: displayTextValue/);
assert.match(serverSource, /const giteaSource = normalizeGiteaSource\(options\.giteaSource\)/);
assert.match(serverSource, /persistedUserMessage\.giteaSource = giteaSource/);
// 标题优先 Issue/PR resource.title旧资源键仅作兜底。
assert.match(serverSource, /title: issueTitle \|\| legacyTitle/);
assert.match(serverSource, /session\.title === legacyTitle/);
assert.match(serverSource, /let sessionCreated = false/);
assert.match(serverSource, /if \(sessionCreated && !presentationChanged\) broadcastSessionList\(\)/);
// 前端既显示来源标记,也会把旧完整 Prompt 脱敏为简短来源消息。
assert.match(appSource, /来自 gitea 消息:/);
assert.match(appSource, /gitea-message-label/);
assert.match(appSource, /session-item-source-badge/);
assert.match(appSource, /function getGiteaVisibleMessageContent/);
assert.match(appSource, /已收到工单请求,请读取工单上下文/);
assert.match(styleSource, /\.msg\.gitea-message \.msg-bubble/);
assert.match(styleSource, /\.session-item-source-badge/);
console.log('Gitea Workflow UI unit checks passed');
}
try {
run();
} catch (error) {
console.error(error.stack || error.message || error);
process.exitCode = 1;
}