aps-agent/scripts/runtime-conformance.test.mjs

75 lines
2.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 引擎一致性测试(任务 A3.2)。
*
* 同一套用例先跑假引擎,A3.3 接真 Pi 后跑同一套(A3.9 引擎可替换验证也用它)。
* 第二个用例故意给一个坏运行时,证明这套检查不是摆设。
*/
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { runRuntimeConformance, createTestTools } from '@aps/server/agent/conformance';
import { createFakeRuntime } from '@aps/server/agent/fake-runtime';
/** 各场景的脚本:假引擎按这个产出事件 */
function turnsFor(scenario) {
switch (scenario) {
case 'tool_call':
return [
{
text: ['我先查一下。'],
toolCalls: [{ capabilityId: 'test.echo', args: { query: '下周排产' } }],
afterToolsText: ['查到了,共 3 条。'],
},
];
case 'cancel':
return [{ text: ['开始处理', '继续处理'] }];
case 'error':
return [{ error: { kind: 'unavailable', message: '上游不可用' } }];
default:
return [{ text: ['我是假引擎,'], afterToolsText: [] }];
}
}
test('假引擎通过一致性测试', async () => {
const report = await runRuntimeConformance({
createRuntime: (scenario) => createFakeRuntime({ name: 'fake', turns: turnsFor(scenario) }),
tools: createTestTools(),
});
assert.equal(report.runtimeName, 'fake');
assert.equal(report.ok, true, JSON.stringify(report.checks.filter((check) => !check.ok), null, 2));
assert.ok(report.checks.length >= 10, `检查项应有十条以上,实际 ${report.checks.length}`);
});
test('坏运行时被一致性测试拦下(负例)', async () => {
const broken = {
name: 'broken',
async createSession() {
return {
id: 'broken-1',
async *send(_text, options) {
if (options?.signal?.aborted) {
// 取消场景:仍然按 stop 收尾,属于违规
yield { type: 'turn_end', reason: 'stop' };
return;
}
yield { type: 'text', delta: '只说一句' };
yield { type: 'turn_end', reason: 'stop' };
},
resolveToolResult() {
/* 不回填:工具回合永远拿不到 tool_result */
},
abort() {
/* 忽略取消 */
},
async dispose() {},
};
},
};
const report = await runRuntimeConformance({ createRuntime: () => broken, tools: createTestTools() });
assert.equal(report.ok, false, '坏运行时不应当通过');
const failed = report.checks.filter((check) => !check.ok).map((check) => check.name);
assert.ok(failed.includes('取消后以 turn_end(cancelled) 结束'), `应检出取消违规,实际:${failed.join('、')}`);
assert.ok(failed.includes('回执回流后产出 tool_result'), `应检出工具回执未回流,实际:${failed.join('、')}`);
assert.ok(failed.includes('错误事件带合法分类'), `应检出缺少错误事件,实际:${failed.join('、')}`);
});