Files
memind/goal-run-gateway.test.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

123 lines
3.8 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createAgentRunGateway } from './agent-run-gateway.mjs';
import { buildAgentOrchestrationAgentText } from './chat-intent-router.mjs';
function createGoalRunPool() {
const runs = new Map();
const events = [];
return {
runs,
events,
async query(sql, params = []) {
if (sql.includes('SELECT * FROM h5_agent_runs WHERE user_id = ? AND request_id = ?')) {
const [userId, requestId] = params;
const row = [...runs.values()].find(
(item) => item.user_id === userId && item.request_id === requestId,
);
return [[row].filter(Boolean)];
}
if (sql.includes('agent_session_id = ?') && sql.includes("status NOT IN ('succeeded', 'failed')")) {
return [[]];
}
if (sql.includes('INSERT INTO h5_agent_runs')) {
const [
id,
userId,
sessionId,
goalRunId,
goalCheckpointId,
requestId,
userMessageJson,
createdAt,
updatedAt,
] = params;
runs.set(id, {
id,
user_id: userId,
agent_session_id: sessionId,
goal_run_id: goalRunId,
goal_checkpoint_id: goalCheckpointId,
request_id: requestId,
status: 'queued',
attempts: 0,
user_message_json: userMessageJson,
created_at: createdAt,
updated_at: updatedAt,
});
return [{ affectedRows: 1 }];
}
if (sql.includes('INSERT INTO h5_agent_run_events')) {
events.push({
runId: params[1],
eventType: params[2],
dataJson: params[3],
});
return [{ affectedRows: 1 }];
}
if (sql.includes('SELECT * FROM h5_agent_runs WHERE id = ? LIMIT 1')) {
return [[runs.get(params[0])].filter(Boolean)];
}
if (sql.includes('INSERT INTO h5_agent_run_snapshots')) {
return [{ affectedRows: 1 }];
}
throw new Error(`Unexpected SQL: ${sql.slice(0, 120)}`);
},
};
}
test('createRun persists goal_run_id and goal_checkpoint_id', async () => {
const pool = createGoalRunPool();
const attachCalls = [];
const gateway = createAgentRunGateway({
pool,
userAuth: {},
tkmindProxy: {},
autoDispatch: false,
goalRunService: {
async attachAgentRunToCheckpoint(input) {
attachCalls.push(input);
return true;
},
},
});
const run = await gateway.createRun('user-1', {
requestId: 'req-goal-1',
userMessage: { role: 'user', content: [{ type: 'text', text: '分阶段任务' }] },
goalRunId: 'goal-1',
goalCheckpointId: 'cp-1',
});
assert.equal(run.requestId, 'req-goal-1');
const stored = [...pool.runs.values()][0];
assert.equal(stored.goal_run_id, 'goal-1');
assert.equal(stored.goal_checkpoint_id, 'cp-1');
assert.deepEqual(attachCalls, [{
checkpointId: 'cp-1',
agentRunId: stored.id,
}]);
const queuedEvent = pool.events.find((event) => event.eventType === 'queued');
assert.match(String(queuedEvent?.dataJson ?? ''), /"goalRunId":"goal-1"/);
});
test('buildAgentOrchestrationAgentText injects goal context before memory context', () => {
const text = buildAgentOrchestrationAgentText({
displayText: '继续推进',
classification: { reason: '长期任务续作' },
goalContext: {
injectionEnabled: true,
envelope: '【Goal Context】\n目标:产品规划\n当前阶段:调研(进行中)',
},
memoryContext: {
injectionEnabled: true,
memories: [{ label: '偏好', text: '简洁中文' }],
},
});
const goalIndex = text.indexOf('【Goal Context】');
const memoryIndex = text.indexOf('[Memory Context]');
assert.ok(goalIndex >= 0);
assert.ok(memoryIndex > goalIndex);
assert.match(text, /目标:产品规划/);
});