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
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
104 lines
4.7 KiB
TypeScript
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());
|
|
}
|
|
});
|