优化项目对话、刷新续流、实时滚动与工具状态恢复 (#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
+44
View File
@@ -0,0 +1,44 @@
const fs = require('node:fs');
const test = require('node:test');
const assert = require('node:assert/strict');
const chat = fs.readFileSync('web/static/js/chat.js', 'utf8');
const monitor = fs.readFileSync('web/static/js/monitor.js', 'utf8');
const projects = fs.readFileSync('web/static/js/projects.js', 'utf8');
const styles = fs.readFileSync('web/static/css/style.css', 'utf8');
const zh = JSON.parse(fs.readFileSync('web/static/i18n/zh-CN.json', 'utf8'));
const en = JSON.parse(fs.readFileSync('web/static/i18n/en-US.json', 'utf8'));
test('主对话时间线不再创建用户或助手头像', () => {
assert.doesNotMatch(chat, /createMessageAvatar/);
assert.doesNotMatch(monitor, /createMessageAvatar/);
assert.doesNotMatch(chat, /message-avatar/);
assert.doesNotMatch(styles, /\.message-avatar/);
});
test('新对话使用无图标的项目欢迎空状态', () => {
assert.match(chat, /function renderChatWelcomeEmptyState\(\)/);
assert.match(chat, /chat-welcome-empty-state-title/);
assert.match(chat, /chat-welcome-empty-state-subtitle/);
assert.doesNotMatch(chat, /chat-welcome-empty-state-icon/);
assert.match(styles, /\.chat-welcome-empty-state\s*\{[\s\S]*?justify-content: center/);
assert.match(styles, /\.chat-welcome-empty-state-title/);
assert.match(styles, /\.chat-welcome-empty-state-subtitle/);
assert.match(styles, /\.chat-welcome-project-name\s*\{[\s\S]*?border-bottom: 1px dotted currentColor/);
assert.match(chat, /projectName\.className = 'chat-welcome-project-name'/);
assert.match(chat, /title\.replaceChildren\(/);
});
test('欢迎语随项目和无项目状态更新', () => {
assert.match(chat, /window\.t\('chat\.projectWelcomeMessage', \{ project \}\)/);
assert.match(chat, /window\.t\('chat\.noProjectWelcomeMessage'\)/);
assert.match(projects, /window\.refreshChatWelcomeEmptyState\(\)/);
assert.equal(
zh.chat.projectWelcomeMessage,
'当前{{project}}项目,请输入您的测试需求,系统将自动执行相应的安全测试。'
);
assert.equal(zh.chat.projectWelcomeTitlePrefix, '要在 ');
assert.equal(zh.chat.projectWelcomeTitleSuffix, ' 项目中测试什么?');
assert.equal(zh.chat.welcomeSubtitle, '请输入您的测试需求,系统将自动执行相应的安全测试。');
assert.equal(typeof en.chat.projectWelcomeMessage, 'string');
});