feat: complete Aider Page Data review workflow

This commit is contained in:
john
2026-07-25 09:47:25 +08:00
parent be9c25f1d0
commit 104fb4e370
15 changed files with 914 additions and 30 deletions
+70 -9
View File
@@ -1,5 +1,10 @@
import { normalizeAgentRunToolMode } from './agent-run-gateway.mjs';
import { AIDER_DEVELOPMENT_SKILL_NAME } from './chat-skills.mjs';
import {
AIDER_DEVELOPMENT_SKILL_NAME,
buildChatSkillPrompt,
extractAiderDevelopmentTask,
isPageDataIntent,
} from './chat-skills.mjs';
import { createSessionAccess } from './session-broker.mjs';
import {
extractRunFromStreamEvent,
@@ -58,6 +63,39 @@ function selectedChatSkill(userMessage) {
return String(runMetadata.selectedChatSkill ?? '').trim();
}
function rewriteAiderPageDataInstruction(userMessage, taskText) {
const aiderPrompt = buildChatSkillPrompt(
AIDER_DEVELOPMENT_SKILL_NAME,
AIDER_DEVELOPMENT_SKILL_NAME,
);
const pageDataPrompt = buildChatSkillPrompt('page-data-collect', 'page-data-collect');
const compositePrompt = [
pageDataPrompt,
taskText,
'\n\n[强制 Aider 审查]',
'先由当前 Agent 使用 private_data_* 和 Page Data 工具完成建表、dataset、页面与绑定。',
'完成后平台会强制调用 Aider 审查当前工作区产物;禁止省略该审查或声称 Aider 已执行。',
].join('');
const content = Array.isArray(userMessage?.content)
? userMessage.content
.filter((item) => (
item?.type !== 'text' ||
!String(item.text ?? '').trim().startsWith('[Memind code-run validation]')
))
.map((item) => {
if (item?.type !== 'text') return item;
const text = String(item.text ?? '');
return {
...item,
text: text.includes(aiderPrompt)
? text.replace(`${aiderPrompt}${taskText}`, compositePrompt)
: text,
};
})
: userMessage?.content;
return { ...userMessage, content };
}
export function enforceSelectedSkillRuntime(userMessage, {
rawToolMode = 'chat',
taskType = null,
@@ -74,16 +112,24 @@ export function enforceSelectedSkillRuntime(userMessage, {
const runMetadata = metadata.memindRun && typeof metadata.memindRun === 'object' && !Array.isArray(metadata.memindRun)
? { ...metadata.memindRun }
: {};
const taskText = extractAiderDevelopmentTask(userMessage);
const requiresPageDataBuild = isPageDataIntent(taskText);
metadata.memindRun = {
...runMetadata,
selectedChatSkill: AIDER_DEVELOPMENT_SKILL_NAME,
executor: 'aider',
...(requiresPageDataBuild
? { reviewExecutor: 'aider', pageDataAiderWorkflow: true }
: { executor: 'aider' }),
};
if (requiresPageDataBuild) delete metadata.memindRun.executor;
return {
userMessage: { ...message, metadata },
rawToolMode: 'code',
taskType: 'h5_chat_code_task',
requiredExecutor: 'aider',
userMessage: requiresPageDataBuild
? rewriteAiderPageDataInstruction({ ...message, metadata }, taskText)
: { ...message, metadata },
rawToolMode: requiresPageDataBuild ? 'chat' : 'code',
taskType: requiresPageDataBuild ? null : 'h5_chat_code_task',
requiredExecutor: requiresPageDataBuild ? null : 'aider',
requiredReviewExecutor: requiresPageDataBuild ? 'aider' : null,
};
}
@@ -142,7 +188,14 @@ export function createPostAgentRunsHandler({
rawToolMode = selectedSkillRuntime.rawToolMode;
taskType = selectedSkillRuntime.taskType;
if (
selectedSkillRuntime.requiredExecutor &&
(selectedSkillRuntime.requiredExecutor || selectedSkillRuntime.requiredReviewExecutor) &&
!extractAiderDevelopmentTask(userMessage)
) {
response.status(400).json({ message: '请输入需要 Aider 执行的具体开发任务' });
return;
}
if (
(selectedSkillRuntime.requiredExecutor || selectedSkillRuntime.requiredReviewExecutor) &&
userAuth?.getUserSkills
) {
const skillState = await userAuth.getUserSkills(request.currentUser.id);
@@ -160,8 +213,11 @@ export function createPostAgentRunsHandler({
});
return;
}
if (toolMode === 'code') {
if (toolMode === 'code' || selectedSkillRuntime.requiredReviewExecutor) {
const codeRunPolicy = await resolveCodeRunPolicy(request.currentUser.id);
const policyTaskType = selectedSkillRuntime.requiredReviewExecutor
? 'h5_chat_code_task'
: taskType;
if (!codeRunPolicy.enabled) {
response.status(403).json({ message: '代码任务灰度未开启' });
return;
@@ -173,7 +229,12 @@ export function createPostAgentRunsHandler({
const taskTypeAllowlist = codeRunPolicy.taskTypeAllowlist ?? [];
if (
taskTypeAllowlist.length > 0 &&
(!taskType || !taskTypeAllowlist.map((item) => String(item).toLowerCase()).includes(taskType.toLowerCase()))
(
!policyTaskType ||
!taskTypeAllowlist
.map((item) => String(item).toLowerCase())
.includes(policyTaskType.toLowerCase())
)
) {
response.status(403).json({ message: '当前代码任务类型未开启灰度' });
return;