feat: v0.4.1 质量加固版 — 工程化基线 + 安全加固 + 测试补齐 + 体验升级
工程化(从零到一): - 新增 Gitea Actions CI(debian-latest):类型检查 + Lint + 单元测试 + 产物编译验证 - 新增 husky + lint-staged 预提交钩子(lint-staged + typecheck 门禁) - 移除坏脚本 test:e2e(无 Playwright 配置必失败);prebuild 改用内置 fs.rmSync - 依赖清理:移除死依赖 sql.js(2MB)/@playwright/test,@types/shell-quote 移至 devDependencies 安全加固: - PolicyEngine 频率限制按会话隔离(多会话并发不再互抢配额) - ConfirmationHook 拒绝记忆加 10 分钟 TTL + 恢复询问入口(新增 2 个 IPC 通道) - Windows run_command 白名单工具(git/node/npm/npx/pnpm/yarn/tsc)改走 cmd.exe /c + 参数数组执行,收窄 shell 注入面 - web_search 四引擎 HTML 解析迁移 node-html-parser(结构化主层 + 正则降级) 缺陷修复(测试驱动发现): - mapError 大小写缺陷:网络错误码永远落入 UNKNOWN 无法触发重试 - 搜狗解析器自我过滤:相对链接补全后又被 sogou.com 过滤导致结果全丢 - 百度复合类名重复收录:class="result c-container" 被双重匹配 测试补齐(113 → 194 用例): - 新增 5 个测试文件:sse-stream / base-adapter / confirmation-hook / ipc-agent 编排链路 / web-search 解析器 - 覆盖 sendMessage 全分支、SSE 流解析、错误映射、确认钩子竞态/超时/批量审批 体验升级: - OutputValidator 验证结果可见化(VALIDATION 流事件 → 聊天流提示卡) - SettingsModal 巨型组件拆分(1503 行 → 10 个文件,可独立维护) - MessageList 接入 react-virtuoso 真虚拟滚动(千条消息恒定开销) - MCP 新增 streamable HTTP 传输支持(SDK 内置传输 + DB 迁移 6 + UI 双模式)
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* AgentSettings — Agent 配置 Tab
|
||||
*
|
||||
* 从 SettingsModal.tsx 提取(v0.4.1 拆分)。
|
||||
* 功能:迭代次数 / 总超时 / 工具超时 / 确认超时 / 思考模式配置。
|
||||
*/
|
||||
|
||||
import {
|
||||
TextField,
|
||||
Select,
|
||||
MenuItem,
|
||||
Stack,
|
||||
Typography,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
InputLabel,
|
||||
FormControl,
|
||||
} from '@mui/material';
|
||||
import { useConfig } from './useConfig';
|
||||
|
||||
export function AgentSettings() {
|
||||
const [maxIter, setMaxIter] = useConfig('agent.maxIterations', 20);
|
||||
const [timeout, setTimeout_] = useConfig('agent.totalTimeoutMs', 600000);
|
||||
const [thinking, setThinking] = useConfig('agent.enableThinking', true);
|
||||
const [thinkingEffort, setThinkingEffort] = useConfig('agent.thinkingEffort', 'high');
|
||||
const [confirmTimeout, setConfirmTimeout] = useConfig('agent.confirmationTimeoutMs', 120000);
|
||||
const [toolExecTimeout, setToolExecTimeout] = useConfig('agent.toolExecutionTimeoutMs', 120000);
|
||||
|
||||
const MAX_ITER_OPTIONS = [10, 20, 50, 85, 128, 256, 512];
|
||||
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
|
||||
Agent 配置
|
||||
</Typography>
|
||||
<FormControl size="small">
|
||||
<InputLabel>最大迭代次数</InputLabel>
|
||||
<Select
|
||||
value={maxIter}
|
||||
label="最大迭代次数"
|
||||
onChange={(e) => setMaxIter(e.target.value as number)}
|
||||
>
|
||||
{MAX_ITER_OPTIONS.map((n) => (
|
||||
<MenuItem key={n} value={n}>
|
||||
{n}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<TextField
|
||||
size="small"
|
||||
label="总超时(秒)"
|
||||
type="number"
|
||||
value={timeout / 1000}
|
||||
onChange={(e) => {
|
||||
const v = Number(e.target.value);
|
||||
if (v >= 120 && v <= 3600) setTimeout_(v * 1000);
|
||||
}}
|
||||
slotProps={{ htmlInput: { min: 120, max: 3600, step: 30 } }}
|
||||
/>
|
||||
<TextField
|
||||
size="small"
|
||||
label="工具执行超时(秒)"
|
||||
type="number"
|
||||
value={toolExecTimeout / 1000}
|
||||
onChange={(e) => {
|
||||
const v = Number(e.target.value);
|
||||
if (v >= 10 && v <= 600) setToolExecTimeout(v * 1000);
|
||||
}}
|
||||
slotProps={{ htmlInput: { min: 10, max: 600, step: 10 } }}
|
||||
helperText="单个工具执行的最大时长,超时自动终止(10~600 秒)"
|
||||
/>
|
||||
<TextField
|
||||
size="small"
|
||||
label="工具确认超时(秒)"
|
||||
type="number"
|
||||
value={confirmTimeout / 1000}
|
||||
onChange={(e) => {
|
||||
const v = Number(e.target.value);
|
||||
if (v >= 30 && v <= 600) setConfirmTimeout(v * 1000);
|
||||
}}
|
||||
slotProps={{ htmlInput: { min: 30, max: 600, step: 10 } }}
|
||||
helperText="用户未响应工具确认时,超时自动视为拒绝(30~600 秒)"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={thinking}
|
||||
onChange={(e) => setThinking(e.target.checked)}
|
||||
size="small"
|
||||
/>
|
||||
}
|
||||
label={<Typography variant="body2">启用思考模式</Typography>}
|
||||
/>
|
||||
{thinking && (
|
||||
<FormControl size="small">
|
||||
<InputLabel>思考强度</InputLabel>
|
||||
<Select
|
||||
value={thinkingEffort}
|
||||
label="思考强度"
|
||||
onChange={(e) => setThinkingEffort(e.target.value)}
|
||||
>
|
||||
<MenuItem value="low">Low</MenuItem>
|
||||
<MenuItem value="medium">Medium</MenuItem>
|
||||
<MenuItem value="high">High</MenuItem>
|
||||
<MenuItem value="max">Max</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user