feat: 建立可扩展网页后端抽象

拆分后端定义、注册表、DOM 适配器和 sandbox preload,统一千问与元宝的就绪、登录和完整文本上报契约。

AI-assisted-by: Codex
AI-model: gpt-5.6-sol
AI-reasoning-effort: medium
Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
2026-08-23 02:33:53 +08:00
co-authored by Codex
parent 4d41cc3de5
commit f1f41f4f48
10 changed files with 466 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { backendOwnsUrl } from '../src/backends/contracts';
import { getBackend, listBackends, requireBackend } from '../src/backends/registry';
test('后端注册表包含千问和元宝且 ID 唯一', () => {
const backends = listBackends();
assert.deepEqual(backends.map(({ id }) => id), ['qianwen', 'yuanbao']);
assert.equal(new Set(backends.map(({ id }) => id)).size, backends.length);
assert.equal(getBackend('qianwen')?.label, '千问');
assert.equal(getBackend('missing'), undefined);
assert.throws(() => requireBackend('missing'), /未知后端/);
});
test('后端 URL 校验使用精确 origin', () => {
const qianwen = requireBackend('qianwen');
assert.equal(backendOwnsUrl(qianwen, 'https://www.qianwen.com/chat/1'), true);
assert.equal(backendOwnsUrl(qianwen, 'https://www.qianwen.com.evil.example/'), false);
assert.equal(backendOwnsUrl(qianwen, 'not a url'), false);
});