feat: add fail-closed Aider development skill

This commit is contained in:
john
2026-07-24 19:48:04 +08:00
parent 1c82b34ad9
commit be9c25f1d0
15 changed files with 320 additions and 7 deletions
+33
View File
@@ -346,6 +346,26 @@ function normalizeSessionMessageCount(value) {
return Math.floor(parsed);
}
export function resolveRequiredCodeExecutor(userMessage) {
const metadata = userMessage?.metadata;
const runMetadata = metadata?.[RUN_METADATA_KEY] ?? metadata?.agentRun ?? {};
const executor = String(runMetadata?.executor ?? '').trim().toLowerCase();
return ['aider', 'openhands'].includes(executor) ? executor : null;
}
export function assertRequiredCodeExecutorAvailable(requiredExecutor, toolGatewayStatus) {
if (!requiredExecutor) return;
const executors = Array.isArray(toolGatewayStatus?.executors)
? toolGatewayStatus.executors.map((item) => String(item).trim().toLowerCase())
: [];
if (!toolGatewayStatus?.enabled || !executors.includes(requiredExecutor)) {
const error = new Error(`必需执行器 ${requiredExecutor} 不可用,任务已停止且不会回退`);
error.code = 'REQUIRED_EXECUTOR_UNAVAILABLE';
error.retryable = false;
throw error;
}
}
function getRunOptionsFromMessage(userMessage) {
const metadata = userMessage?.metadata;
const runMetadata = metadata?.[RUN_METADATA_KEY] ?? metadata?.agentRun ?? {};
@@ -358,6 +378,7 @@ function getRunOptionsFromMessage(userMessage) {
return {
toolMode,
taskType: normalizeTaskType(runMetadata?.taskType ?? metadata?.taskType),
requiredExecutor: resolveRequiredCodeExecutor(userMessage),
forceDeepReasoning: runMetadata?.forceDeepReasoning === true || metadata?.forceDeepReasoning === true,
validation: normalizeToolGatewayValidation(runMetadata?.validation ?? metadata?.toolGatewayValidation),
sessionMessageCount: normalizeSessionMessageCount(
@@ -859,6 +880,7 @@ export function createAgentRunGateway({
let userMessage = safeJsonParse(row.user_message_json, {});
const runOptions = getRunOptionsFromMessage(userMessage);
const toolGatewayStatus = toolGateway?.getStatus ? toolGateway.getStatus() : null;
assertRequiredCodeExecutorAvailable(runOptions.requiredExecutor, toolGatewayStatus);
let disclosureDecision = null;
try {
disclosureDecision = systemDisclosurePolicyService?.evaluate?.({
@@ -1037,6 +1059,17 @@ export function createAgentRunGateway({
cwd: workingDir,
timeoutMs: runTimeoutMs,
});
if (
runOptions.requiredExecutor &&
String(result?.executor ?? '').trim().toLowerCase() !== runOptions.requiredExecutor
) {
const error = new Error(
`执行器不匹配:要求 ${runOptions.requiredExecutor},实际 ${result?.executor ?? 'unknown'}`,
);
error.code = 'REQUIRED_EXECUTOR_MISMATCH';
error.retryable = false;
throw error;
}
await appendEvent(runId, 'tool_gateway_result', {
executor: result.executor ?? null,
dryRun: Boolean(result.dryRun),