Skip to content

状态管理与持久化 ​

本文引用的源码文件

本文引用的文件

更新摘要 ​

变更内容

  • 更新了会话取消键收集机制,新增 collectSessionCancelKeys 函数以支持子任务进度数据结构处理
  • 增强了标签页状态管理,改进了派生会话祖先链和 keepalive 端口路由
  • 完善了子任务进度数据结构的错误处理机制
  • 优化了 ReAct 循环的取消控制和工具等待终止逻辑

目录 ​

  1. 引言
  2. 项目结构与职责边界
  3. 核心组件总览
  4. 架构总览:状态层次、存储分层与数据流
  5. 详细组件分析
  6. 依赖关系与并发控制
  7. 性能优化与大数据量策略
  8. 故障排查指南
  9. 结论

引言 ​

本文件聚焦 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.jsIndexedDB 封装层、数据库连接单例、事务包装器、ReAct Checkpoint 双写与 TTL 清理sessions、activeSession、archivedSessions、uiPrototypes、tokenStats、reactCheckpoints、bookmarks、scheduledTasksopenDB、withStore、CRUD、迁移、Checkpoint 读写
src/storage/session-store.js会话存储适配器,对接 IndexedDB,兼容旧 chrome.storage API活跃会话、归档会话、当前会话、滚动位置、收藏初始化迁移、创建/保存/切换/删除/归档/复制会话
src/storage/token-store.jsToken 使用统计的 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.jsReAct 推理循环、Checkpoint 节流保存、恢复流程currentMessages、executionLog、iteration、taskContextsaveCheckpointNow、resumeReactLoopFromCheckpoint、异常强制保存
src/shared/i18n.js国际化初始化与跨环境语言同步language 偏好从 chrome.storage.local 读取语言并监听变更

章节来源

架构总览:状态层次、存储分层与数据流 ​

状态层次 ​

  • 内存状态:侧边栏 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

图表来源

章节来源

详细组件分析 ​

IndexedDB 数据模型与版本管理 ​

数据库名称为 ai-helper-db,当前版本为 6。对象存储包括:

  • sessions:活跃会话,主键 id,索引 updatedAt。
  • activeSession:单条记录,keyPath key,用于保存当前活跃会话 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)

图表来源

章节来源

状态迁移与版本兼容性 ​

  • 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 实例的消息路由。

新的标签页状态管理包含以下增强功能:

  1. 派生会话祖先链:通过 getSessionAncestry 函数逐层剥离派生后缀,得到从自身到根任务的会话祖先链
  2. Keepalive 端口路由:支持定向消息路由,避免多 Tab 实例广播导致的误判
  3. 实例身份管理:记录 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

图表来源

章节来源

增强的子任务进度数据结构处理 ​

更新 改进了子任务进度数据结构的错误处理,包括更好的部分进度记录和失败恢复机制。

新的子任务进度处理机制包括:

  1. 部分进度记录:recordSubtaskPartialProgress 函数支持增量式进度记录
  2. 失败恢复:buildSubtaskFailureResult 函数在重试耗尽后生成完整的失败报告
  3. 进度继承:composeSubtaskInheritedContext 函数支持进度上下文继承
  4. 节流保存:改进的 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

图表来源

章节来源

并发与取消控制 ​

  • 后台 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 清理数量,评估数据增长趋势。

章节来源

故障排查指南 ​

IndexedDB 连接问题 ​

  • 现象:store 不存在导致写入静默失败。
  • 原因:其他连接持有旧版本,阻塞升级。
  • 解决:withStore 自动关闭连接并重置单例,延迟重试;onversionchange 主动关闭当前连接。

Checkpoint 恢复失败 ​

  • 现象:前端显示"继续执行"但后端无法恢复。
  • 原因:checkpoint 未成功双写或 sessionId 不匹配。
  • 排查:检查 chrome.storage.local 中 react_checkpoint_* 是否存在;查看 getAllReactCheckpoints 输出。

会话切换卡顿 ​

  • 现象:切换会话时 UI 卡顿。
  • 原因:全量加载所有会话或消息历史过大。
  • 优化:使用 order 排序、分页加载、懒加载消息历史。

Token 统计查询缓慢 ​

  • 现象:Token 统计页面加载慢。
  • 原因:全表扫描 tokenStats。
  • 优化:使用 sessionId 与 timestamp 索引,限制返回记录数。

子任务进度丢失 ​

  • 现象:子任务中断后进度信息不完整。
  • 原因:部分进度记录未正确保存或失败恢复逻辑异常。
  • 排查:检查 recordSubtaskPartialProgress 调用点和 buildSubtaskFailureResult 返回值。

章节来源

结论 ​

本项目的状态管理与持久化体系围绕三层展开:

  • 内存状态:侧边栏与后台分别维护运行时状态,支持多会话并行与取消控制。
  • 会话状态:IndexedDB 作为主存储,支持活跃会话、归档会话、收藏、原型、定时任务等。
  • 配置与偏好:chrome.storage.local 作为轻量配置与后备存储,语言偏好跨环境同步。

更新后的关键设计亮点:

  • withStore 统一事务包装,增强连接稳定性与错误恢复能力。
  • ReAct Checkpoint 双写策略保障长任务可靠性。
  • 数据迁移与版本管理确保平滑升级。
  • 查询优化与索引设计应对大数据量场景。
  • 新增 智能会话取消键收集机制,支持精确的子任务取消范围控制。
  • 新增 增强的标签页状态管理,改进派生会话祖先链和 keepalive 端口路由。
  • 新增 改进的子任务进度数据结构处理,提供更好的错误处理和恢复机制。

未来改进方向:

  • 引入增量聚合记录(如 overall 汇总)减少全表扫描。
  • 增加更细粒度的性能埋点与监控。
  • 探索分片存储与异步批量写入,进一步提升高并发场景下的稳定性。
  • 进一步优化子任务进度记录的准确性和完整性。