主题
状态管理与持久化
本文引用的源码文件
本文引用的文件
更新摘要
变更内容
- 更新了会话取消键收集机制,新增
collectSessionCancelKeys函数以支持子任务进度数据结构处理 - 增强了标签页状态管理,改进了派生会话祖先链和 keepalive 端口路由
- 完善了子任务进度数据结构的错误处理机制
- 优化了 ReAct 循环的取消控制和工具等待终止逻辑
目录
引言
本文件聚焦 Chrome 扩展端的状态管理与持久化机制,覆盖以下目标:
- 解释应用状态的层次结构:内存状态、会话状态、配置数据、用户偏好。
- 说明变更追踪与同步机制:侧边栏状态、后台 Service Worker 状态、IndexedDB、chrome.storage.local 的读写路径。
- 详细说明 IndexedDB 数据模型设计、事务处理与并发访问控制。
- 解释 ReAct Checkpoint 的双写策略、TTL 清理与恢复流程。
- 说明状态迁移方案、数据备份恢复思路与版本兼容性管理。
- 提供状态转换图、数据库 schema 图和数据流图。
- 讨论大数据量场景下的查询优化、缓存策略和性能监控。
本项目为双进程架构:Chrome 扩展端(Manifest V3,Service Worker + Side Panel)与独立本地代理端 Agent(Node.js)。本文仅关注扩展端的状态与持久化;Agent 端的记忆与 RAG 数据不在本文件范围内。
项目结构与职责边界
与状态管理和持久化直接相关的代码集中在 src/storage、src/side_panel/state.js、src/background/state.js、src/background/index.js、src/background/react-loop.js 以及共享国际化模块。
graph TB subgraph "扩展端" SP["Side Panel<br/>UI 与交互"] SW["Background Service Worker<br/>任务执行与调度"] IDB["IndexedDB<br/>ai-helper-db"] CS["chrome.storage.local<br/>配置与后备存储"] end subgraph "Agent 端" AGENT["本地 Agent 服务<br/>文件/命令/RAG/记忆"] end SP --> SW SP --> IDB SP --> CS SW --> IDB SW --> CS SW --> AGENT
图表来源
章节来源
核心组件总览
| 组件 | 职责 | 主要数据 | 关键行为 |
|---|---|---|---|
src/storage/db.js | IndexedDB 封装层、数据库连接单例、事务包装器、ReAct Checkpoint 双写与 TTL 清理 | sessions、activeSession、archivedSessions、uiPrototypes、tokenStats、reactCheckpoints、bookmarks、scheduledTasks | openDB、withStore、CRUD、迁移、Checkpoint 读写 |
src/storage/session-store.js | 会话存储适配器,对接 IndexedDB,兼容旧 chrome.storage API | 活跃会话、归档会话、当前会话、滚动位置、收藏 | 初始化迁移、创建/保存/切换/删除/归档/复制会话 |
src/storage/token-store.js | Token 使用统计的 IndexedDB CRUD 与聚合查询 | tokenStats | 记录调用、会话汇总、全局汇总、按天聚合、按模型/类型分布 |
src/side_panel/state.js | 侧边栏全局内存状态,通过 Proxy 暴露字段 | 消息历史、当前模型、温度、工具开关、会话上下文压缩等 | 双向导出、事件派发、运行时状态隔离 |
src/background/state.js | 后台状态与取消控制、AbortController、keepalive 端口注册 | 取消标记、API 计数、派生会话祖先链、实例身份 | 取消 ReAct 循环、获取/创建 AbortController、端口路由 |
src/background/index.js | 后台入口、消息路由、SW 启动自检与自动恢复 | ReAct Checkpoint、Agent 迁移结果 | 清理过期 checkpoint、检测可恢复任务、响应前端 GET/DELETE_CHECKPOINT |
src/background/react-loop.js | ReAct 推理循环、Checkpoint 节流保存、恢复流程 | currentMessages、executionLog、iteration、taskContext | saveCheckpointNow、resumeReactLoopFromCheckpoint、异常强制保存 |
src/shared/i18n.js | 国际化初始化与跨环境语言同步 | language 偏好 | 从 chrome.storage.local 读取语言并监听变更 |
章节来源
- src/storage/db.js#L21-L92
- src/storage/session-store.js#L42-L113
- src/storage/token-store.js#L1-L45
- src/side_panel/state.js#L1-L74
- src/background/state.js#L1-L46
- src/background/index.js#L74-L95
- src/background/react-loop.js#L1037-L1075
- src/shared/i18n.js#L162-L193
架构总览:状态层次、存储分层与数据流
状态层次
- 内存状态:侧边栏
state.js维护 UI 渲染与交互所需状态;后台state.js维护任务生命周期、取消控制、端口路由。 - 会话状态:活跃会话与归档会话持久化到 IndexedDB;当前活跃会话 ID 单独存储。
- 配置数据:扩展配置、主题、工具列表、输入历史等保存在
chrome.storage.local。 - 用户偏好:语言偏好、模型选择、温度、TopP 等可通过配置或会话级参数体现。
- 运行态快照:ReAct Checkpoint 作为长任务中断后的断点续接数据,采用 IndexedDB + chrome.storage.local 双写。
flowchart TD
Start(["应用启动"]) --> LoadState["加载内存状态<br/>side_panel/state.js"]
LoadState --> InitStorage["初始化存储<br/>session-store.init()"]
InitStorage --> EnsureMigration["确保数据迁移<br/>ensureMigration()"]
EnsureMigration --> LoadSessions["加载会话列表<br/>getAllSessions() + getActiveSessionId()"]
LoadSessions --> RenderUI["渲染侧边栏 UI"]
RenderUI --> UserAction{"用户操作"}
UserAction --> |新建/切换/归档/复制| SessionOps["会话操作<br/>session-store.js"]
UserAction --> |发送消息| ReactLoop["ReAct 循环<br/>react-loop.js"]
ReactLoop --> SaveCheckpoint["保存 Checkpoint<br/>saveReactCheckpoint()"]
SessionOps --> PersistIDB["写入 IndexedDB<br/>db.js withStore()"]
SaveCheckpoint --> PersistIDB
PersistIDB --> UpdateMemory["更新内存状态<br/>state.js"]
UpdateMemory --> RenderUI
图表来源
- src/storage/session-store.js#L42-L113
- src/storage/db.js#L154-L252
- src/background/react-loop.js#L1037-L1075
章节来源
- src/side_panel/state.js#L1-L74
- src/storage/session-store.js#L42-L113
- src/storage/db.js#L154-L252
- src/background/react-loop.js#L1037-L1075
详细组件分析
IndexedDB 数据模型与版本管理
数据库名称为 ai-helper-db,当前版本为 6。对象存储包括:
sessions:活跃会话,主键id,索引updatedAt。activeSession:单条记录,keyPathkey,用于保存当前活跃会话 ID。archivedSessions:归档会话,主键id,索引createdAt。uiPrototypes:UI 原型,主键id,索引createdAt、sessionId。tokenStats:Token 使用统计,主键id,索引sessionId、timestamp。reactCheckpoints:ReAct Checkpoint,主键sessionId,索引updatedAt。bookmarks:消息收藏,主键id,索引sessionId、createdAt。scheduledTasks:定时任务,主键id,索引nextRunAt、enabled。
erDiagram
SESSIONS {
string id PK
string title
string model
boolean useTools
array enabledTools
string agentId
number temperature
number topP
array messageHistory
string updatedAt
number order
boolean isGenerating
array lastExecutionLog
}
ACTIVE_SESSION {
string key PK
string sessionId
}
ARCHIVED_SESSIONS {
string id PK
string title
string createdAt
array messages
}
UI_PROTOTYPES {
string id PK
string sessionId
string createdAt
}
TOKEN_STATS {
string id PK
string sessionId
string timestamp
string model
number promptTokens
number completionTokens
number totalTokens
number contextWindow
number contextUsageRate
string callType
}
REACT_CHECKPOINTS {
string sessionId PK
array currentMessages
array executionLog
number iteration
object globalIteration
object subtaskPlan
number currentSubtaskIndex
number totalReflectionRounds
string model
object apiParams
object taskContext
number tabId
string callId
string interruptedReason
number createdAt
number updatedAt
}
BOOKMARKS {
string id PK
string sessionId
string messageId
string content
string sessionTitle
string createdAt
boolean pinned
}
SCHEDULED_TASKS {
string id PK
string nextRunAt
boolean enabled
}
SESSIONS ||--o{ TOKEN_STATS : "按 sessionId 关联"
SESSIONS ||--o{ BOOKMARKS : "按 sessionId 关联"
UI_PROTOTYPES ||--o{ SESSIONS : "按 sessionId 关联"
REACT_CHECKPOINTS ||--|| SESSIONS : "按 sessionId 对应"
图表来源
章节来源
事务处理与并发访问控制
withStore 是统一的事务包装器,负责:
- 检查 store 是否存在,若缺失则关闭连接并重置单例,延迟重试以触发
onupgradeneeded。 - 捕获
transaction()同步异常,在失败时重置连接并重试一次。 - 在
tx.oncomplete中 resolve,确保事务提交后再返回结果。 - 在
tx.onerror与tx.onabort中执行连接重置与重试逻辑。 - 支持
isRetry标志,避免无限重试。
此外,openDB 中处理了 onversionchange 与 onblocked:
onversionchange:当其他连接触发版本变更时主动关闭当前连接,避免阻塞 DB 升级。onblocked:当升级被阻塞时记录警告,等待后续重试。
flowchart TD
Enter(["withStore 调用"]) --> CheckStore["检查 store 是否存在"]
CheckStore --> |不存在| CloseConn["关闭连接并重置单例"]
CloseConn --> DelayRetry["延迟 50ms 重试"]
DelayRetry --> RetryCall["再次调用 withStore"]
CheckStore --> |存在| CreateTx["创建事务"]
CreateTx --> ExecCallback["执行回调"]
ExecCallback --> TxComplete{"事务完成?"}
TxComplete --> |是| Resolve["resolve 结果"]
TxComplete --> |否| TxError{"事务错误/中止?"}
TxError --> |是| ResetAndRetry["重置连接并重试"]
TxError --> |否| Wait["等待 oncomplete/onerror/onabort"]
图表来源
章节来源
会话状态与变更追踪
session-store.js 提供与旧 API 兼容的会话操作:
init():首次调用时执行ensureMigration(),并清理孤儿scrollPosition_*key。loadSessions():并行加载会话列表与活跃会话 ID,按order排序。saveCurrentSession():将当前内存状态映射到会话对象并持久化。createSession()/importSessions()/appendMessageToSession():创建、导入、追加消息。switchToSession():并发保存当前会话、读取目标会话、设置活跃会话 ID、恢复模型/温度/工具等状态。deleteStoreSession():删除会话、清理 scrollPosition、checkpoint、收藏,并就近激活相邻会话。archiveCurrentSession()/restoreArchivedSession()/duplicateSession()/createScheduledSession():归档、恢复、复制、定时任务宿主会话。
sequenceDiagram participant UI as "侧边栏 UI" participant Store as "session-store.js" participant IDB as "db.js" participant State as "side_panel/state.js" UI->>Store : switchToSession(sessionId) Store->>Store : saveCurrentSession() Store->>IDB : getSession(sessionId) IDB-->>Store : targetSession Store->>IDB : setActiveSessionId(sessionId) Store->>State : 恢复 activeSessionId/messageHistory/model/temperature/topP/tools Store-->>UI : 返回 targetSession
图表来源
章节来源
ReAct Checkpoint 双写与恢复
ReAct Checkpoint 是长任务中断后的断点续接数据,采用双写策略:
- 先写
chrome.storage.local(可靠),再尝试写入 IndexedDB(性能优化)。 - 读取时优先 IndexedDB,失败降级到
chrome.storage.local。 - 删除时同时清理两处存储。
- SW 启动时清理超过 7 天的过期 checkpoint。
sequenceDiagram
participant Loop as "react-loop.js"
participant DB as "db.js"
participant Storage as "chrome.storage.local"
participant SW as "background/index.js"
Loop->>DB : saveReactCheckpoint(checkpoint)
DB->>Storage : set(key, data)
DB->>DB : withStore('reactCheckpoints', 'readwrite')
Note over DB,Storage : 双写:storage.local 为主,IDB 为辅
SW->>DB : cleanupExpiredReactCheckpoints()
DB->>DB : getAllReactCheckpoints()
DB->>DB : deleteReactCheckpoint(sessionId)
图表来源
章节来源
- src/storage/db.js#L633-L703
- src/storage/db.js#L786-L799
- src/background/index.js#L74-L95
- src/background/react-loop.js#L1037-L1075
状态迁移与版本兼容性
migrateFromChromeStorage():将旧chrome.storage.local中的sessions与conversationSessions迁移到 IndexedDB,并清理旧的大数据 key。ensureMigration():若 IndexedDB 无数据且无活跃会话标记,则尝试迁移。session-store.js的init()在首次加载时调用ensureMigration()。db.js的DB_VERSION = 6,并在onupgradeneeded中按需创建 store 与索引。
flowchart TD
AppStart["应用启动"] --> SessionInit["session-store.init()"]
SessionInit --> Ensure["ensureMigration()"]
Ensure --> HasData{"IndexedDB 有数据?"}
HasData --> |是| Ready["就绪"]
HasData --> |否| Migrate["migrateFromChromeStorage()"]
Migrate --> CleanOld["清理旧 storage.local 大数据 key"]
CleanOld --> Ready
图表来源
章节来源
用户偏好与配置同步
语言偏好通过 shared/i18n.js 初始化:
- 从
chrome.storage.local读取language。 - 未设置时根据浏览器语言自动检测并持久化。
- 监听
chrome.storage.onChanged,实现跨环境同步。
sequenceDiagram
participant Env as "任意环境"
participant I18n as "shared/i18n.js"
participant Storage as "chrome.storage.local"
Env->>I18n : initI18n()
I18n->>Storage : get('language')
Storage-->>I18n : language
I18n->>Storage : set({ language })
Storage-->>I18n : onChanged(language)
图表来源
章节来源
增强的会话取消键收集机制
更新 新增了 collectSessionCancelKeys 函数来改进子任务进度数据结构处理,支持更精确的会话取消范围控制。
collectSessionCancelKeys 函数实现了智能的取消键收集逻辑:
- 收集根会话自身及其全部派生会话的取消键
- 支持 plan_task 子任务的
${root}_subtask_${i}格式 - 支持 dispatch_task 子代理的
${root}_sub_${agentId}格式 - 按优先级排序:根会话优先,其余按 key 长度递增
flowchart TD
CollectKeys["collectSessionCancelKeys(sessionId, knownKeys)"] --> Validate{"验证 sessionId"}
Validate --> |无效| ReturnEmpty["返回空数组"]
Validate --> |有效| IterateKeys["遍历已知 keys"]
IterateKeys --> MatchKey{"匹配规则"}
MatchKey --> |等于 sessionId| AddRoot["添加根会话 key"]
MatchKey --> |以 sessionId_ 开头| AddDerived["添加派生会话 key"]
AddRoot --> SortKeys["排序:根优先,其余按长度"]
AddDerived --> SortKeys
SortKeys --> ReturnKeys["返回排序后的 keys"]
ReturnEmpty --> End["结束"]
ReturnKeys --> End
图表来源
章节来源
改进的标签页状态管理
更新 增强了派生会话祖先链和 keepalive 端口路由,改进了多 Tab 实例的消息路由。
新的标签页状态管理包含以下增强功能:
- 派生会话祖先链:通过
getSessionAncestry函数逐层剥离派生后缀,得到从自身到根任务的会话祖先链 - Keepalive 端口路由:支持定向消息路由,避免多 Tab 实例广播导致的误判
- 实例身份管理:记录 keepalive 连接上报的实例身份,支持可见性判定
sequenceDiagram participant Parent as "父会话" participant Child as "子任务/子代理" participant Registry as "会话注册表" participant Router as "消息路由器" Note over Parent,Child : 派生会话命名规则 Parent->>Registry : register(parent_session_id) Child->>Registry : register(parent_session_id_subtask_0) Note over Router : 消息路由查找 Router->>Registry : getKeepalivePort(child_session_id) Registry->>Registry : getSessionAncestry(child_session_id) Registry-->>Router : [child_session_id, parent_session_id] Router->>Registry : find port for parent_session_id Registry-->>Router : return parent_port
图表来源
章节来源
增强的子任务进度数据结构处理
更新 改进了子任务进度数据结构的错误处理,包括更好的部分进度记录和失败恢复机制。
新的子任务进度处理机制包括:
- 部分进度记录:
recordSubtaskPartialProgress函数支持增量式进度记录 - 失败恢复:
buildSubtaskFailureResult函数在重试耗尽后生成完整的失败报告 - 进度继承:
composeSubtaskInheritedContext函数支持进度上下文继承 - 节流保存:改进的 checkpoint 节流机制避免频繁磁盘写入
flowchart TD
SubtaskStart["子任务开始"] --> ProgressWriter["创建进度写入器"]
ProgressWriter --> ExecuteNodes["执行节点"]
ExecuteNodes --> RecordProgress["记录部分进度"]
RecordProgress --> CheckSuccess{"检查成功?"}
CheckSuccess --> |是| MarkDone["标记完成"]
CheckSuccess --> |否| BuildFailure["构建失败结果"]
MarkDone --> SaveCheckpoint["保存 checkpoint"]
BuildFailure --> AppendSummary["附加进度摘要"]
AppendSummary --> SaveCheckpoint
SaveCheckpoint --> SubtaskEnd["子任务结束"]
图表来源
章节来源
依赖关系与并发控制
组件依赖图
graph TB SP_State["side_panel/state.js"] BG_State["background/state.js"] SessionStore["session-store.js"] TokenStore["token-store.js"] DB["db.js"] IndexJS["background/index.js"] ReactLoop["background/react-loop.js"] SP_State --> SessionStore SessionStore --> DB TokenStore --> DB IndexJS --> DB ReactLoop --> DB IndexJS --> ReactLoop BG_State --> ReactLoop
图表来源
- src/storage/session-store.js#L1-L10
- src/storage/token-store.js#L1-L4
- src/storage/db.js#L1-L5
- src/background/index.js#L15-L95
- src/background/react-loop.js#L636-L726
章节来源
- src/storage/session-store.js#L1-L10
- src/storage/token-store.js#L1-L4
- src/storage/db.js#L1-L5
- src/background/index.js#L15-L95
- src/background/react-loop.js#L636-L726
并发与取消控制
- 后台
state.js维护每个会话的AbortController,支持取消 ReAct 循环与工具等待。 - 派生会话(子任务/子代理)通过祖先链回退到根会话进行取消与可见性判定。
- keepalive 端口注册表用于定向消息路由,避免多 Tab 实例广播导致的误判。
更新 改进了取消控制的范围和精度,现在能够更准确地取消子任务和工具等待。
flowchart TD
CancelReq["取消请求"] --> CheckType{"sessionId 还是 tabId?"}
CheckType --> |tabId| OldCompat["旧版兼容:cancelledTabs"]
CheckType --> |sessionId| NewCancel["cancelledSessions.set(sessionId, true)"]
NewCancel --> CollectKeys["collectSessionCancelKeys()"]
CollectKeys --> AbortFetch["sessionAbortControllers.get(key).abort()"]
OldCompat --> ClearAll["clearAll()"]
图表来源
章节来源
性能优化与大数据量策略
查询优化
getSessionTokenSummary使用sessionId索引与IDBKeyRange.bound缩小候选集,避免全表扫描。getDailyTokenSummary与getOverallTokenSummaryByRange使用timestamp索引进行范围查询。searchActiveSessionsMessages在指定sessionId时使用 O(1) 主键查询,避免加载所有会话。
缓存策略
db.js的getDB()返回单例连接,减少重复打开开销。session-store.js的loadSessions()并行加载会话列表与活跃会话 ID。switchToSession()并行发起保存当前会话与读取目标会话,提升切换性能。
性能监控建议
- 监控 IndexedDB 事务错误与 abort 次数,识别连接不稳定场景。
- 监控 ReAct Checkpoint 双写成功率,评估 IndexedDB 可用性。
- 监控 Token 统计聚合查询耗时,评估索引有效性。
- 监控 SW 启动时 checkpoint 清理数量,评估数据增长趋势。
章节来源
- src/storage/token-store.js#L52-L98
- src/storage/token-store.js#L194-L277
- src/storage/db.js#L486-L520
- src/storage/session-store.js#L85-L99
- src/storage/session-store.js#L302-L312
故障排查指南
IndexedDB 连接问题
- 现象:store 不存在导致写入静默失败。
- 原因:其他连接持有旧版本,阻塞升级。
- 解决:
withStore自动关闭连接并重置单例,延迟重试;onversionchange主动关闭当前连接。
Checkpoint 恢复失败
- 现象:前端显示"继续执行"但后端无法恢复。
- 原因:checkpoint 未成功双写或 sessionId 不匹配。
- 排查:检查
chrome.storage.local中react_checkpoint_*是否存在;查看getAllReactCheckpoints输出。
会话切换卡顿
- 现象:切换会话时 UI 卡顿。
- 原因:全量加载所有会话或消息历史过大。
- 优化:使用
order排序、分页加载、懒加载消息历史。
Token 统计查询缓慢
- 现象:Token 统计页面加载慢。
- 原因:全表扫描
tokenStats。 - 优化:使用
sessionId与timestamp索引,限制返回记录数。
子任务进度丢失
- 现象:子任务中断后进度信息不完整。
- 原因:部分进度记录未正确保存或失败恢复逻辑异常。
- 排查:检查
recordSubtaskPartialProgress调用点和buildSubtaskFailureResult返回值。
章节来源
- src/storage/db.js#L154-L252
- src/storage/db.js#L633-L703
- src/storage/token-store.js#L52-L98
- src/background/react-loop.js#L547-L619
结论
本项目的状态管理与持久化体系围绕三层展开:
- 内存状态:侧边栏与后台分别维护运行时状态,支持多会话并行与取消控制。
- 会话状态:IndexedDB 作为主存储,支持活跃会话、归档会话、收藏、原型、定时任务等。
- 配置与偏好:
chrome.storage.local作为轻量配置与后备存储,语言偏好跨环境同步。
更新后的关键设计亮点:
withStore统一事务包装,增强连接稳定性与错误恢复能力。- ReAct Checkpoint 双写策略保障长任务可靠性。
- 数据迁移与版本管理确保平滑升级。
- 查询优化与索引设计应对大数据量场景。
- 新增 智能会话取消键收集机制,支持精确的子任务取消范围控制。
- 新增 增强的标签页状态管理,改进派生会话祖先链和 keepalive 端口路由。
- 新增 改进的子任务进度数据结构处理,提供更好的错误处理和恢复机制。
未来改进方向:
- 引入增量聚合记录(如
overall汇总)减少全表扫描。 - 增加更细粒度的性能埋点与监控。
- 探索分片存储与异步批量写入,进一步提升高并发场景下的稳定性。
- 进一步优化子任务进度记录的准确性和完整性。