重做AGC智能体设置界面
将常用设置、Agent 模型、连接工具和高级参数分层展示 补充保存中、保存成功和失败状态反馈 更新设置页测试与项目决策记录
This commit is contained in:
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。
|
||||
|
||||
Reference in New Issue
Block a user