import { test, expect } from '@playwright/test'; import { resolve } from 'node:path'; import { writeFile } from 'node:fs/promises'; import type {} from '../physics/agent'; test('8 次 A 场景与 IK scratch 加载/释放:验证原生句柄,不以 heap 高水位判泄漏', async ({ page, }, info) => { await page.goto('/physics/agent.html'); await page.waitForFunction(() => Boolean(window.lekiwiAgent)); await page.evaluate( (url) => window.lekiwiAgent.boot(url), `/@fs${resolve('build/lekiwi/lekiwi-v1.zip')}`, ); const rows = await page.evaluate(() => window.lekiwiAgent.resources()); await writeFile(info.outputPath('resource-evidence.json'), JSON.stringify(rows, null, 2)); expect(rows).toHaveLength(8); expect(rows.every((row) => row.deleted.length === 6 && row.deleted.every(Boolean))).toBe(true); console.log( 'A + scratch heap capacity MiB', rows.map((row) => row.heapBytes / 1024 / 1024), ); }); for (const action of ['pause-task', 'pause-global', 'stop', 'force', 'reload'] as const) { test(`真实 WASM 等待规划时 ${action}:迟到结果不写控制/不步进`, async ({ page }, info) => { await page.goto('/physics/agent.html'); await page.waitForFunction(() => Boolean(window.lekiwiAgent)); await page.evaluate( (url) => window.lekiwiAgent.boot(url), `/@fs${resolve('build/lekiwi/lekiwi-v1.zip')}`, ); try { const result = await page.evaluate((action) => window.lekiwiAgent.lifecycle(action), action); await writeFile( info.outputPath('late-response-evidence.json'), JSON.stringify(result, null, 2), ); expect(result.before).toEqual(result.after); expect(result.before.time).toBe(0); expect(result.jevCalls).toBe(0); expect(result.state).toBe(action === 'pause-task' ? 'paused' : 'cancelled'); expect(result.owner).toBe(action === 'pause-task' ? 'agent' : 'manual'); } finally { await page.evaluate(() => window.lekiwiAgent.dispose()); } }); }