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>
This commit is contained in:
@@ -31,6 +31,7 @@ function plazaRouteError(res, req, error) {
|
||||
* @param {object} deps.userAuth
|
||||
* @param {object|null} deps.llmProviderService
|
||||
* @param {object|null} deps.memoryV2ConfigService
|
||||
* @param {object|null} deps.goalRunAdminOpsService
|
||||
* @param {object|null} deps.orchestratorConfigService
|
||||
* @param {object|null} deps.orchestratorObservabilityService
|
||||
* @param {object|null} deps.skillRuntimeConfigService
|
||||
@@ -50,6 +51,7 @@ export function createAdminApi({
|
||||
assetGatewayConfigService,
|
||||
imageMakeAdminConfigService,
|
||||
memoryV2ConfigService,
|
||||
goalRunAdminOpsService,
|
||||
orchestratorConfigService,
|
||||
orchestratorObservabilityService,
|
||||
mindSearchConfigService,
|
||||
@@ -231,6 +233,105 @@ export function createAdminApi({
|
||||
return res.json(result);
|
||||
});
|
||||
|
||||
adminApi.get('/goal-runs/runtime', requireAdmin, async (_req, res) => {
|
||||
if (!goalRunAdminOpsService?.getRuntime) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
return res.json(goalRunAdminOpsService.getRuntime());
|
||||
});
|
||||
|
||||
adminApi.get('/goal-runs/summary', requireAdmin, async (_req, res) => {
|
||||
if (!goalRunAdminOpsService?.countByStatus) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
try {
|
||||
const counts = await goalRunAdminOpsService.countByStatus();
|
||||
const runtime = goalRunAdminOpsService.getRuntime();
|
||||
return res.json({ counts, runtime });
|
||||
} catch (err) {
|
||||
return res.status(500).json({
|
||||
message: err instanceof Error ? err.message : '读取 Goal Run 汇总失败',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
adminApi.get('/goal-runs', requireAdmin, async (req, res) => {
|
||||
if (!goalRunAdminOpsService?.listGoals) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
try {
|
||||
const status = String(req.query?.status ?? '').trim() || null;
|
||||
const userId = String(req.query?.userId ?? req.query?.user_id ?? '').trim() || null;
|
||||
const limit = Number(req.query?.limit ?? 50);
|
||||
const offset = Number(req.query?.offset ?? 0);
|
||||
const items = await goalRunAdminOpsService.listGoals({ status, userId, limit, offset });
|
||||
return res.json({ items, status, limit, offset });
|
||||
} catch (err) {
|
||||
return res.status(400).json({
|
||||
message: err instanceof Error ? err.message : '读取 Goal Run 列表失败',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
adminApi.get('/goal-runs/:goalRunId', requireAdmin, async (req, res) => {
|
||||
if (!goalRunAdminOpsService?.getGoalDetail) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
try {
|
||||
const goal = await goalRunAdminOpsService.getGoalDetail(req.params.goalRunId);
|
||||
if (!goal) return res.status(404).json({ message: '目标不存在' });
|
||||
return res.json({ goal });
|
||||
} catch (err) {
|
||||
return res.status(500).json({
|
||||
message: err instanceof Error ? err.message : '读取 Goal Run 详情失败',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
adminApi.post('/goal-runs/:goalRunId/checkpoints/:checkpointId/approve', requireAdmin, async (req, res) => {
|
||||
if (!goalRunAdminOpsService?.approveCheckpoint) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
try {
|
||||
const goal = await goalRunAdminOpsService.approveCheckpoint({
|
||||
goalRunId: req.params.goalRunId,
|
||||
checkpointId: req.params.checkpointId,
|
||||
feedback: req.body?.feedback ?? null,
|
||||
reviewedBy: req.currentUser.id,
|
||||
});
|
||||
return res.json({ ok: true, goal });
|
||||
} catch (err) {
|
||||
const status = err?.code === 'GOAL_RUN_NOT_FOUND' || err?.code === 'GOAL_CHECKPOINT_NOT_FOUND'
|
||||
? 404
|
||||
: err?.code === 'GOAL_CHECKPOINT_NOT_APPROVABLE'
|
||||
? 409
|
||||
: 500;
|
||||
return res.status(status).json({
|
||||
message: err instanceof Error ? err.message : '确认阶段失败',
|
||||
code: err?.code ?? null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
adminApi.post('/goal-runs/:goalRunId/cancel', requireAdmin, async (req, res) => {
|
||||
if (!goalRunAdminOpsService?.cancelGoal) {
|
||||
return res.status(503).json({ message: 'Goal Run 管理服务未启用' });
|
||||
}
|
||||
try {
|
||||
const goal = await goalRunAdminOpsService.cancelGoal({
|
||||
goalRunId: req.params.goalRunId,
|
||||
reviewedBy: req.currentUser.id,
|
||||
});
|
||||
return res.json({ ok: true, goal });
|
||||
} catch (err) {
|
||||
const status = err?.code === 'GOAL_RUN_NOT_FOUND' ? 404 : err?.code === 'GOAL_RUN_NOT_CANCELLABLE' ? 409 : 500;
|
||||
return res.status(status).json({
|
||||
message: err instanceof Error ? err.message : '取消目标失败',
|
||||
code: err?.code ?? null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
adminApi.get('/orchestrator/config', requireAdmin, async (_req, res) => {
|
||||
if (!orchestratorConfigService?.getAdminConfig) {
|
||||
return res.status(503).json({ message: 'Orchestrator 配置服务未启用' });
|
||||
|
||||
Reference in New Issue
Block a user