Files
memind/goal-run-resolve.mjs
T
john 666db0b939 feat(goal-run): add multi-checkpoint goal orchestration with H5 and admin surfaces.
Persist goal runs in MySQL, bind agent runs to checkpoints, expose awaiting-approval
UX in chat, and add admin inspection routes with local verify scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 17:03:16 +08:00

68 lines
1.8 KiB
JavaScript

import {
deriveGoalTitleFromText,
extractUserMessageDisplayText,
isGoalRunEnabledForUser,
isGoalRunIntent,
} from './goal-run-intent.mjs';
export async function resolveGoalBindingForAgentRun({
goalRunService = null,
chatIntentRouter = null,
userId,
userMessage,
sessionId = null,
body = {},
env = process.env,
} = {}) {
if (!goalRunService || !isGoalRunEnabledForUser(userId, env)) {
return null;
}
const explicitGoalRunId = String(body.goal_run_id ?? body.goalRunId ?? '').trim() || null;
if (explicitGoalRunId) {
const goal = await goalRunService.getGoalRun({ userId, goalRunId: explicitGoalRunId });
if (!goal) {
const error = new Error('目标不存在');
error.code = 'GOAL_RUN_NOT_FOUND';
error.status = 404;
throw error;
}
const started = await goalRunService.startNextCheckpoint({
userId,
goalRunId: explicitGoalRunId,
});
return {
goalRunId: explicitGoalRunId,
goalCheckpointId: started.checkpointId,
};
}
const displayText = extractUserMessageDisplayText(userMessage);
let shouldCreateGoal = isGoalRunIntent(displayText);
if (!shouldCreateGoal && chatIntentRouter?.classify) {
const classification = await chatIntentRouter.classify({
userId,
userMessage,
sessionId,
toolMode: 'chat',
});
shouldCreateGoal = classification?.decision?.flags?.includes('goal_run') === true;
}
if (!shouldCreateGoal) return null;
const goal = await goalRunService.createGoalRun({
userId,
title: deriveGoalTitleFromText(displayText),
intentSummary: displayText || '长期任务',
sourceSessionId: sessionId,
});
const started = await goalRunService.startNextCheckpoint({
userId,
goalRunId: goal.id,
});
return {
goalRunId: goal.id,
goalCheckpointId: started.checkpointId,
};
}