Files
Mujoco_WASM/web_platform/e2e/lekiwi.agent.subscription.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
5.3 KiB
TypeScript
Raw 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.
import { expect, test } from '@playwright/test';
import { resolve } from 'node:path';
import { readFile, writeFile } from 'node:fs/promises';
import { subscriptionOperation } from './fixtures/subscriptionSession';
test.use({ trace: 'off', video: 'off' });
test('显式 opt-in:已人工登录的 ChatGPT 订阅 + Jev 主视口物理验收与退出', async ({
page,
}, info) => {
test.skip(
process.env.LEKIWI_LIVE_SUBSCRIPTION !== '1',
'需要用户在隔离官方页面完成登录;不自动发起登录或使用全局账号',
);
const session = await subscriptionOperation('connect');
const token = String(session.token);
try {
expect(session.llmProtocol).toBe('codex');
const before = await subscriptionOperation('status');
expect(before.loggedIn).toBe(true);
const limitsBefore = await subscriptionOperation('limits');
await page.goto('/');
await page
.locator('input[type="file"]')
.first()
.setInputFiles(resolve('build/lekiwi/lekiwi-v1.zip'));
const dialog = page.getByRole('dialog', { name: '配置 URDF 仿真组件' });
await expect(dialog).toBeVisible({ timeout: 30000 });
await dialog.getByLabel('URDF 机器人 profile').selectOption('lekiwi-v1');
await dialog.getByRole('button', { name: '转换并加载' }).click();
await expect(page.getByRole('button', { name: '▶ 播放' })).toBeEnabled({ timeout: 60000 });
await page.getByRole('tab', { name: '控制台', exact: true }).click();
await page.getByRole('button', { name: 'LeKiwi 智能抓放', exact: true }).click();
const panel = page.getByLabel('LeKiwi 智能抓放任务', { exact: true });
await panel.getByText('模型连接与官方订阅登录', { exact: true }).click();
await panel.getByLabel('本机模型服务', { exact: true }).fill(String(session.address));
await panel.getByLabel('本机服务令牌', { exact: true }).fill(token);
await panel.getByRole('button', { name: '连接本机模型服务', exact: true }).click();
await expect(panel).toContainText('本机桥已连接');
await expect(panel.getByLabel('LLM 协议', { exact: true })).toHaveValue('codex');
await expect(panel.getByLabel('LLM API Key', { exact: true })).toHaveCount(0);
await panel.getByText(/ChatGPT 订阅 · 官方/).click();
await panel.getByRole('button', { name: '刷新账号', exact: true }).click();
await expect(panel).toContainText('ChatGPT 已登录(仅本次服务会话)');
await panel.getByRole('button', { name: '查询官方型号', exact: true }).click();
await expect(panel.getByLabel('LLM 型号', { exact: true })).toHaveValue(
String(session.llmModel),
);
await expect(panel.getByLabel('JEV 型号', { exact: true })).toHaveValue('typesafe/jev-1.13');
await panel.getByText('模型连接与官方订阅登录', { exact: true }).click();
await panel.getByLabel('智能任务决策模式').selectOption('api');
await panel.getByRole('button', { name: '开始任务(真实 API)', exact: true }).click();
await expect(panel.getByTestId('agent-task-state')).toContainText(
/物理验收成功|失败 \/ 安全停止|已取消/,
{ timeout: 240000 },
);
const download = page.waitForEvent('download');
await panel.getByRole('button', { name: '导出任务证据', exact: true }).click();
const data = JSON.parse(await readFile((await (await download).path())!, 'utf8'));
const after = await subscriptionOperation('status');
const evidence = {
source: 'real-chatgpt-subscription-plus-openrouter-jev',
before,
after,
limitsBefore,
...data,
};
const encoded = JSON.stringify(evidence, null, 2);
if (encoded.includes(token) || encoded.includes('auth.openai.com/'))
throw new Error('任务证据包含认证信息');
await writeFile(info.outputPath('subscription-physical-evidence.json'), encoded);
console.log('真实订阅回合', {
state: data.state,
error: data.error,
model: session.llmModel,
llm: data.llmCalls,
jev: data.jevCalls,
simTime: data.sample.time,
transported: data.transported,
});
expect(data.state, data.error).toBe('succeeded');
expect(data.succeeded).toBe(true);
expect(data.transported).toBeGreaterThanOrEqual(0.5);
expect(data.llmCalls).toBe(1);
expect(data.jevCalls).toBe(11);
expect(data.receipts).toHaveLength(12);
expect(data.receipts.find((r: { kind: string }) => r.kind === 'plan').provider).toBe('codex');
expect(after.checkedModels).toContain(session.llmModel);
await page.screenshot({ path: info.outputPath('subscription-workbench.png') });
await panel.getByText('模型连接与官方订阅登录', { exact: true }).click();
await panel.getByRole('button', { name: '退出隔离账号', exact: true }).click();
await expect(panel).toContainText('已退出本次隔离会话');
const loggedOut = await subscriptionOperation('status');
expect(loggedOut.loggedIn).toBe(false);
await writeFile(
info.outputPath('subscription-logout.json'),
JSON.stringify(loggedOut, null, 2),
);
} catch (error) {
await page.close().catch(() => undefined);
// eslint-disable-next-line preserve-caught-error -- Playwright causes can contain the private bridge token.
throw new Error(String(error).replaceAll(token, '[redacted]'));
}
});