Skip to content

feat: 添加 Agent 会话归档和搜索功能#32

Open
david188888 wants to merge 1 commit intoErlichLiu:mainfrom
david188888:feat/agent-archive-search
Open

feat: 添加 Agent 会话归档和搜索功能#32
david188888 wants to merge 1 commit intoErlichLiu:mainfrom
david188888:feat/agent-archive-search

Conversation

@david188888
Copy link

@david188888 david188888 commented Feb 19, 2026

功能描述

本 PR 为 Agent 模式添加会话归档和搜索功能,提升会话管理体验。

主要改动

类型定义 (packages/shared/src/types/agent.ts)

  • AgentSessionMeta 类型中添加 archived?: boolean 字段支持会话归档
  • AGENT_IPC_CHANNELS 常量中添加 TOGGLE_ARCHIVE: 'agent:toggle-archive' 通道

主进程 (apps/electron/src/main)

  • ipc.ts: 新增 TOGGLE_ARCHIVE IPC 处理器,切换会话归档状态
  • agent-session-manager.ts: 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

- 在 AgentSessionMeta 中添加 archived 字段支持会话归档
- 新增 TOGGLE_ARCHIVE IPC 通道用于切换归档状态
- 在 agent-atoms 中添加归档和搜索相关的状态管理
  - showArchivedSessionsAtom: 控制归档视图切换
  - sessionSearchKeywordAtom: 会话搜索关键词
  - filteredAgentSessionsAtom: 过滤后的会话列表
- 在 LeftSidebar 中实现归档和搜索 UI
  - 添加归档/活跃会话切换按钮
  - 添加搜索输入框支持按标题搜索
  - 悬停时显示归档/取消归档图标按钮
- 支持归档会话的视觉区分和交互

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 19, 2026 16:39
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +556 to +560
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 })
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

切换归档状态时通过 listAgentSessions() 读取并排序全量会话再 find 当前项,属于不必要的 IO + 排序开销。既然 agent-session-manager 已提供 getAgentSessionMeta(id),建议改用它读取当前 meta(或直接在 updateAgentSessionMeta 内处理不存在),减少额外开销。

Copilot uses AI. Check for mistakes.
<div
role="button"
tabIndex={0}
onClick={onSelect}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ListItemContainer 使用了 role="button" + tabIndex={0} 但未处理键盘交互(Enter/Space),这会导致键盘/读屏用户无法触发点击。建议补充 onKeyDown(Enter/Space -> onSelect),或改用原生 <button> 来获得默认可访问性行为。

Suggested change
onClick={onSelect}
onClick={onSelect}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
onSelect()
}
}}

Copilot uses AI. Check for mistakes.
{searchKeyword && (
<button
onClick={() => setSearchKeyword('')}
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground/60 hover:text-foreground"
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

搜索框右侧清除按钮是纯图标按钮,目前没有提供可访问名称(aria-label/title)。建议添加明确的 aria-label(如“清除搜索关键词”),以便读屏用户可识别其用途。

Suggested change
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="清除搜索关键词"

Copilot uses AI. Check for mistakes.
Comment on lines +9 to 10
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'
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@proma/shared 中当前没有导出 USAGE_IPC_CHANNELS,并且本文件新增引用的 UsageStats/ConversationUsage/UsageSettings 类型在 shared 包中也未找到定义,会导致编译失败。建议移除这组 usage 相关改动,或在 shared 包中补齐对应的通道常量与类型定义后再引入。

Copilot uses AI. Check for mistakes.
Comment on lines +9 to 10
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'
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本 PR 描述聚焦于 Agent 会话归档/搜索,但这里额外引入了“使用统计”相关 IPC/API(USAGE_*)。建议将 usage 统计拆分为单独 PR,避免功能耦合并降低回归风险。

Copilot uses AI. Check for mistakes.
Comment on lines +8 to 10
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 {
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@proma/shared 中当前没有导出 USAGE_IPC_CHANNELS,且本文件引用的 UsageStats/ConversationUsage/UsageSettings 类型在 shared 包中也未找到定义,会导致主进程编译失败。建议移除 usage 相关改动或先在 shared 包补齐导出。

Copilot uses AI. Check for mistakes.
Comment on lines +115 to 121
import {
getUsageStats,
getConversationUsage,
getUsageSettings,
updateUsageSettings,
} from './lib/usage-service'

Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里新增引入 ./lib/usage-service,但仓库内不存在该模块(当前 main/lib 下未找到 usage-service.ts),会导致运行/构建失败。建议补齐实现文件并纳入测试,或将 usage 统计改动从本 PR 移除。

Suggested change
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
}

Copilot uses AI. Check for mistakes.
Comment on lines +487 to +490
// 关键词搜索
if (keyword.trim()) {
return s.title.toLowerCase().includes(keyword.toLowerCase())
}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

关键词判断使用了 keyword.trim(),但实际匹配使用的是未 trim 的 keyword.toLowerCase();当用户输入前后空格时会导致无法命中(例如 " foo ")。建议先计算 const normalized = keyword.trim().toLowerCase(),再用于 includes 匹配。

Copilot uses AI. Check for mistakes.
() => groupByDate(filteredAgentSessions),
[filteredAgentSessions]
)
const agentSessionGroups = groupByDate(filteredAgentSessions)
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agentSessionGroups 每次渲染都会重新 groupByDate(filteredAgentSessions) 生成新数组;在会话列表较大或频繁状态更新时会带来不必要的计算和子树重渲染。建议恢复 useMemo(依赖 filteredAgentSessions)以避免重复分组。

Suggested change
const agentSessionGroups = groupByDate(filteredAgentSessions)
const agentSessionGroups = React.useMemo(
() => groupByDate(filteredAgentSessions),
[filteredAgentSessions],
)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants