重做AGC智能体设置界面
Project CI / Repository checks (push) Successful in 1m32s
Project CI / Frontend tests (push) Successful in 3m2s
Project CI / Backend tests (push) Successful in 4m5s
Project CI / Native shell tests (push) Successful in 14m27s

将常用设置、Agent 模型、连接工具和高级参数分层展示

补充保存中、保存成功和失败状态反馈

更新设置页测试与项目决策记录
This commit is contained in:
kdletters
2026-08-12 20:58:16 +08:00
parent 82957fe1d4
commit e04a8310a0
5 changed files with 1719 additions and 977 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -4305,6 +4305,7 @@ export function registerProjectSupervisorSurfaceTests() {
expect(
await screen.findByRole('dialog', { name: '运行时配置' }),
).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: /连接与工具/ }));
expect(screen.getByLabelText('External Editor Base URL')).toHaveProperty(
'value',
'http://127.0.0.1:8082',
@@ -10188,7 +10189,8 @@ export function registerProjectAgentStatusTests() {
},
);
let runtimeUpdateHandler:
((event: { payload: Record<string, unknown> }) => void) | null = null;
| ((event: { payload: Record<string, unknown> }) => void)
| null = null;
const listen = vi.fn(
async (
eventName: string,
@@ -412,16 +412,13 @@ export function registerRuntimeSettingsTests() {
const dialog = await screen.findByRole('dialog', { name: '运行时配置' });
expect(await screen.findByDisplayValue('gpt-launcher')).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: /高级参数/ }));
expect(screen.getByLabelText('LLM 超时 ms')).toHaveProperty(
'value',
'1000',
);
expect(screen.getByLabelText('LLM 重试次数')).toHaveProperty('value', '0');
expect(screen.getByLabelText('LLM 退避 ms')).toHaveProperty('value', '1');
expect(screen.getByLabelText('LLM API 类型')).toHaveProperty(
'value',
'openai_responses',
);
expect(screen.getByLabelText('LLM 上下文窗口 tokens')).toHaveProperty(
'value',
'128000',
@@ -434,19 +431,11 @@ export function registerRuntimeSettingsTests() {
'value',
'12000',
);
expect(screen.getByLabelText('External Editor Base URL')).toHaveProperty(
fireEvent.click(screen.getByRole('button', { name: /常用设置/ }));
expect(screen.getByLabelText('LLM API 类型')).toHaveProperty(
'value',
'http://127.0.0.1:8082',
'openai_responses',
);
expect(screen.getByLabelText('External Editor API Key')).toHaveProperty(
'type',
'password',
);
expect(
screen
.getByLabelText('External Editor API Key')
.getAttribute('autocomplete'),
).toBe('off');
fireEvent.change(screen.getByLabelText('LLM 模型'), {
target: { value: 'gpt-launcher-updated' },
});
@@ -466,10 +455,12 @@ export function registerRuntimeSettingsTests() {
});
});
expect(
await screen.findByText(
'已保存:/home/test/AppData/game-creator.config.json',
),
).not.toBeNull();
(
await screen.findByText(
'已保存:/home/test/AppData/game-creator.config.json',
)
).getAttribute('data-tone'),
).toBe('success');
fireEvent.mouseDown(dialog.parentElement as HTMLElement);
expect(screen.queryByRole('dialog', { name: '运行时配置' })).toBeNull();
});
@@ -569,6 +560,7 @@ export function registerRuntimeSettingsTests() {
renderLauncherAt('/?launcher');
fireEvent.click(screen.getByRole('button', { name: '配置' }));
fireEvent.click(await screen.findByRole('button', { name: /连接与工具/ }));
const mcpRegion = await screen.findByRole('region', {
name: 'MCP servers',
});
@@ -869,15 +861,30 @@ export function registerPublishedRuntimeSettingsTests() {
expect(
screen.getByLabelText('LLM API Key').getAttribute('autocomplete'),
).toBe('off');
expect(screen.getByLabelText('External Editor API Key')).toHaveProperty(
'type',
'password',
);
fireEvent.click(screen.getByRole('button', { name: /连接与工具/ }));
expect(
screen.getByLabelText('External Editor API Key'),
).toHaveProperty('type', 'password');
expect(
screen
.getByLabelText('External Editor API Key')
.getAttribute('autocomplete'),
).toBe('off');
fireEvent.click(screen.getByRole('button', { name: /Agent 模型/ }));
fireEvent.click(screen.getByRole('button', { name: /Planner planner/ }));
fireEvent.click(
screen.getByRole('button', {
name: /生成首版美术素材.*art-asset-plan/,
}),
);
fireEvent.click(
screen.getByRole('button', { name: /Generator generator/ }),
);
fireEvent.click(
screen.getByRole('button', {
name: /项目总控 Agent project-supervisor/,
}),
);
expect(screen.getByLabelText('Planner LLM API Key')).toHaveProperty(
'type',
'password',
@@ -898,10 +905,6 @@ export function registerPublishedRuntimeSettingsTests() {
'value',
'claude-3-5-sonnet-latest',
);
expect(screen.getByLabelText('LLM 推理档')).toHaveProperty(
'value',
'medium',
);
expect(screen.getByLabelText('Planner LLM 推理档')).toHaveProperty(
'value',
'default',
@@ -923,10 +926,6 @@ export function registerPublishedRuntimeSettingsTests() {
expect(
screen.getByLabelText('生成首版美术素材 (art/Asset) LLM 流式请求'),
).toHaveProperty('value', 'true');
expect(screen.getByLabelText('LLM 联网检索')).toHaveProperty(
'checked',
false,
);
expect(screen.getByLabelText('Planner LLM 联网检索')).toHaveProperty(
'value',
'false',
@@ -942,6 +941,12 @@ export function registerPublishedRuntimeSettingsTests() {
expect(supervisorWebSearch).toHaveProperty('value', 'true');
fireEvent.change(supervisorWebSearch, { target: { value: 'false' } });
expect(supervisorWebSearch).toHaveProperty('value', 'false');
fireEvent.click(screen.getByRole('button', { name: /常用设置/ }));
expect(screen.getByLabelText('LLM 联网检索')).toHaveProperty(
'checked',
false,
);
fireEvent.click(screen.getByRole('button', { name: /高级参数/ }));
expect(screen.getByLabelText('LLM 上下文窗口 tokens')).toHaveProperty(
'value',
'128000',
@@ -954,11 +959,17 @@ export function registerPublishedRuntimeSettingsTests() {
'value',
'12000',
);
fireEvent.click(screen.getByRole('button', { name: /Agent 模型/ }));
expect(screen.getByLabelText('Planner 上下文窗口 tokens')).toHaveProperty(
'value',
'',
);
fireEvent.click(screen.getByRole('button', { name: /常用设置/ }));
expect(screen.getByLabelText('LLM 推理档')).toHaveProperty(
'value',
'medium',
);
fireEvent.change(screen.getByLabelText('LLM API Key'), {
target: { value: 'unit-new-secret-value' },
});
@@ -973,6 +984,7 @@ export function registerPublishedRuntimeSettingsTests() {
});
fireEvent.click(screen.getByLabelText('LLM 流式请求'));
fireEvent.click(screen.getByLabelText('LLM 联网检索'));
fireEvent.click(screen.getByRole('button', { name: /高级参数/ }));
fireEvent.change(screen.getByLabelText('LLM 上下文窗口 tokens'), {
target: { value: '160000' },
});
@@ -991,6 +1003,7 @@ export function registerPublishedRuntimeSettingsTests() {
fireEvent.change(screen.getByLabelText('LLM 退避 ms'), {
target: { value: '800' },
});
fireEvent.click(screen.getByRole('button', { name: /Agent 模型/ }));
fireEvent.change(screen.getByLabelText('Generator LLM API Key'), {
target: { value: 'generator-new-secret' },
});
@@ -1018,6 +1031,7 @@ export function registerPublishedRuntimeSettingsTests() {
target: { value: 'ark' },
},
);
fireEvent.click(screen.getByRole('button', { name: /连接与工具/ }));
fireEvent.change(screen.getByLabelText('External Editor Base URL'), {
target: { value: 'http://127.0.0.1:8099' },
});
@@ -1092,10 +1106,12 @@ export function registerPublishedRuntimeSettingsTests() {
within(runtimeConfigDialog).getByRole('button', { name: '读取' }),
);
expect(await screen.findByText(/已读取:/)).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: /常用设置/ }));
expect(screen.getByLabelText('LLM 联网检索')).toHaveProperty(
'checked',
true,
);
fireEvent.click(screen.getByRole('button', { name: /Agent 模型/ }));
expect(screen.getByLabelText('项目总控 Agent LLM 联网检索')).toHaveProperty(
'value',
'false',
@@ -1107,6 +1123,7 @@ export function registerPublishedRuntimeSettingsTests() {
'generator-new-secret',
);
fireEvent.click(screen.getByRole('button', { name: /高级参数/ }));
fireEvent.change(screen.getByLabelText('LLM 超时 ms'), {
target: { value: '' },
});
@@ -1137,6 +1154,7 @@ export function registerPublishedRuntimeSettingsTests() {
);
expect(screen.getByText('已恢复默认配置,保存后生效')).not.toBeNull();
fireEvent.click(screen.getByRole('button', { name: /常用设置/ }));
expect(screen.getByLabelText('Agent 模式')).toHaveProperty(
'value',
'codex_app_server',
@@ -1158,10 +1176,12 @@ export function registerPublishedRuntimeSettingsTests() {
'checked',
false,
);
fireEvent.click(screen.getByRole('button', { name: /Agent 模型/ }));
expect(screen.getByLabelText('项目总控 Agent LLM 联网检索')).toHaveProperty(
'value',
'',
);
fireEvent.click(screen.getByRole('button', { name: /高级参数/ }));
expect(screen.getByLabelText('LLM 上下文窗口 tokens')).toHaveProperty(
'value',
'128000',
@@ -1174,10 +1194,10 @@ export function registerPublishedRuntimeSettingsTests() {
'value',
'12000',
);
expect(screen.getByLabelText('External Editor Base URL')).toHaveProperty(
'value',
'http://127.0.0.1:8082',
);
fireEvent.click(screen.getByRole('button', { name: /连接与工具/ }));
expect(
screen.getByLabelText('External Editor Base URL'),
).toHaveProperty('value', 'http://127.0.0.1:8082');
fireEvent.click(
within(runtimeConfigDialog).getByRole('button', { name: '保存' }),
);
@@ -7145,6 +7145,12 @@
- HTTP 传输边界:根 H5 包不得依赖 Tauri guest 插件;AGC 独立包保留 `@tauri-apps/plugin-http`。Rust 插件显式关闭默认特性,只启用 `charset``cookies``http2``rustls-tls`,避免 `reqwest/system-proxy` 通过 Cargo feature union 把画布、Provider、Runtime 与本地回环夹具统一接入 OS 自动系统代理;如未来产品要求正式客户端继承系统代理,必须按各客户端明确设计并单独完成跨平台验证。
- 运行决策:Godot 项目提交给 Project Supervisor 时使用 `standard` Run Profile,避免触发 Web 专用 `game/index.html`、HTTP preview 与自主 Web 完成门。Godot 编辑器启动和内嵌运行预览不在本切片范围。
## 2026-08-12 AGC Agent 设置分层界面
- `RuntimeConfigDialog` 保持现有配置字段、持久化格式、Runner 读取和 MCP 测试语义,只重构界面信息架构。
- 设置页固定为“常用设置 / Agent 模型 / 连接与工具 / 高级参数”四类;默认只展示运行方式与默认模型,逐 Agent 覆盖按角色折叠,MCP、External Editor 连接和低频运行参数不进入首屏。
- 设置壳复用 AGC 平台 tokens、按钮层级和响应式断点;桌面使用双栏 modal,窄屏改为横向分类导航和单列表单,底部保存动作常驻。
## 2026-08-11 Game Agent 通用 Goal Contract 与动态验收图
- 决策:固定规则只负责安全、事实完整性和完成协议。根 Project Supervisor 必须先用 `agent.goal_contract` 把自己对当前用户最终意图的理解冻结为结构化 outcome、硬约束、偏好、禁止假设、开放问题和 acceptance nodes;同一根 Run 不允许改写。该合同摘要进入共享黑板,权威 JSON 绑定可信 root Run Profile、source task SHA-256 与 fingerprint。