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:
@@ -0,0 +1,121 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createGoalRunAdminOpsService } from './goal-run-admin-ops.mjs';
|
||||
|
||||
test('createGoalRunAdminOpsService reports runtime flags', () => {
|
||||
const service = createGoalRunAdminOpsService(
|
||||
{ async query() { return [[]]; } },
|
||||
{
|
||||
env: {
|
||||
GOAL_RUN_ENABLED: '1',
|
||||
GOAL_RUN_CANARY_USER_IDS: 'user-a, user-b',
|
||||
},
|
||||
},
|
||||
);
|
||||
const runtime = service.getRuntime();
|
||||
assert.equal(runtime.enabled, true);
|
||||
assert.deepEqual(runtime.canaryUserIds, ['user-a', 'user-b']);
|
||||
assert.equal(runtime.canaryMode, true);
|
||||
});
|
||||
|
||||
test('listGoals returns normalized rows with checkpoint counts', async () => {
|
||||
const service = createGoalRunAdminOpsService({
|
||||
async query(sql, params) {
|
||||
if (String(sql).includes('CREATE TABLE')) return [[]];
|
||||
if (String(sql).includes('information_schema')) return [[{ ok: 1 }]];
|
||||
if (String(sql).includes('GROUP BY status')) {
|
||||
return [[{ status: 'active', count: 2 }]];
|
||||
}
|
||||
if (String(sql).includes('FROM h5_goal_runs g')) {
|
||||
return [[{
|
||||
id: 'goal-1',
|
||||
user_id: 'user-1',
|
||||
username: 'john2',
|
||||
title: '产品规划',
|
||||
intent_summary: '分阶段完成',
|
||||
status: 'active',
|
||||
priority: 5,
|
||||
source_channel: 'h5',
|
||||
source_session_id: null,
|
||||
current_checkpoint_id: 'cp-1',
|
||||
checkpoint_count: 2,
|
||||
active_agent_run_count: 1,
|
||||
created_at: 1000,
|
||||
updated_at: 2000,
|
||||
completed_at: null,
|
||||
}]];
|
||||
}
|
||||
if (String(sql).includes('FROM h5_goal_checkpoints WHERE goal_run_id')) {
|
||||
return [[
|
||||
{
|
||||
id: 'cp-1',
|
||||
goal_run_id: 'goal-1',
|
||||
sequence: 1,
|
||||
title: '调研',
|
||||
description: null,
|
||||
status: 'running',
|
||||
agent_run_id: null,
|
||||
output_summary: null,
|
||||
output_artifact_ids: null,
|
||||
user_feedback: null,
|
||||
approved_at: null,
|
||||
created_at: 1000,
|
||||
updated_at: 2000,
|
||||
started_at: 1500,
|
||||
completed_at: null,
|
||||
},
|
||||
]];
|
||||
}
|
||||
if (String(sql).includes('FROM h5_goal_runs WHERE id = ? AND user_id = ?')) {
|
||||
return [[{
|
||||
id: 'goal-1',
|
||||
user_id: 'user-1',
|
||||
title: '产品规划',
|
||||
intent_summary: '分阶段完成',
|
||||
status: 'active',
|
||||
priority: 5,
|
||||
source_channel: 'h5',
|
||||
source_session_id: null,
|
||||
source_message_id: null,
|
||||
current_checkpoint_id: 'cp-1',
|
||||
context_json: null,
|
||||
memory_snapshot_json: null,
|
||||
created_at: 1000,
|
||||
updated_at: 2000,
|
||||
completed_at: null,
|
||||
}]];
|
||||
}
|
||||
if (String(sql).includes('FROM h5_agent_runs') && String(sql).includes('goal_run_id')) {
|
||||
return [[{
|
||||
id: 'run-1',
|
||||
status: 'running',
|
||||
request_id: 'req-1',
|
||||
goal_checkpoint_id: 'cp-1',
|
||||
created_at: 1000,
|
||||
updated_at: 2000,
|
||||
completed_at: null,
|
||||
}]];
|
||||
}
|
||||
throw new Error(`Unexpected SQL: ${sql}`);
|
||||
},
|
||||
}, {
|
||||
env: {
|
||||
GOAL_RUN_ENABLED: '1',
|
||||
GOAL_RUN_CANARY_USER_IDS: 'user-1',
|
||||
},
|
||||
});
|
||||
|
||||
const counts = await service.countByStatus();
|
||||
assert.equal(counts.active, 2);
|
||||
|
||||
const items = await service.listGoals({ limit: 10 });
|
||||
assert.equal(items.length, 1);
|
||||
assert.equal(items[0].username, 'john2');
|
||||
assert.equal(items[0].checkpointCount, 2);
|
||||
|
||||
const detail = await service.getGoalDetail('goal-1');
|
||||
assert.equal(detail?.title, '产品规划');
|
||||
assert.equal(detail?.checkpoints.length, 1);
|
||||
assert.equal(detail?.agentRuns[0].id, 'run-1');
|
||||
assert.equal(detail?.canaryEnabled, true);
|
||||
});
|
||||
Reference in New Issue
Block a user