feat(h5): web 联网能力、实时查询路由与 session Finish 对齐
- 新增 web 能力并挂载 platform/web(web_search/fetch_url) - 实时查询强制 web skill,router fallback 与 await session Finish - Session Broker 覆盖率/指标、stream replay 与相关单测/E2E 脚本 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -284,6 +284,36 @@ test('agent run starts a session and marks submitted reply as succeeded', async
|
||||
assert.equal(pool.runs.get(run.id).attempts, 1);
|
||||
});
|
||||
|
||||
test('agent run awaits session Finish before succeeding when proxy supports it', async () => {
|
||||
const pool = createFakePool();
|
||||
const awaited = [];
|
||||
const gateway = createAgentRunGateway({
|
||||
pool,
|
||||
userAuth: {},
|
||||
tkmindProxy: {
|
||||
async startSessionForUser() {
|
||||
return { id: 'session-finish-1' };
|
||||
},
|
||||
async submitSessionReplyAndAwaitFinishForUser(userId, sessionId, requestId, userMessage) {
|
||||
awaited.push({ userId, sessionId, requestId, userMessage });
|
||||
return { ok: true, finishEvent: { type: 'Finish' }, tokenState: { totalTokens: 9 } };
|
||||
},
|
||||
},
|
||||
retryDelaysMs: [],
|
||||
});
|
||||
|
||||
const run = await gateway.createRun('user-1', {
|
||||
requestId: 'req-finish-1',
|
||||
userMessage: { role: 'user', content: [{ type: 'text', text: '世界杯现在赛况如何' }] },
|
||||
});
|
||||
|
||||
await waitFor(() => pool.runs.get(run.id)?.status === 'succeeded');
|
||||
assert.equal(awaited.length, 1);
|
||||
assert.equal(awaited[0].sessionId, 'session-finish-1');
|
||||
const finishEvents = pool.events.filter((item) => item.eventType === 'session_finished');
|
||||
assert.equal(finishEvents.length, 1);
|
||||
});
|
||||
|
||||
test('agent run uses direct chat service for eligible chat messages', async () => {
|
||||
const pool = createFakePool();
|
||||
const directRuns = [];
|
||||
@@ -1458,6 +1488,35 @@ test('listRunEventsForUser replays events after Last-Event-ID cursor', async ()
|
||||
assert.equal(replay.events[0].data.run.agentSessionId, 'sess-1');
|
||||
});
|
||||
|
||||
test('listRunEventsForUser accepts mysql2-parsed JSON objects in data_json', async () => {
|
||||
const pool = createFakePool();
|
||||
const gateway = createAgentRunGateway({
|
||||
pool,
|
||||
userAuth: {},
|
||||
tkmindProxy: {},
|
||||
autoDispatch: false,
|
||||
});
|
||||
|
||||
const run = await gateway.createRun('user-1', {
|
||||
requestId: 'req-replay-json-object',
|
||||
userMessage: { role: 'user', content: [] },
|
||||
});
|
||||
|
||||
const queuedAt = Number(pool.events.find((event) => event.runId === run.id)?.createdAt ?? 1000);
|
||||
pool.events.push({
|
||||
id: 'evt-snapshot-object',
|
||||
runId: run.id,
|
||||
eventType: 'run_snapshot',
|
||||
dataJson: { run: { ...run, status: 'running', agentSessionId: 'sess-mysql2' } },
|
||||
createdAt: queuedAt + 1000,
|
||||
});
|
||||
|
||||
const batch = await gateway.listRunEventsForUser('user-1', run.id);
|
||||
const snapshotEvent = batch.events.find((event) => event.id === 'evt-snapshot-object');
|
||||
assert.ok(snapshotEvent);
|
||||
assert.equal(snapshotEvent.data.run.agentSessionId, 'sess-mysql2');
|
||||
});
|
||||
|
||||
test('listRunEventsForUser reports cursorMiss for unknown Last-Event-ID', async () => {
|
||||
const pool = createFakePool();
|
||||
const gateway = createAgentRunGateway({
|
||||
|
||||
Reference in New Issue
Block a user