优化项目对话、刷新续流、实时滚动与工具状态恢复 (#245)

* feat(chat): add project-based conversation sidebar

* feat(chat): refine Codex-style conversation UI

* feat(chat): add Codex-style conversation workflow

* feat(ui): 优化对话框与项目侧边栏交互

* fix(chat): 修复暗色输入框圆角填色

* fix(chat): 恢复输入区分层错位布局

* fix(hitl): isolate reviewer state per conversation

* feat(hitl): 增加双入口审批与倒计时进度

* fix(hitl): 汇总项目审批并隔离对话状态

* fix(ui): 修复审批状态与无项目新任务

* fix(ui): 优化审批状态与对话切换性能

* fix(ui): 修复中断任务审批仍计时

* fix(ui): 修复多对话并发切换卡顿

* fix(hitl): 主动同步审批并关闭中断状态

* fix(ui): 固定项目审批汇总为绿色

* feat(ui): 同步系统模型与推理强度

* feat(ui): 完善项目侧栏预览与新建入口

* fix(ui): 防止无项目文件夹误展开

* fix(ui): 防止长历史对话滚动误触审批

* fix(ui): 修复对话操作并补充项目置顶

* fix(ui): 移除对话分组并调整项目置顶排序

* feat(ui): 优化迭代导航与审批交互

* fix(hitl): 将 write_file 加入内置免审批工具

* fix(chat): 支持回车发送与 Shift 回车换行

* fix(chat): 优化对话刷新与 Codex 风格交互

* fix(ui): 显示对话具体更新时间

* fix(ui): 优化对话刷新与项目加载

* fix(ui): 修复 Agent 审查文字裁切

* fix(chat): 修复刷新续流与多标签页同步

* fix(chat): 修复滚动跟随与中断任务终态

* fix(ui): 修复流式滚动跳动与工具状态恢复

* fix(ui): 修复刷新后流式输出停止粘底
This commit is contained in:
RuoJi6
2026-08-13 21:28:37 +08:00
committed by GitHub
parent b170f2c4b1
commit eb6bab574f
31 changed files with 10763 additions and 886 deletions
+121 -5
View File
@@ -508,6 +508,8 @@
"settingsIntroTitle": "Project settings",
"settingsIntroHint": "Configure project metadata and Agent authorization boundary; takes effect immediately for bound conversations after saving.",
"pinProject": "Pin project (show first in list)",
"pinProjectAction": "Pin project",
"unpinProjectAction": "Unpin project",
"pinFact": "Pin fact (prioritize in list and blackboard index)",
"editDescriptionPlaceholder": "Client/task notes, contacts, collaboration…",
"scopeTitle": "Test scope",
@@ -521,6 +523,7 @@
"archiveRestore": "Archive / Restore",
"archiveProject": "Archive",
"editProject": "Edit",
"renameProject": "Rename",
"restoreProjectActive": "Restore to active",
"projectActions": "Project actions",
"deleteProject": "Delete project",
@@ -538,11 +541,40 @@
},
"chat": {
"newChat": "New chat",
"newTask": "New task",
"toggleConversationPanel": "Collapse/expand conversation list",
"searchHistory": "Search history...",
"projectFolders": "Projects",
"projectFoldersLoadMoreRemaining": "Load more, {{count}} projects remaining",
"projectPreviewLabel": "Project information",
"projectPreviewStats": "{{total}} tasks · {{active}} open",
"projectPreviewNoDescription": "No project description",
"projectPreviewScope": "Test scope: {{scope}}",
"projectPreviewEdit": "Edit project",
"conversationPreviewJustNow": "Now",
"conversationPreviewMinutes": "{{count}} min",
"conversationPreviewHours": "{{count}}h",
"conversationPreviewDays": "{{count}}d",
"conversationPreviewDateTime": "{{year}}-{{month}}-{{day}} {{hour}}:{{minute}}",
"conversationPreviewNoProject": "No project",
"conversationPreviewDefaultMode": "Default",
"conversationPreviewUnread": "Unread update",
"conversationPreviewViewed": "Viewed",
"conversationPreviewConversation": "Conversation",
"returnToLatest": "Jump to latest message",
"completedUnread": "Completed, not viewed",
"newConversationInProject": "Start a new conversation in this project",
"newUnassignedConversation": "Start a new conversation without a project",
"conversationActions": "Conversation actions",
"renameConversationPrompt": "Enter a new title:",
"renameConversationTitle": "Rename conversation",
"renameConversationSubtitle": "The name will update in project folders and recent conversations",
"conversationTitleLabel": "Conversation name",
"conversationTitlePlaceholder": "Enter a conversation name",
"conversationGroups": "Conversation groups",
"addGroup": "New group",
"recentConversations": "Recent conversations",
"toggleRecentConversations": "Expand/collapse recent conversations",
"filterByProject": "Filter by project",
"filterAllProjects": "All projects",
"filterUnboundProjects": "Unbound",
@@ -571,7 +603,7 @@
"viewAttackChain": "View attack chain",
"selectRole": "Select role",
"defaultRole": "Default",
"inputPlaceholder": "Enter target or command... (type @ to select tools | Shift+Enter newline, Enter send)",
"inputPlaceholder": "Enter a target or command… @ select tools",
"selectFile": "Select file",
"uploadFile": "Upload file (multi-select or drag & drop)",
"readingAttachmentsDetail": "Reading attachment {{current}}/{{total}} · {{name}} · {{percent}}%",
@@ -587,10 +619,20 @@
"noMatchTools": "No matching tools",
"penetrationTestDetail": "Task execution details",
"expandDetail": "Expand details",
"turnElapsedRunning": "Processed for {{duration}}",
"turnElapsedComplete": "Took {{duration}}",
"turnElapsedCancelled": "Interrupted · Took {{duration}}",
"turnElapsedTimeout": "Timed out · Took {{duration}}",
"turnElapsedFailed": "Failed · Took {{duration}}",
"turnDurationSeconds": "{{seconds}} sec",
"turnDurationMinutes": "{{minutes}} min {{seconds}} sec",
"turnDurationHours": "{{hours}} hr {{minutes}} min",
"turnProcessAria": "{{state}}; expand or collapse execution details",
"turnNumber": "Turn {{number}}",
"turnPending": "Processing…",
"expandDetailLazyHint": "Expand details (loads iteration details on click)",
"loadingEarlierDetails": "Loading earlier entries…",
"loadingLaterDetails": "Loading newer entries…",
"backToLatestProgress": "↓ Back to latest",
"viewToolDetail": "View details",
"collapseToolDetail": "Collapse",
"liveTimelinePruned": "Collapsed the first {{count}} live process details. View the full record page by page after the task completes.",
@@ -617,6 +659,12 @@
"executeFailed": "Execution failed",
"callOpenAIFailed": "Call OpenAI failed",
"systemReadyMessage": "System is ready. Please enter your test requirements, and the system will automatically perform the corresponding security tests.",
"projectWelcomeMessage": "Current project: {{project}}. Enter your test requirements and the system will run the corresponding security tests.",
"noProjectWelcomeMessage": "No project is currently selected. Enter your test requirements and the system will run the corresponding security tests.",
"projectWelcomeTitlePrefix": "What should be tested in ",
"projectWelcomeTitleSuffix": "?",
"noProjectWelcomeTitle": "What should be tested?",
"welcomeSubtitle": "Enter your test requirements and the system will automatically run the corresponding security tests.",
"addNewGroup": "+ New group",
"callNumber": "Call #{{n}}",
"iterationRound": "Iteration {{n}}",
@@ -674,15 +722,16 @@
"loadFailedRetry": "Load failed, please retry",
"dataFormatError": "Data format error",
"progressInProgress": "Penetration test in progress...",
"scrollToBottom": "Scroll to bottom",
"scrollToBottomHasNew": "↓ New content below",
"scrollToBottomNew": "↓ {{count}} new update(s)",
"executionFailed": "Execution failed",
"penetrationTestComplete": "Penetration test complete",
"yesterday": "Yesterday",
"historyGroupToday": "Today",
"historyGroupLast7Days": "Past 7 days",
"historyGroupEarlier": "Older",
"conversationPreviewJustNow": "Just now",
"conversationPreviewMinutes": "{{count}} min",
"conversationPreviewHours": "{{count}} hr",
"conversationPreviewDays": "{{count}} days",
"agentModeSelectAria": "Choose conversation execution mode",
"agentModePanelTitle": "Conversation mode",
"agentModeEinoSingle": "Eino single (ADK)",
@@ -711,6 +760,21 @@
"sessionSettingsTitle": "Session settings",
"sessionSettingsAria": "Open session settings",
"sessionSettingsHint": "AI channel, reasoning, and HITL settings only affect future messages.",
"sessionShortcutAuditAgent": "Agent review",
"modelSettingsAria": "Choose model and reasoning effort",
"systemModelPickerTitle": "Choose system model",
"systemModelField": "Model",
"systemModelLoading": "Fetching model list…",
"systemModelLoaded": "Loaded {count} models",
"systemModelCurrent": "Current",
"systemModelSaving": "Saving…",
"systemModelSaved": "Saved automatically",
"systemModelLoadFailed": "Failed to fetch models",
"systemModelSaveFailed": "Failed to save model",
"systemModelApplyFailed": "Failed to apply model",
"systemModelNeedApiKey": "Configure an API key in System Settings first",
"systemModelRetry": "Try again",
"sessionShortcutHuman": "Human approval",
"aiChannelLabel": "AI channel",
"aiChannelDefault": "Use default channel",
"aiChannelDefaultShort": "Default channel",
@@ -738,6 +802,12 @@
"hitlApplyOkWhitelistYaml": "Tool whitelist merged into config.yaml and active. Session settings are saved automatically.",
"hitlApplyOkLocal": "Saved in this browser.",
"hitlApplyFail": "Failed to sync to server",
"hitlTimeoutLabel": "Approval wait limit",
"hitlTimeoutOneMinute": "1 minute",
"hitlTimeoutFiveMinutes": "5 minutes",
"hitlTimeoutTenMinutes": "10 minutes",
"hitlTimeoutUnlimited": "No limit",
"hitlTimeoutHint": "Unanswered requests are rejected automatically when time expires; approval cards show the countdown.",
"hitlStatusOff": "Human-in-the-loop: Off"
},
"hitl": {
@@ -763,6 +833,52 @@
"tabStrategy": "Audit strategy",
"tabWhitelist": "Tool whitelist",
"pendingTitle": "Pending approvals",
"auditReviewing": "Automatic review in progress",
"auditReviewEditing": "Automatically reviewing and correcting",
"auditReviewExplanation": "A carefully prompted review agent is reviewing this request. It will run only after approval.",
"auditApproved": "Audit Agent approved",
"auditEditedApproved": "Audit Agent edited parameters and approved",
"auditRejected": "Audit Agent rejected",
"waitingHumanApproval": "Waiting for human approval",
"waitingHumanReview": "Waiting for human review",
"humanApprovalExplanation": "This tool call needs your confirmation before it can run.",
"humanReviewExplanation": "Review and optionally edit the parameters before allowing execution.",
"humanApproved": "Allowed once",
"humanEditedApproved": "Edited parameters and allowed",
"humanRejected": "Human approval rejected",
"viewEditedArgs": "View edited parameters",
"reviewArgs": "Review parameters (JSON)",
"commentOptional": "Comment (optional)",
"commentPlaceholder": "For example: read-only operations only",
"reject": "Reject",
"allowOnce": "Allow once",
"saveEditedAndAllow": "Save edits and allow",
"waitingApprovalShort": "Waiting for approval",
"waitingApprovalCount": "Waiting approval {{count}}",
"approvalUrgencyUnlimited": "Approval has no time limit",
"approvalUrgencyMoreThanThree": "Earliest approval expires in more than 3 minutes",
"approvalUrgencyMoreThanFive": "Earliest approval expires in more than 5 minutes",
"approvalUrgencyThreeToFive": "Earliest approval expires in 35 minutes",
"approvalUrgencyOneToThree": "Earliest approval expires in 13 minutes",
"approvalUrgencyWithinOne": "Earliest approval expires within 1 minute",
"requestGeneric": "Allow CyberStrikeAI to call {{tool}}?",
"requestVisitUrl": "Allow CyberStrikeAI to visit {{url}}?",
"requestBrowser": "Allow CyberStrikeAI to use the browser?",
"requestCommand": "Allow CyberStrikeAI to run this command?",
"requestFile": "Allow CyberStrikeAI to modify {{path}}?",
"requestFiles": "Allow CyberStrikeAI to modify files?",
"toolTerminal": "Terminal",
"toolFiles": "Files",
"viewRequestDetails": "View request details",
"editRequestDetails": "View or edit request parameters",
"addApprovalComment": "Add approval comment (optional)",
"timeoutAutoReject": "Automatically rejects at expiry",
"timeoutUnlimited": "No time limit",
"expiredAutoRejected": "Approval timed out; rejecting automatically…",
"taskClosedApprovalUnavailable": "Task ended; approval is unavailable",
"taskInterrupted": "Task interrupted",
"interruptedApprovalCancelled": "Task interrupted; approval cancelled",
"expiredRejected": "Approval timed out and was rejected",
"searchLabel": "Search",
"searchPlaceholder": "Tool, conversation, payload, comment…",
"searchApply": "Search",
+121 -5
View File
@@ -496,6 +496,8 @@
"settingsIntroTitle": "项目设置",
"settingsIntroHint": "配置项目元数据与 Agent 授权边界,保存后即时生效于绑定对话。",
"pinProject": "置顶项目(列表优先显示)",
"pinProjectAction": "置顶项目",
"unpinProjectAction": "取消置顶",
"pinFact": "置顶事实(列表与黑板索引优先)",
"editDescriptionPlaceholder": "客户/任务备注、协作说明、联系人…",
"scopeTitle": "测试范围",
@@ -509,6 +511,7 @@
"archiveRestore": "归档 / 恢复",
"archiveProject": "归档",
"editProject": "编辑",
"renameProject": "重命名",
"restoreProjectActive": "恢复为进行中",
"projectActions": "项目操作",
"deleteProject": "删除项目",
@@ -526,11 +529,40 @@
},
"chat": {
"newChat": "新对话",
"newTask": "新任务",
"toggleConversationPanel": "折叠/展开对话列表",
"searchHistory": "搜索历史记录...",
"projectFolders": "项目",
"projectFoldersLoadMoreRemaining": "加载更多,剩余 {{count}} 个项目",
"projectPreviewLabel": "项目信息",
"projectPreviewStats": "{{total}} 个任务 · {{active}} 个已开启",
"projectPreviewNoDescription": "暂无项目说明",
"projectPreviewScope": "测试范围:{{scope}}",
"projectPreviewEdit": "编辑项目",
"conversationPreviewJustNow": "刚刚",
"conversationPreviewMinutes": "{{count}} 分钟",
"conversationPreviewHours": "{{count}} 小时",
"conversationPreviewDays": "{{count}} 天",
"conversationPreviewDateTime": "{{year}}年{{month}}月{{day}}日 {{hour}}:{{minute}}",
"conversationPreviewNoProject": "未绑定项目",
"conversationPreviewDefaultMode": "默认",
"conversationPreviewUnread": "有未读更新",
"conversationPreviewViewed": "已查看",
"conversationPreviewConversation": "对话",
"returnToLatest": "回到最新消息",
"completedUnread": "已完成,尚未查看",
"newConversationInProject": "在此项目中新建对话",
"newUnassignedConversation": "新建无项目对话",
"conversationActions": "对话操作",
"renameConversationPrompt": "请输入新标题:",
"renameConversationTitle": "重命名对话",
"renameConversationSubtitle": "修改后会同步更新项目文件夹和最近对话中的名称",
"conversationTitleLabel": "对话名称",
"conversationTitlePlaceholder": "请输入对话名称",
"conversationGroups": "对话分组",
"addGroup": "新建分组",
"recentConversations": "最近对话",
"toggleRecentConversations": "展开/折叠最近对话",
"filterByProject": "按项目筛选",
"filterAllProjects": "全部项目",
"filterUnboundProjects": "未绑定项目",
@@ -559,7 +591,7 @@
"viewAttackChain": "查看攻击链",
"selectRole": "选择角色",
"defaultRole": "默认",
"inputPlaceholder": "输入测试目标或命令... (输入 @ 选择工具 | Shift+Enter 换行,Enter 发送)",
"inputPlaceholder": "输入测试目标或命令… @ 选择工具",
"selectFile": "选择文件",
"uploadFile": "上传文件(可多选或拖拽到此处)",
"readingAttachmentsDetail": "读取附件 {{current}}/{{total}} · {{name}} · {{percent}}%",
@@ -575,10 +607,20 @@
"noMatchTools": "没有匹配的工具",
"penetrationTestDetail": "任务执行详情",
"expandDetail": "展开详情",
"turnElapsedRunning": "已处理 {{duration}}",
"turnElapsedComplete": "耗时 {{duration}}",
"turnElapsedCancelled": "已中断 · 耗时 {{duration}}",
"turnElapsedTimeout": "已超时 · 耗时 {{duration}}",
"turnElapsedFailed": "执行失败 · 耗时 {{duration}}",
"turnDurationSeconds": "{{seconds}} 秒",
"turnDurationMinutes": "{{minutes}} 分钟 {{seconds}} 秒",
"turnDurationHours": "{{hours}} 小时 {{minutes}} 分钟",
"turnProcessAria": "{{state}},展开或收起执行过程",
"turnNumber": "第 {{number}} 轮",
"turnPending": "正在处理…",
"expandDetailLazyHint": "展开详情(点击后加载迭代详情)",
"loadingEarlierDetails": "正在加载更早记录…",
"loadingLaterDetails": "正在加载更新记录…",
"backToLatestProgress": "↓ 回到最新进度",
"viewToolDetail": "查看详情",
"collapseToolDetail": "收起",
"liveTimelinePruned": "已收起前 {{count}} 条实时过程详情,任务完成后可按页查看完整记录",
@@ -605,6 +647,12 @@
"executeFailed": "执行失败",
"callOpenAIFailed": "调用OpenAI失败",
"systemReadyMessage": "系统已就绪。请输入您的测试需求,系统将自动执行相应的安全测试。",
"projectWelcomeMessage": "当前{{project}}项目,请输入您的测试需求,系统将自动执行相应的安全测试。",
"noProjectWelcomeMessage": "当前无项目,请输入您的测试需求,系统将自动执行相应的安全测试。",
"projectWelcomeTitlePrefix": "要在 ",
"projectWelcomeTitleSuffix": " 项目中测试什么?",
"noProjectWelcomeTitle": "要测试什么?",
"welcomeSubtitle": "请输入您的测试需求,系统将自动执行相应的安全测试。",
"addNewGroup": "+ 新增分组",
"callNumber": "调用 #{{n}}",
"iterationRound": "第 {{n}} 轮迭代",
@@ -662,15 +710,16 @@
"loadFailedRetry": "加载失败,请重试",
"dataFormatError": "数据格式错误",
"progressInProgress": "渗透测试进行中...",
"scrollToBottom": "回到底部",
"scrollToBottomHasNew": "↓ 有新内容",
"scrollToBottomNew": "↓ {{count}} 条新内容",
"executionFailed": "执行失败",
"penetrationTestComplete": "渗透测试完成",
"yesterday": "昨天",
"historyGroupToday": "今天",
"historyGroupLast7Days": "过去七天",
"historyGroupEarlier": "更早",
"conversationPreviewJustNow": "刚刚",
"conversationPreviewMinutes": "{{count}} 分钟",
"conversationPreviewHours": "{{count}} 小时",
"conversationPreviewDays": "{{count}} 天",
"agentModeSelectAria": "选择对话执行模式",
"agentModePanelTitle": "对话模式",
"agentModeEinoSingle": "Eino 单代理(ADK",
@@ -699,6 +748,21 @@
"sessionSettingsTitle": "会话设置",
"sessionSettingsAria": "打开会话设置",
"sessionSettingsHint": "AI 通道、推理设置与人机协同只影响后续消息。",
"sessionShortcutAuditAgent": "Agent 审查",
"modelSettingsAria": "选择模型与推理强度",
"systemModelPickerTitle": "选择系统模型",
"systemModelField": "模型",
"systemModelLoading": "正在获取模型列表…",
"systemModelLoaded": "已获取 {count} 个模型",
"systemModelCurrent": "当前",
"systemModelSaving": "正在保存…",
"systemModelSaved": "已自动保存",
"systemModelLoadFailed": "获取模型失败",
"systemModelSaveFailed": "保存模型失败",
"systemModelApplyFailed": "应用模型失败",
"systemModelNeedApiKey": "请先在系统设置中配置 API Key",
"systemModelRetry": "重新获取",
"sessionShortcutHuman": "人工审批",
"aiChannelLabel": "AI 通道",
"aiChannelDefault": "跟随默认通道",
"aiChannelDefaultShort": "默认通道",
@@ -726,6 +790,12 @@
"hitlApplyOkWhitelistYaml": "免审批工具已合并进 config.yaml 并生效。会话配置会自动保存。",
"hitlApplyOkLocal": "已保存到本浏览器。",
"hitlApplyFail": "同步到服务器失败",
"hitlTimeoutLabel": "审批等待时限",
"hitlTimeoutOneMinute": "1 分钟",
"hitlTimeoutFiveMinutes": "5 分钟",
"hitlTimeoutTenMinutes": "10 分钟",
"hitlTimeoutUnlimited": "不限制",
"hitlTimeoutHint": "到期未处理将自动拒绝;审批卡片会显示倒计时。",
"hitlStatusOff": "人机协同:关闭"
},
"hitl": {
@@ -751,6 +821,52 @@
"tabStrategy": "审计策略",
"tabWhitelist": "工具白名单",
"pendingTitle": "待处理审批",
"auditReviewing": "自动审核中",
"auditReviewEditing": "自动审查并校正中",
"auditReviewExplanation": "经过谨慎提示的审查智能体正在审查此请求,通过后才会执行。",
"auditApproved": "审计 Agent 已批准",
"auditEditedApproved": "审计 Agent 已修改参数并批准",
"auditRejected": "审计 Agent 已拒绝",
"waitingHumanApproval": "等待人工审批",
"waitingHumanReview": "等待人工审查",
"humanApprovalExplanation": "此工具调用需要你的确认,通过后才会执行。",
"humanReviewExplanation": "请审查并可修改参数,保存后才会执行。",
"humanApproved": "已允许一次",
"humanEditedApproved": "已修改参数并允许",
"humanRejected": "人工审批已拒绝",
"viewEditedArgs": "查看修改后的参数",
"reviewArgs": "审查参数(JSON",
"commentOptional": "备注(可选)",
"commentPlaceholder": "例如:仅允许只读操作",
"reject": "拒绝",
"allowOnce": "允许一次",
"saveEditedAndAllow": "保存修改并允许",
"waitingApprovalShort": "等待批准",
"waitingApprovalCount": "等待批准 {{count}}",
"approvalUrgencyUnlimited": "审批不限时",
"approvalUrgencyMoreThanThree": "最早审批将在 3 分钟后到期",
"approvalUrgencyMoreThanFive": "最早审批将在 5 分钟后到期",
"approvalUrgencyThreeToFive": "最早审批将在 3–5 分钟内到期",
"approvalUrgencyOneToThree": "最早审批将在 1–3 分钟内到期",
"approvalUrgencyWithinOne": "最早审批将在 1 分钟内到期",
"requestGeneric": "允许 CyberStrikeAI 调用 {{tool}}",
"requestVisitUrl": "允许 CyberStrikeAI 访问 {{url}}",
"requestBrowser": "允许 CyberStrikeAI 使用浏览器?",
"requestCommand": "允许 CyberStrikeAI 执行这条命令?",
"requestFile": "允许 CyberStrikeAI 修改 {{path}}",
"requestFiles": "允许 CyberStrikeAI 修改文件?",
"toolTerminal": "终端",
"toolFiles": "文件",
"viewRequestDetails": "查看请求详情",
"editRequestDetails": "查看或修改请求参数",
"addApprovalComment": "添加审批备注(可选)",
"timeoutAutoReject": "到期自动拒绝",
"timeoutUnlimited": "不限时等待",
"expiredAutoRejected": "审批已超时,正在自动拒绝…",
"taskClosedApprovalUnavailable": "任务已结束,审批不可用",
"taskInterrupted": "任务已中断",
"interruptedApprovalCancelled": "任务已中断,审批已取消",
"expiredRejected": "审批超时,已自动拒绝",
"searchLabel": "搜索",
"searchPlaceholder": "工具名、会话 ID、载荷、备注…",
"searchApply": "搜索",