-
Notifications
You must be signed in to change notification settings - Fork 403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support chat sessions management & recover from storage #4399
Conversation
Walkthrough此次变更涉及多个模块,主要增强了聊天功能。修改包括在核心贡献类中注入并异步初始化聊天服务、扩展聊天会话和模型的初始化与序列化方法、调整聊天 UI 组件(包含历史记录管理)的交互逻辑,以及更新 CSS 样式和国际化条目。此外,还在存储模块中添加了专用于聊天数据的命名空间,从而完善整体聊天功能的支持。 Changes
Sequence Diagram(s)sequenceDiagram
participant BC as BrowserContribution
participant CMS as ChatManagerService
participant CIS as ChatInternalService
BC->>CMS: 调用 init() 进行存储初始化和会话加载
CMS-->>BC: 返回会话数据
BC->>CIS: 调用 init() 初始化内部会话管理
CIS->>CMS: 订阅 onStorageInit 事件
CMS-->>CIS: 触发 storageInit 事件
CIS->>CMS: 获取并处理现有会话数据
Possibly related PRs
Suggested labels
Suggested reviewers
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 ESLint
yarn install v1.22.22 ✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (15)
packages/ai-native/src/browser/chat/chat.internal.service.ts (2)
79-79
: 方法命名清晰,便于理解功能。若需要在外部使用创建的会话实例,可考虑在方法末尾返回该会话。
84-91
: 在清理会话后立即重建当前会话,这样可以确保用户总有一个可用的活跃会话。若想在彻底清除后保持无会话状态,可额外提供可选配置。packages/ai-native/src/browser/chat/chat-manager.service.ts (4)
7-34
: 这些新的导入与ISessionModel
接口为后续会话管理与序列化提供了良好的扩展性。ISessionModel
定义较为清晰,且包含必要的字段。请注意后续 TODO(行 55)中的功能是否需要尽快完善。
118-118
: 在清理会话后立即调用saveSessions()
,可确保存储数据与内存保持一致。对于批量操作,建议考虑合并保存以提升性能。
137-137
: 在会话不存在时抛出异常能及时暴露逻辑问题。若有可能在用户层面遇到此错误,或可改为返回可读性更高的提示信息。
199-201
: 存储操作在多次请求中频繁调用,可能带来性能开销。可以考虑在高频场景中使用节流或批量写入策略来降低存储压力。packages/ai-native/src/browser/chat/chat-model.ts (3)
83-105
: 新的构造函数允许通过initParams
自定义初始状态,增强了灵活性。若某些属性可能在外部未显式传入,建议使用安全默认值以免产生undefined
。
239-247
:ChatResponseModel.toJSON()
输出必要字段便于序列化。若后续需要从序列化结果反向恢复requestId
、agentId
等更多信息,可酌情添加相关字段。
337-343
:ChatModel.toJSON()
会将所有请求与历史记录打包序列化。对于有大批消息的用户环境,可考虑在此处分页或按需序列化,以减轻一次性写入压力。packages/ai-native/src/browser/chat/chat.view.tsx (1)
72-72
: 建议将MAX_TITLE_LENGTH
的值抽离到配置或常量文件中。
如果其他地方也需要相同的长度限制,统一管理会更易维护。packages/ai-native/src/browser/components/ChatHistory.tsx (3)
116-135
: 建议将时间格式化逻辑抽取为独立的工具函数。
getTimeKey
函数的逻辑可以移到一个单独的工具文件中,这样可以:
- 提高代码的可重用性
- 便于单元测试
- 使组件代码更加清晰
建议创建
utils/time.ts
文件:export const formatTimeAgo = (timestamp: number): string => { const diff = Date.now() - timestamp; if (diff < 60 * 60 * 1000) { const minutes = Math.floor(diff / (60 * 1000)); return minutes === 0 ? 'Just now' : `${minutes}m ago`; } else if (diff < 24 * 60 * 60 * 1000) { const hours = Math.floor(diff / (60 * 60 * 1000)); return `${hours}h ago`; } // ... 其余逻辑 };
226-230
: 优化搜索功能的性能。当前的搜索实现在每次输入时都会重新过滤整个列表。对于大型历史记录,这可能会导致性能问题。
建议:
- 使用防抖(debounce)来减少不必要的过滤操作
- 考虑实现模糊搜索
- 对搜索结果进行缓存
import { debounce } from 'lodash'; const debouncedSearch = debounce((value: string) => { const filteredList = historyList .slice(0, MAX_HISTORY_LIST) .filter((item) => item.title && item.title.toLowerCase().includes(value.toLowerCase())); setFilteredResults(filteredList); }, 300);
192-200
: 删除被注释的代码。建议删除被注释的编辑功能代码。如果将来需要这个功能,可以从版本控制系统中恢复。
packages/ai-native/src/browser/ai-core.contribution.ts (1)
243-252
: 初始化聊天服务初始化逻辑清晰,顺序合理:
- 先初始化内部服务
- 再异步初始化管理服务
建议添加错误处理。
async initialize() { const { supportsChatAssistant } = this.aiNativeConfigService.capabilities; if (supportsChatAssistant) { ComponentRegistryImpl.addLayoutModule(this.appConfig.layoutConfig, AI_CHAT_VIEW_ID, AI_CHAT_CONTAINER_ID); ComponentRegistryImpl.addLayoutModule(this.appConfig.layoutConfig, DESIGN_MENU_BAR_RIGHT, AI_CHAT_LOGO_AVATAR_ID); this.chatProxyService.registerDefaultAgent(); + try { this.chatInternalService.init(); await this.chatManagerService.init(); + } catch (error) { + console.error('Failed to initialize chat services:', error); + } } }packages/i18n/src/common/zh-CN.lang.ts (1)
1255-1259
: 新增聊天操作相关的本地化文案文案清晰简洁,符合中文用户习惯。建议补充以下场景的文案:
- 聊天历史为空时的提示
- 删除确认对话框的文案
'aiNative.operate.chatHistory.title': '聊天历史', 'aiNative.operate.chatHistory.searchPlaceholder': '请搜索...', 'aiNative.operate.chatHistory.edit': '编辑', 'aiNative.operate.chatHistory.delete': '删除', +'aiNative.operate.chatHistory.empty': '暂无聊天历史', +'aiNative.operate.chatHistory.delete.confirm': '确定要删除该聊天记录吗?',
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
packages/ai-native/src/browser/ai-core.contribution.ts
(2 hunks)packages/ai-native/src/browser/chat/chat-manager.service.ts
(3 hunks)packages/ai-native/src/browser/chat/chat-model.ts
(6 hunks)packages/ai-native/src/browser/chat/chat-proxy.service.ts
(1 hunks)packages/ai-native/src/browser/chat/chat.internal.service.ts
(2 hunks)packages/ai-native/src/browser/chat/chat.module.less
(2 hunks)packages/ai-native/src/browser/chat/chat.view.tsx
(7 hunks)packages/ai-native/src/browser/components/ChatHistory.tsx
(1 hunks)packages/ai-native/src/browser/components/ChatReply.tsx
(1 hunks)packages/ai-native/src/browser/components/ChatThinking.tsx
(1 hunks)packages/ai-native/src/browser/components/chat-history.css
(1 hunks)packages/ai-native/src/browser/model/msg-history-manager.ts
(2 hunks)packages/core-common/src/storage.ts
(1 hunks)packages/i18n/src/common/en-US.lang.ts
(1 hunks)packages/i18n/src/common/zh-CN.lang.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/ai-native/src/browser/components/chat-history.css
🧰 Additional context used
🪛 Biome (1.9.4)
packages/ai-native/src/browser/chat/chat-manager.service.ts
[error] 82-86: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
packages/ai-native/src/browser/components/ChatHistory.tsx
[error] 235-235: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: unittest (ubuntu-latest, 18.x, node)
- GitHub Check: build (macos-latest, 20.x)
- GitHub Check: unittest (macos-latest, 18.x, jsdom)
- GitHub Check: unittest (macos-latest, 18.x, node)
- GitHub Check: build-windows
- GitHub Check: ubuntu-latest, Node.js 20.x
🔇 Additional comments (29)
packages/ai-native/src/browser/chat/chat.internal.service.ts (2)
46-54
: 在存储初始化事件中,根据已有会话决定是否创建新会话的逻辑十分合理。若后续需要根据时间戳或其他自定义优先级选择会话,建议在这里扩展相应的逻辑。
93-95
: 对外暴露获取所有会话的接口,功能直观简单。若需要进行权限控制或过滤,可在此处扩展。packages/ai-native/src/browser/chat/chat-manager.service.ts (7)
40-41
: 通过storageInitEmitter
与onStorageInit
来处理存储初始化事件,设计非常直观。对于复杂场景,可考虑在触发同时传递更多上下文信息。
49-52
: 在该服务中引入并保存StorageProvider
对象及_chatStorage
有助于实现会话的持久化。若后续需要切换不同的命名空间或存储策略,可以在此处灵活扩展。
54-80
:fromJSON
方法可将存储中的数据恢复为完整的ChatModel
实例。建议在处理item.requests
时增补空值判断或异常处理,以免数据不完整时引发错误。
96-98
: 提供获取所有会话的方式,便于 UI 或其他服务调用。若后续需要基于会话属性进行筛选或排序,可以在此方法中进一步扩展。
101-101
: 使用new ChatModel()
的方式取代依赖注入,简化了会话创建流程。若需要更灵活的构造过程,可在此处引入参数或工厂模式。
195-195
: 在响应请求流程的 finally 块中调用this.saveSessions()
可确保无论成功或异常都能进行持久化,这种设计非常健壮。
207-207
: 在取消请求后立即保存会话同样能保证数据一致性,但若取消操作频繁,建议评估对性能的影响并视情况进行优化。packages/ai-native/src/browser/chat/chat-model.ts (2)
277-284
: 新的ChatModel
构造函数允许自定义会话 ID、历史等,设计灵活。初始化逻辑简单明了,复用性强。
296-297
:restoreRequests
通过一次性替换存储结构来恢复会话请求列表,简洁易懂。若需要在恢复前后执行校验或转换,可在此方法中进一步扩展。packages/ai-native/src/browser/chat/chat.view.tsx (6)
24-24
: 引入DisposableCollection
很合理。
封装一处集中清理的思路可以有效避免事件监听或订阅的内存泄漏。
455-456
: 在再生成流程中校验request
安全性。
此处保证request
存在便发起请求,逻辑简单明了,但也建议思考异常处理或请求失败的应对措施。
621-622
: 在从存储恢复时判空逻辑合理。
对request
为空或未完成做了保护,能有效避免异常。后续可考虑在 UI 上给用户展示正在恢复或未完成的提示。Also applies to: 631-632
761-780
: 状态与回调声明整体清晰易读。
handleNewChat
、handleHistoryItemSelect
和handleHistoryItemDelete
各自单一职责明确,逻辑简单,便于后续维护和扩展。
781-831
: 在React.useEffect
中动态监听多处 session 变动需谨慎。
虽然通过DisposableCollection
可以正确清理,但应注意确保不会重复注册;如果 session 数量非常多,需做性能评估。
834-874
: 头部区域布局与事件绑定逻辑简洁明了。
ChatHistory
组件与弹出操作配合默契,无明显问题。若要做更多定制操作,可考虑抽离通用 UI 组件以便在其他地方复用。packages/ai-native/src/browser/model/msg-history-manager.ts (2)
18-24
: 新增构造函数支持外部初始化数据,提升灵活性。
可以在创建实例时还原历史消息与附加数据,满足更多场景需求。
100-105
:toJSON
方法实现非常便捷。
对接存储或网络传输场景时可直接使用本方法序列化。后续若需要只导出部分数据,可新增额外函数进行筛选处理。packages/core-common/src/storage.ts (1)
56-56
: 为聊天功能独立存储命名空间非常合适。
有助于实现对话数据的定向管理,避免与其他模块的存储相互影响。packages/ai-native/src/browser/components/ChatThinking.tsx (1)
119-125
: 代码变更增强了重新生成按钮的显示逻辑。通过添加
!!requestId
检查,确保只有在存在有效的请求 ID 时才显示重新生成按钮,这是一个很好的防御性编程实践。packages/ai-native/src/browser/chat/chat-proxy.service.ts (1)
42-42
:❓ Verification inconclusive
请验证移除 UUID 后缀的影响。
将
AGENT_ID
从动态值更改为静态值可能会影响:
- 多个代理实例的唯一性
- 会话持久化
- 代理标识
建议确认这个更改不会导致任何并发或状态管理问题。
运行以下脚本来检查代码库中
AGENT_ID
的使用情况:
🏁 Script executed:
#!/bin/bash # 描述:检查 AGENT_ID 的使用情况,特别是在并发和状态管理相关的代码中 # 搜索所有引用 AGENT_ID 的代码 rg "AGENT_ID" -A 5 -B 5 # 搜索可能的并发处理相关代码 rg "concurrent|async|await|Promise|setTimeout|setInterval" --type tsLength of output: 68067
验证静态化 AGENT_ID 影响
经过代码库内的搜索,发现所有对
ChatProxyService.AGENT_ID
的引用都采用了固定字符串'Default_Chat_Agent'
进行比较和过滤,未依赖原先动态附加 UUID 的机制来保证唯一性。从目前的使用情况来看:
- 默认代理在注册、更新及视图显示时均基于固定 ID 进行逻辑判断(例如在对比、过滤和显示代理 ID 时)。
- 没有明显迹象表明当前场景中需要依靠动态 UUID 来区分多个默认代理实例,也未发现并发处理或状态管理上的隐患。
建议:
- 请确认系统设计中默认代理仅为单一实例。如果未来需要同时支持多个默认代理实例,可能需要重新考虑使用动态唯一 ID 来避免潜在冲突。
- 对于当前默认代理的使用,确保其他功能模块(如会话持久化和代理区分)能够正确识别和处理该固定标识,防止误判或状态错乱。
综合来看,在现有的代码逻辑和使用场景中,此改动暂未引入并发或状态管理上的问题,但建议开发者在扩展多实例场景时保持警惕。
packages/ai-native/src/browser/components/ChatReply.tsx (1)
363-367
: 完善了消息存在性的检查逻辑。通过添加
responseContents.length
的检查,使消息存在性的判断更加完整和准确。这个改进可以更好地处理不同类型的响应内容。packages/ai-native/src/browser/ai-core.contribution.ts (3)
76-77
: 导入新的聊天服务接口导入的接口定义清晰,符合命名规范。
83-85
: 导入聊天服务实现类导入的服务实现类符合命名规范。
233-237
: 注入聊天服务依赖通过
@Autowired
装饰器正确注入了聊天管理服务和内部服务。packages/i18n/src/common/en-US.lang.ts (1)
1487-1491
: 新增的本地化字符串看起来不错!新增的聊天历史相关的本地化字符串遵循了现有的命名约定,使用了合适的命名空间,并且提供了清晰的英文翻译。
packages/ai-native/src/browser/chat/chat.module.less (2)
76-87
: 头部容器样式优化得很好!对header_container的改进:
- 通过减小padding使头部更加紧凑
- 简化了header结构,移除了复杂的left/right类,使代码更加清晰
282-285
: 新增的chat_history样式定义合理!chat_history类的样式设置:
- 使用calc()计算宽度,保留了合适的边距
- 使用CSS变量设置文字颜色,保持了主题的一致性
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4399 +/- ##
==========================================
- Coverage 53.58% 53.56% -0.03%
==========================================
Files 1651 1651
Lines 101806 101866 +60
Branches 22027 22035 +8
==========================================
+ Hits 54557 54566 +9
- Misses 39304 39351 +47
- Partials 7945 7949 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
packages/ai-native/src/browser/components/ChatHistory.tsx (5)
9-25
: 建议为接口添加 JSDoc 文档注释为了提高代码的可维护性和可读性,建议为
IChatHistoryItem
和IChatHistoryProps
接口添加详细的 JSDoc 文档注释,包括每个属性的用途说明。+/** + * 聊天历史记录项的接口定义 + */ export interface IChatHistoryItem { + /** 唯一标识符 */ id: string; + /** 聊天标题 */ title: string; + /** 更新时间戳 */ updatedAt: number; + /** 是否正在加载 */ loading: boolean; } +/** + * 聊天历史记录组件的属性接口 + */ export interface IChatHistoryProps { // ... 同样添加其他属性的文档注释 }
45-45
: 建议优化 inputRef 的类型定义当前
inputRef
使用any
类型,建议使用更具体的类型以提高类型安全性。-const inputRef = useRef<any>(null); +const inputRef = useRef<HTMLInputElement>(null);
191-199
: 建议清理未使用的注释代码建议移除或实现被注释的编辑功能代码。如果这是一个计划中的功能,建议使用 TODO 注释标记,或者完全移除这段代码。保留注释掉的代码可能会导致混淆。
115-134
: 建议国际化时间标签当前时间标签(如 "Just now", "5m ago" 等)使用硬编码的英文文本。建议使用
localize
函数进行国际化处理,以支持多语言。const getTimeKey = useCallback((diff: number): string => { if (diff < 60 * 60 * 1000) { const minutes = Math.floor(diff / (60 * 1000)); - return minutes === 0 ? 'Just now' : `${minutes}m ago`; + return minutes === 0 + ? localize('aiNative.time.justNow') + : localize('aiNative.time.minutesAgo', minutes); } // ... 对其他时间标签进行类似处理 }, []);
234-239
: 建议使用可选链操作符优化代码为了提高代码的健壮性,建议在事件处理中使用可选链操作符。
<Input placeholder={localize('aiNative.operate.chatHistory.searchPlaceholder')} style={{ width: '100%', maxWidth: '100%' }} value={searchValue} - onChange={handleSearchChange} + onChange={handleSearchChange?.} />🧰 Tools
🪛 Biome (1.9.4)
[error] 235-235: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/ai-native/src/browser/components/ChatHistory.tsx
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/ai-native/src/browser/components/ChatHistory.tsx
[error] 235-235: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: unittest (ubuntu-latest, 18.x, node)
- GitHub Check: build (macos-latest, 20.x)
- GitHub Check: build-windows
- GitHub Check: ubuntu-latest, Node.js 20.x
Types
Background or solution
feat: support chat sessions management & recover from storage
Changelog
feat: support chat sessions management & recover from storage
Summary by CodeRabbit
新功能
样式