'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; }