fix(test): 测试强制使用假引擎,不读本机真实配置

真引擎点亮后自动化测试开始真调模型(测试通过 startServer 默认读到 ~/.aps/config.json 里的密钥),verify 从 6 秒变成挂住。现在 StartOptions 支持显式 engine 覆盖,六个测试文件统一传 engine: 'fake';CI 再加 APS_ENGINE=fake 双保险。verify 恢复到 6 秒、60 条测试(59 通过 + 1 跳过)。
This commit is contained in:
zh 2026-09-28 20:30:40 +08:00
parent e74ca8a131
commit 4f59524d2a
8 changed files with 15 additions and 9 deletions

View File

@ -11,6 +11,9 @@ on:
jobs:
platform:
runs-on: ubuntu-latest
env:
# 双保险:CI 里永远不走真引擎(测试自己也注入 fake,见 startServer 的 engine 参数)
APS_ENGINE: fake
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4

View File

@ -17,7 +17,7 @@ async function startPlatform(devProvider = true) {
if (devProvider) process.env.APS_DEV_PROVIDER = '1';
else delete process.env.APS_DEV_PROVIDER;
const { startServer } = await import('../server/dist/index.js');
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:' });
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', engine: 'fake' });
return server;
}

View File

@ -10,7 +10,7 @@ import { test } from 'node:test';
async function startWithProvider() {
process.env.APS_DEV_PROVIDER = '1';
const { startServer } = await import('../server/dist/index.js');
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:' });
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', engine: 'fake' });
const created = await fetch(`${server.url}/v1/sessions`, {
method: 'POST',
headers: { 'content-type': 'application/json' },

View File

@ -23,7 +23,7 @@ test('假引擎发起工具调用,经 Core.invoke 到假 Provider 并把回执
],
});
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', runtime });
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', engine: 'fake', runtime });
try {
const created = await fetch(`${server.url}/v1/sessions`, {
method: 'POST',

View File

@ -16,7 +16,7 @@ test('平台服务托管客户端产物,且 API 不受影响', async () => {
execFileSync('pnpm', ['--filter', '@aps/client-app', 'run', 'build'], { cwd: ROOT, stdio: 'pipe', shell: isWindows });
const { startServer } = await import('../server/dist/index.js');
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:' });
const server = await startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', engine: 'fake' });
try {
const page = await fetch(`${server.url}/`);
assert.equal(page.status, 200, 'GET / 应返回客户端页面');

View File

@ -31,7 +31,7 @@ async function validator() {
async function startServer(options = {}) {
const { startServer: start } = await import('../server/dist/index.js');
return start({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', ...options });
return start({ host: '127.0.0.1', port: 0, version: 'test', databasePath: ':memory:', engine: 'fake', ...options });
}
const json = (method, body) => ({ method, headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });

View File

@ -11,7 +11,7 @@ import { test } from 'node:test';
async function startWithDatabase(dbPath) {
const { startServer } = await import('../server/dist/index.js');
return startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: dbPath });
return startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: dbPath, engine: 'fake' });
}
const postJson = (base, path, body) =>

View File

@ -26,6 +26,8 @@ export interface StartOptions {
runtime?: AgentRuntime;
/** 数据库路径:默认取配置;测试传 ':memory:' 以隔离 */
databasePath?: string;
/** 引擎覆盖:测试必须传 'fake',避免读到本机的真实模型配置 */
engine?: 'fake' | 'pi';
}
export interface RunningServer {
@ -41,7 +43,7 @@ export async function startServer(options: StartOptions = {}): Promise<RunningSe
const config = loadConfig();
const host = options.host ?? config.server.host;
const port = options.port ?? config.server.port;
const runtime = options.runtime ?? (await selectRuntime(config));
const runtime = options.runtime ?? (await selectRuntime(config, options.engine));
const database: Database = openDatabase(options.databasePath ?? config.database.path);
const service = new ApplicationService({
...(options.version === undefined ? {} : { version: options.version }),
@ -81,8 +83,9 @@ export async function startServer(options: StartOptions = {}): Promise<RunningSe
};
}
/** 引擎选择:显式注入 > 配置里的 engine.kind;选 pi 但没密钥时明确回退到假引擎 */
async function selectRuntime(config: ReturnType<typeof loadConfig>): Promise<AgentRuntime> {
if (config.engine.kind !== 'pi') {
async function selectRuntime(config: ReturnType<typeof loadConfig>, override?: 'fake' | 'pi'): Promise<AgentRuntime> {
const kind = override ?? config.engine.kind;
if (kind !== 'pi') {
const { createFakeRuntime } = await import('./agent/fake-runtime.js');
const { createRulePlanner, plannerToFakeTurn } = await import('./agent/rule-planner.js');
return createFakeRuntime({ name: 'fake', planner: plannerToFakeTurn(createRulePlanner()) });