Files
Mujoco_WASM/web_platform/e2e/lekiwi.agent.spec.ts
T
chenlin f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00

104 lines
4.7 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { resolve } from 'node:path';
import { writeFile } from 'node:fs/promises';
import preset from '../../contracts/lekiwi-pick-place-v1.json' with { type: 'json' };
import type {} from '../physics/agent';
for (const seed of preset.frozenSeeds) {
test(`规则物理基线:冻结种子 ${seed.id},双指抓持/搬运/释放/撤离`, async ({ page }, info) => {
const errors: string[] = [];
page.on('pageerror', (error) => errors.push(error.message));
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((seed) => window.lekiwiAgent.baseline(seed), seed.id);
await writeFile(info.outputPath('physical-evidence.json'), JSON.stringify(result, null, 2));
console.log('baseline', { ...result, trace: `${result.trace.length} control samples` });
expect(result.status, result.error).toBe('succeeded');
expect(result.succeeded).toBe(true);
expect(result.transported).toBeGreaterThanOrEqual(preset.transportMin);
expect(result.maxJointSpeed).toBeLessThanOrEqual(preset.jointSpeedStop);
const goal = preset.goal.position.map((v, i) => v + (seed.offset[i] ?? 0));
expect(Math.hypot(...result.final.object.map((v, i) => v - goal[i]))).toBeLessThan(
preset.placementTolerance,
);
expect(result.final.objectSpeed).toBeLessThan(preset.placementSpeedMax);
expect(result.final.onGoalSupport).toBe(true);
expect(result.final.fingerForces.every((force) => force < preset.fingerForceMin)).toBe(true);
expect(result.final.opening).toBeGreaterThan(0.65);
expect(
Math.hypot(...result.final.object.map((v, i) => v - result.final.tcp[i])),
).toBeGreaterThanOrEqual(preset.retreatMin);
expect(
result.trace.filter((s) => s.phase === 'carry' && s.secure && !s.supported).length,
).toBeGreaterThan(100);
expect(errors).toEqual([]);
} finally {
await page.evaluate(() => window.lekiwiAgent.dispose());
}
});
}
for (const seed of preset.frozenSeeds) {
test(`mock 决策闭环:冻结种子 ${seed.id},逐技能门禁与独立物理成功`, 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((id) => window.lekiwiAgent.task(id), seed.id);
await writeFile(info.outputPath('mock-closed-loop.json'), JSON.stringify(result, null, 2));
console.log('mock closed loop', {
state: result.state,
error: result.error,
transported: result.transported,
llm: result.llmCalls,
jev: result.jevCalls,
simTime: result.simTime,
});
expect(result.ownerAtStart).toBe('agent');
expect(result.mode).toBe('mock');
expect(result.state, result.error).toBe('succeeded');
expect(result.succeeded).toBe(true);
expect(result.transported).toBeGreaterThanOrEqual(preset.transportMin);
expect(result.maxJointSpeed).toBeLessThanOrEqual(preset.jointSpeedStop);
expect(result.llmCalls).toBe(1);
expect(result.jevCalls).toBe(11);
expect(result.results).toHaveLength(11);
expect(result.failures).toEqual([]);
expect(result.sample.onGoalSupport).toBe(true);
expect(result.sample.fingerForces.every((v) => v < preset.fingerForceMin)).toBe(true);
expect(result.sample.opening).toBeGreaterThanOrEqual(0.65);
expect(
Math.hypot(...result.sample.object.map((v, i) => v - result.sample.tcp[i])),
).toBeGreaterThanOrEqual(preset.retreatMin);
} finally {
await page.evaluate(() => window.lekiwiAgent.dispose());
}
});
}
test('agent 控制权下同一物理时钟完成基线,不建立第二个环境循环', 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(() => window.lekiwiAgent.baseline(0, true));
await writeFile(info.outputPath('governed-baseline.json'), JSON.stringify(result, null, 2));
expect(result.ownerAtStart).toBe('agent');
expect(result.status, result.error).toBe('succeeded');
expect(result.transported).toBeGreaterThanOrEqual(0.5);
} finally {
await page.evaluate(() => window.lekiwiAgent.dispose());
}
});