Conversation
- 在 AgentSessionMeta 中添加 archived 字段支持会话归档 - 新增 TOGGLE_ARCHIVE IPC 通道用于切换归档状态 - 在 agent-atoms 中添加归档和搜索相关的状态管理 - showArchivedSessionsAtom: 控制归档视图切换 - sessionSearchKeywordAtom: 会话搜索关键词 - filteredAgentSessionsAtom: 过滤后的会话列表 - 在 LeftSidebar 中实现归档和搜索 UI - 添加归档/活跃会话切换按钮 - 添加搜索输入框支持按标题搜索 - 悬停时显示归档/取消归档图标按钮 - 支持归档会话的视觉区分和交互 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
本 PR 旨在为 Electron 端 Agent 模式补齐“会话归档 + 搜索”能力,通过在会话元数据中加入归档标记、补充 IPC 通道以及在侧边栏提供归档视图切换与标题关键词过滤来提升会话管理体验。
Changes:
- 为
AgentSessionMeta增加archived?: boolean,并扩展updateAgentSessionMeta支持更新归档字段 - 新增
AGENT_IPC_CHANNELS.TOGGLE_ARCHIVE,主进程注册对应 handler,预加载层暴露toggleArchiveAgentSession - 渲染端新增会话归档/搜索相关 atoms,并在
LeftSidebar中加入归档切换、搜索框、会话项归档/取消归档入口与空状态
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/types/agent.ts | 扩展会话元数据与 Agent IPC 通道常量以支持归档切换 |
| apps/electron/src/main/lib/agent-session-manager.ts | 允许 updateAgentSessionMeta 更新 archived 字段以实现持久化 |
| apps/electron/src/main/ipc.ts | 注册归档切换 IPC;同时引入了与本 PR 目标不一致的 usage 统计 IPC/服务改动 |
| apps/electron/src/preload/index.ts | 暴露归档切换 API;同时引入了与本 PR 目标不一致的 usage 统计 API 改动 |
| apps/electron/src/renderer/atoms/agent-atoms.ts | 增加归档视图开关、搜索关键词与组合过滤的派生 atom |
| apps/electron/src/renderer/components/app-shell/LeftSidebar.tsx | 侧边栏 UI:归档/活跃切换、搜索、归档按钮与空状态;抽取可复用标题编辑与列表项容器 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async (_, id: string): Promise<AgentSessionMeta> => { | ||
| const sessions = listAgentSessions() | ||
| const current = sessions.find((s) => s.id === id) | ||
| if (!current) throw new Error(`会话不存在: ${id}`) | ||
| return updateAgentSessionMeta(id, { archived: !current.archived }) |
There was a problem hiding this comment.
切换归档状态时通过 listAgentSessions() 读取并排序全量会话再 find 当前项,属于不必要的 IO + 排序开销。既然 agent-session-manager 已提供 getAgentSessionMeta(id),建议改用它读取当前 meta(或直接在 updateAgentSessionMeta 内处理不存在),减少额外开销。
| <div | ||
| role="button" | ||
| tabIndex={0} | ||
| onClick={onSelect} |
There was a problem hiding this comment.
ListItemContainer 使用了 role="button" + tabIndex={0} 但未处理键盘交互(Enter/Space),这会导致键盘/读屏用户无法触发点击。建议补充 onKeyDown(Enter/Space -> onSelect),或改用原生 <button> 来获得默认可访问性行为。
| onClick={onSelect} | |
| onClick={onSelect} | |
| onKeyDown={(e) => { | |
| if (e.key === 'Enter' || e.key === ' ') { | |
| e.preventDefault() | |
| onSelect() | |
| } | |
| }} |
| {searchKeyword && ( | ||
| <button | ||
| onClick={() => setSearchKeyword('')} | ||
| className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground" |
There was a problem hiding this comment.
搜索框右侧清除按钮是纯图标按钮,目前没有提供可访问名称(aria-label/title)。建议添加明确的 aria-label(如“清除搜索关键词”),以便读屏用户可识别其用途。
| className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground" | |
| className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground" | |
| aria-label="清除搜索关键词" | |
| title="清除搜索关键词" |
| import { IPC_CHANNELS, CHANNEL_IPC_CHANNELS, CHAT_IPC_CHANNELS, AGENT_IPC_CHANNELS, ENVIRONMENT_IPC_CHANNELS, PROXY_IPC_CHANNELS, GITHUB_RELEASE_IPC_CHANNELS, USAGE_IPC_CHANNELS } from '@proma/shared' | ||
| import { USER_PROFILE_IPC_CHANNELS, SETTINGS_IPC_CHANNELS } from '../types' |
There was a problem hiding this comment.
@proma/shared 中当前没有导出 USAGE_IPC_CHANNELS,并且本文件新增引用的 UsageStats/ConversationUsage/UsageSettings 类型在 shared 包中也未找到定义,会导致编译失败。建议移除这组 usage 相关改动,或在 shared 包中补齐对应的通道常量与类型定义后再引入。
| import { IPC_CHANNELS, CHANNEL_IPC_CHANNELS, CHAT_IPC_CHANNELS, AGENT_IPC_CHANNELS, ENVIRONMENT_IPC_CHANNELS, PROXY_IPC_CHANNELS, GITHUB_RELEASE_IPC_CHANNELS, USAGE_IPC_CHANNELS } from '@proma/shared' | ||
| import { USER_PROFILE_IPC_CHANNELS, SETTINGS_IPC_CHANNELS } from '../types' |
There was a problem hiding this comment.
本 PR 描述聚焦于 Agent 会话归档/搜索,但这里额外引入了“使用统计”相关 IPC/API(USAGE_*)。建议将 usage 统计拆分为单独 PR,避免功能耦合并降低回归风险。
| import { IPC_CHANNELS, CHANNEL_IPC_CHANNELS, CHAT_IPC_CHANNELS, AGENT_IPC_CHANNELS, ENVIRONMENT_IPC_CHANNELS, PROXY_IPC_CHANNELS, GITHUB_RELEASE_IPC_CHANNELS, USAGE_IPC_CHANNELS } from '@proma/shared' | ||
| import { USER_PROFILE_IPC_CHANNELS, SETTINGS_IPC_CHANNELS } from '../types' | ||
| import type { |
There was a problem hiding this comment.
@proma/shared 中当前没有导出 USAGE_IPC_CHANNELS,且本文件引用的 UsageStats/ConversationUsage/UsageSettings 类型在 shared 包中也未找到定义,会导致主进程编译失败。建议移除 usage 相关改动或先在 shared 包补齐导出。
| import { | ||
| getUsageStats, | ||
| getConversationUsage, | ||
| getUsageSettings, | ||
| updateUsageSettings, | ||
| } from './lib/usage-service' | ||
|
|
There was a problem hiding this comment.
这里新增引入 ./lib/usage-service,但仓库内不存在该模块(当前 main/lib 下未找到 usage-service.ts),会导致运行/构建失败。建议补齐实现文件并纳入测试,或将 usage 统计改动从本 PR 移除。
| import { | |
| getUsageStats, | |
| getConversationUsage, | |
| getUsageSettings, | |
| updateUsageSettings, | |
| } from './lib/usage-service' | |
| // Usage service stubs: underlying implementation not available in this build. | |
| // These implementations return null so usage-related IPC calls fail gracefully | |
| // instead of causing module resolution errors at runtime. | |
| const getUsageStats: any = async (..._args: any[]) => { | |
| return null | |
| } | |
| const getConversationUsage: any = async (..._args: any[]) => { | |
| return null | |
| } | |
| const getUsageSettings: any = async (..._args: any[]) => { | |
| return null | |
| } | |
| const updateUsageSettings: any = async (..._args: any[]) => { | |
| return null | |
| } |
| // 关键词搜索 | ||
| if (keyword.trim()) { | ||
| return s.title.toLowerCase().includes(keyword.toLowerCase()) | ||
| } |
There was a problem hiding this comment.
关键词判断使用了 keyword.trim(),但实际匹配使用的是未 trim 的 keyword.toLowerCase();当用户输入前后空格时会导致无法命中(例如 " foo ")。建议先计算 const normalized = keyword.trim().toLowerCase(),再用于 includes 匹配。
| () => groupByDate(filteredAgentSessions), | ||
| [filteredAgentSessions] | ||
| ) | ||
| const agentSessionGroups = groupByDate(filteredAgentSessions) |
There was a problem hiding this comment.
agentSessionGroups 每次渲染都会重新 groupByDate(filteredAgentSessions) 生成新数组;在会话列表较大或频繁状态更新时会带来不必要的计算和子树重渲染。建议恢复 useMemo(依赖 filteredAgentSessions)以避免重复分组。
| const agentSessionGroups = groupByDate(filteredAgentSessions) | |
| const agentSessionGroups = React.useMemo( | |
| () => groupByDate(filteredAgentSessions), | |
| [filteredAgentSessions], | |
| ) |
功能描述
本 PR 为 Agent 模式添加会话归档和搜索功能,提升会话管理体验。
主要改动
类型定义 (packages/shared/src/types/agent.ts)
AgentSessionMeta类型中添加archived?: boolean字段支持会话归档AGENT_IPC_CHANNELS常量中添加TOGGLE_ARCHIVE: 'agent:toggle-archive'通道主进程 (apps/electron/src/main)
TOGGLE_ARCHIVEIPC 处理器,切换会话归档状态updateAgentSessionMeta函数支持更新archived字段Preload 桥接 (apps/electron/src/preload/index.ts)
toggleArchiveAgentSession(id: string)API 供渲染进程调用前端状态管理 (apps/electron/src/renderer/atoms/agent-atoms.ts)
showArchivedSessionsAtom: 控制归档/活跃会话视图切换sessionSearchKeywordAtom: 会话搜索关键词状态activeAgentSessionsAtom: 派生 atom,获取当前工作区的活跃会话archivedAgentSessionsAtom: 派生 atom,获取当前工作区的归档会话filteredAgentSessionsAtom: 组合过滤(工作区 + 归档状态 + 关键词搜索)UI 界面 (apps/electron/src/renderer/components/app-shell/LeftSidebar.tsx)
extraButton实现,与删除按钮并排)测试清单
联系方式:david.liu1888888@gmail.com