Skip to content

Latest commit

 

History

History
413 lines (347 loc) · 17.3 KB

File metadata and controls

413 lines (347 loc) · 17.3 KB

Agent Session Manager — 技术架构文档

内容
文档版本 v1.0
更新日期 2026-08-10
状态 已确认基线
关联文档 docs/REQUIREMENTS.md(需求)

1. 系统概述

单进程本地应用:Python 后端提供 HTTP API + 托管前端静态资源;Vue 3 前端经 Vite 构建后由后端 serve。启动一个命令即用。

┌──────────────────────────────────────────────┐
│  浏览器 (localhost:8000)                       │
│  ┌────────────────────────────────────────┐  │
│  │  Vue 3 SPA (Vite 构建产物)              │  │
│  └──────────────────┬─────────────────────┘  │
└─────────────────────┼────────────────────────┘
                      │ HTTP /api/*
┌─────────────────────▼────────────────────────┐
│  Python 后端 (单进程, http.server)            │
│  ┌──────────┐  ┌──────────┐  ┌───────────┐  │
│  │ 静态资源  │  │ API 路由  │  │ resume    │  │
│  │ serve    │  │ server.py│  │ (开终端)   │  │
│  └──────────┘  └────┬─────┘  └───────────┘  │
│                     │                         │
│         ┌───────────▼────────────┐           │
│         │  scanner / indexer      │           │
│         │  (差分同步)             │           │
│         └───────────┬────────────┘           │
│                     │                         │
│         ┌───────────▼────────────┐           │
│         │  adapters: pi/claude/codex│         │
│         └───────────┬────────────┘           │
│                     │                         │
│         ┌───────────▼────────────┐           │
│         │  SQLite (data/asm.db)   │           │
│         └────────────────────────┘           │
└──────────────────────────────────────────────┘
                      │ 读取
        ┌─────────────▼──────────────┐
        │  ~/.pi  ~/.claude  ~/.codex │
        └────────────────────────────┘

2. 技术栈选型

2.1 后端

选型 理由
语言 Python 3.12 本机已有;jsonl 解析、sqlite 标准库即用
HTTP http.server(标准库) 零第三方依赖,本地工具足够;实测内存 ~25MB
存储 sqlite3 + FTS5(标准库) 全文搜索白嫖标准库,本机已验证 FTS5 可用
依赖策略 零第三方依赖 复制目录即可运行;无原生编译风险

2.2 前端(采用构建模式)

选型 理由
框架 Vue 3(Composition API + <script setup> 模板化、组件化、TS 友好;中文社区成熟
构建 Vite Vue 官方一等支持;HMR 快;产物干净
语言 TypeScript 类型安全;后端模型可镜像成类型
UI 自写轻量组件(不引重型 UI 库) 控制体积,避免过度依赖
HTTP fetch 封装 无需 axios

选型权衡:Vue/Vite 引入 Node 构建链(开发期),换取组件化与可维护性;构建产物为纯静态文件,部署期后端仍零依赖、单进程


3. 总体分层架构

四层,单向依赖,职责隔离。新增 agent 只动适配层。

┌─────────────────────────────────────────────┐
│  表现层 Presentation                         │
│  frontend/ (Vue SPA)  +  backend server.py   │
└──────────────────┬──────────────────────────┘
                   │ HTTP
┌──────────────────▼──────────────────────────┐
│  应用层 Application                          │
│  scanner.py   扫描调度(聚合各 adapter)      │
│  indexer.py   差分同步(全量差分/增量差分)    │
│  resume.py    恢复调度(开终端窗口)           │
└──────────────────┬──────────────────────────┘
                   │
┌──────────────────▼──────────────────────────┐
│  适配层 Adapter(每 agent 一个文件)          │
│  adapters/base.py   Adapter 抽象基类         │
│  adapters/pi.py | claude.py | codex.py       │
└──────────────────┬──────────────────────────┘
                   │
┌──────────────────▼──────────────────────────┐
│  基础设施层 Infrastructure                   │
│  models.py    数据模型 / 枚举                 │
│  config.py    路径常量 / agent 注册表         │
│  db.py        SQLite 连接与底层操作           │
└─────────────────────────────────────────────┘

依赖规则:上层可调下层,下层不感知上层;适配层不直接写库(交 indexer);应用层不解析具体格式(交 adapter)。


4. 后端模块设计

4.1 模块职责表

文件 职责 禁止
models.py Session/Message 数据类、Agent/PermissionLevel 枚举 碰 IO、碰 SQL
config.py 各 agent 数据目录路径、AGENT_REGISTRY(名字→adapter) 含业务逻辑
db.py SQLite 连接、建表迁移、底层 CRUD 含业务逻辑、解析 jsonl
adapters/base.py Adapter 抽象基类(见 §4.2)
adapters/<agent>.py 解析该 agent jsonl → Session;构造 resume 命令 直接写库
scanner.py 遍历注册表,调 adapter 收集 (path, mtime, size) 解析具体格式
indexer.py 差分算法(§7)、FTS 维护、查询接口 解析 jsonl
resume.py 接收 (session, level),开终端窗口 构造命令
server.py HTTP 路由分发、参数校验、调应用层 业务逻辑
main.py 入口:建库 → 首次同步 → 起 HTTP → 开浏览器

4.2 Adapter 抽象接口(扩展点)

class Adapter(ABC):
    name: str            # "pi" | "claude" | "codex"
    data_dir: Path       # 该 agent session 根目录

    def discover(self) -> list[Path]:
        """发现该 agent 所有 session 文件路径。"""

    def fingerprint(self, path: Path) -> FileFingerprint:
        """返回 (path, mtime, size),供差分比对。"""

    def parse(self, path: Path) -> Session:
        """解析单文件 → Session 元数据(不含完整消息流)。"""

    def read_messages(self, path: Path) -> list[Message]:
        """读取完整消息流(详情页按需调用)。"""

    def build_resume_command(self, session: Session, level: PermissionLevel) -> str:
        """构造 resume 命令(含权限档位映射)。"""

    def supports_full_access(self) -> bool:
        """是否有独立 full 档(pi 返回 False)。"""

5. 前端架构

5.1 目录结构

frontend/
├─ index.html
├─ vite.config.ts        # dev proxy /api → http://localhost:8000
├─ tsconfig.json
├─ package.json
└─ src/
   ├─ main.ts            # 挂载入口
   ├─ App.vue            # 根布局(侧栏 + 主区)
   ├─ api/
   │  └─ client.ts       # fetch 封装 + 类型化接口
   ├─ stores/
   │  ├─ sessions.ts     # 会话列表/筛选/视图模式状态
   │  └─ index.ts        # 同步状态/统计
   ├─ views/
   │   ├─ SessionList.vue
   │   └─ SessionDetail.vue
   ├─ components/
   │   ├─ AgentFilter.vue
   │   ├─ SearchBar.vue
   │   ├─ SessionItem.vue
   │   └─ ResumeBar.vue  # 权限档位按钮
   ├─ composables/
   │   └─ useResume.ts
   └─ types/
      └─ models.ts       # 镜像后端 Session/Message 类型

5.2 关键约定

  • 状态管理:用 Vue 3 reactive 组合式(轻量场景不引 Pinia;若复杂再升级)。
  • 类型同步types/models.ts 手工镜像后端模型,保持字段一致(后续可考虑自动生成)。
  • 路由:hash 路由(#/#/session/:id),避免后端 history fallback 配置。

5.3 构建与部署

阶段 命令 产物
开发 npm run dev (Vite :5173) + python -m asm (:8000) Vite proxy /api 到后端
构建 npm run build frontend/dist/(纯静态)
部署 后端 server.pyfrontend/dist/ 映射为静态根 单进程对外

启动 python -m asm 即:serve 前端 dist + 提供 /api/* + 自动开浏览器。


6. 数据模型与 Schema

6.1 统一模型(Python)

@dataclass
class Session:
    id: str              # 原始 uuid,主键
    agent: Agent         # pi|claude|codex
    project_path: str    # 归一化 cwd
    title: str           # ≤80 字符
    message_count: int
    model: str           # 可空
    created_at: str      # ISO8601
    updated_at: str      # 文件 mtime, ISO8601
    file_path: str       # 原始 jsonl 路径

class Agent(str, Enum):  pi="pi"; claude="claude"; codex="codex"
class PermissionLevel(str, Enum): default="default"; full="full"

6.2 SQLite Schema

CREATE TABLE sessions (
    id            TEXT PRIMARY KEY,
    agent         TEXT NOT NULL,
    project_path  TEXT NOT NULL,
    title         TEXT,
    message_count INTEGER DEFAULT 0,
    model         TEXT,
    created_at    TEXT,
    updated_at    TEXT,
    file_path     TEXT NOT NULL,
    file_mtime    REAL,          -- 差分比对依据
    file_size     INTEGER,       -- 差分比对依据
    indexed_at    TEXT
);
CREATE INDEX idx_sessions_project ON sessions(project_path);
CREATE INDEX idx_sessions_updated ON sessions(updated_at);

CREATE VIRTUAL TABLE sessions_fts USING fts5(
    session_id UNINDEXED,
    title,
    content,
    tokenize = 'unicode61'       -- 按字符切分,兼容中文
);

-- 同步水位线(增量差分用)
CREATE TABLE sync_meta (
    key   TEXT PRIMARY KEY,
    value TEXT
);  -- key: last_scan_at, last_full_scan_at

7. 索引同步机制(核心)

v1.0 实现全量差分;v1.1 实现增量差分。两者都不做清空重插

7.1 全量差分(Full Diff)— v1.0

目标:遍历全部文件保证最终一致,但只对差集写入,未变化文件零解析。

输入: 各 adapter.discover() 得 current_files: {key: (mtime, size)}
      key = (agent, file_path)
步骤:
  1. scanner 收集 current_files(含 fingerprint,不解析内容)
  2. 从 DB 读 indexed: {key: (mtime, size, id, ...)}
  3. 计算差集:
       added   = current_keys - indexed_keys
       removed = indexed_keys - current_keys
       changed = {k ∈ current∩indexed | (mtime,size) 变了}
       unchanged = (current∩indexed) - changed
  4. 对 added ∪ changed:
       adapter.parse(k) → Session
       UPSERT sessions;删除并重建该 session 的 FTS 行
  5. 对 removed:
       DELETE sessions + sessions_fts(按 id)
  6. 更新 sync_meta.last_full_scan_at
  7. 返回 DiffStat(added, changed, removed, unchanged)

优点:能检测外部删除(最终一致);unchanged 完全跳过解析与 FTS 写入,省 IO/CPU。

7.2 增量差分(Incremental Diff)— v1.1

目标:以水位线过滤,只处理「自上次扫描以来变化」的文件,减少比对与解析量。

输入: last_scan_at (水位线)
步骤:
  1. scanner 遍历目录(文件系统无变更通知则仍需遍历),
     但仅收集 mtime > last_scan_at 的文件 → changed_set
  2. 对 changed_set 内每个文件:
       fingerprint 对比 DB;变化则 parse + UPSERT + 重建 FTS
  3. 更新 sync_meta.last_scan_at = now
  4. 删除检测(增量难发现):
       策略 A: 每 N 次增量后自动触发一次全量差分校准
       策略 B: 提供「全量校准」按钮手动触发

说明(技术诚实):纯标准库无文件事件监听,增量仍需遍历目录;相比全量差分,主要省掉未变化文件的解析与 DB 写入。真正事件驱动增量需引入 watchdog(第三方依赖),列为 v2 可选增强。

7.3 触发时机

触发 行为
首次启动 全量差分
手动「重建索引」 全量差分
手动「同步」(v1.1) 增量差分
定时后台(可选) 增量差分 + 周期全量校准

8. 权限档位机制

8.1 映射表(隔离在各 adapter)

Agent default 命令 full 命令 supports_full_access
pi pi --session <id> False
claude claude --resume <id> claude --resume <id> --dangerously-skip-permissions True
codex codex resume <id> codex resume <id> -s danger-full-access True

8.2 流程

前端 ResumeBar → POST /api/sessions/{id}/resume {level}
  → server 校验 localhost + level
  → resume.py 调 adapter.build_resume_command(session, level)
  → Windows: subprocess 调 start/wt 开新终端窗口执行命令
  → 返回 {ok, command}

8.3 前端交互

  • default / full 两按钮。
  • adapter supports_full_access()=False(pi)时,full 按钮置灰,tooltip 说明「该 agent 无权限边界」。
  • full 按钮旁固定风险提示文案。

9. API 设计

方法 路径 说明
GET /api/sessions ?view=project|timeline&agent=pi,claude&q=词
GET /api/sessions/{id} 详情(含完整消息流)
POST /api/sessions/{id}/resume body {"level":"default"|"full"} → 开终端
POST /api/reindex 全量差分同步,返回 DiffStat
POST /api/sync (v1.1) 增量差分同步
GET /api/stats 索引状态:按 agent 计数、last_scan_at、上次 DiffStat

10. 扩展性设计

10.1 新增 agent(如 cursor)

  1. adapters/cursor.py 实现 Adapter 接口。
  2. config.pyAGENT_REGISTRY 加一行 "cursor": CursorAdapter
  3. 前端 types/models.ts 的 Agent 枚举加值(可选,筛选器自动渲染)。
  4. 其他层零改动。

10.2 新增权限档位(如 codex read-only)

  1. models.pyPermissionLevel 加值。
  2. 各 adapter 的 build_resume_command 加映射分支。
  3. 前端 ResumeBar 按枚举渲染按钮。

10.3 切换前端框架

后端仅依赖 /api/* + 静态目录,前端可整体替换(如换 React)而不动后端。


11. 构建与运行

11.1 目录结构总览

agent_session_manager/
├─ backend/
│  ├─ asm/
│  │   ├─ __init__.py
│  │   ├─ main.py
│  │   ├─ server.py
│  │   ├─ scanner.py
│  │   ├─ indexer.py
│  │   ├─ resume.py
│  │   ├─ models.py
│  │   ├─ config.py
│  │   ├─ db.py
│  │   └─ adapters/{__init__,base,pi,claude,codex}.py
│  └─ pyproject.toml
├─ frontend/                    # Vue 3 + Vite
│  ├─ src/...
│  ├─ vite.config.ts
│  └─ package.json
├─ docs/{REQUIREMENTS,ARCHITECTURE}.md
├─ data/                        # 运行时 asm.db
└─ README.md

11.2 命令

操作 命令
前端开发 cd frontend && npm run dev
后端开发 cd backend && python -m asm
前端构建 cd frontend && npm run build → 产物入 frontend/dist
一键运行(生产) python -m asm(serve dist + API + 开浏览器)

11.3 启动流程(main.py)

  1. 初始化 DB(建表/迁移)。
  2. 若索引为空 → 首次全量差分同步。
  3. http.server 监听 127.0.0.1:8000。
  4. 注册路由:/api/* 走 API;其余走 frontend/dist 静态。
  5. webbrowser.open("http://127.0.0.1:8000")

12. 开放问题(实现期确认)

  • codex resume <id> 已验证支持直传 id;运行时若 picker 仍弹出,回退为复制命令到剪贴板。
  • FTS5 unicode61 对中文按字符切分,召回尚可但非分词级;若不满意可后续接入 jieba(引入第三方依赖,v2 评估)。
  • 虚拟滚动/分页阈值待会话规模实测后定。