# 分层上下文架构设计方案

## 一、当前问题分析

### 1.1 核心问题

| 问题                              | 位置                        | 描述                                                |
| --------------------------------- | --------------------------- | --------------------------------------------------- |
| **共享 `_messages`**              | `agent-chat.js:100`         | `this._messages = []` 是实例级别，所有 session 共用 |
| **并行 session 冲突**             | `_doChat()`                 | 多个 session 并行时，`_messages` 互相覆盖           |
| **Session 历史加载到共享内存**    | `_loadHistoryFromSession()` | 加载历史到共享的 `_messages`，导致竞态条件          |
| **上下文层次不清晰**              | `runWithContext()`          | `context` 只有 `{sessionId, isStream}`，缺少分层    |
| **Handler 与 SessionPlugin 耦合** | `_loadHistoryFromSession()` | 直接依赖 `sessionPlugin.getHistory()`               |

### 1.2 问题代码示例

```javascript
// agent-chat.js:100 - 共享的消息存储
this._messages = []; // 问题：所有 session 共用！

// agent-chat.js:899-904 - 并行时的竞态
if (sessionId) {
  const savedMessages = this._loadHistoryFromSession(sessionId);
  if (savedMessages.length > 0) {
    this._messages = savedMessages; // 问题：覆盖其他 session 的消息
  }
}
```

### 1.3 架构问题图示

```
当前架构：
┌─────────────────────────────────────────────────────────────┐
│                  AgentChatHandler                            │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  this._messages[]  ←── 所有 session 共用！           │    │
│  │  this._sessionQueues  ← Per-Session 队列（正确）     │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    SessionPlugin                              │
│  _sessions Map → { messages[], variables, metadata }        │
└─────────────────────────────────────────────────────────────┘

并行请求时：
Request A (session A) ──→ 加载 session A 历史 ──→ _messages = [A的历史]
                                        │
Request B (session B) ──→ 加载 session B 历史 ──→ _messages = [B的历史]  ← 覆盖！
                                        │
Request A 继续 ──→ _messages 被 B 覆盖了！ ──→ 保存到 A ──→ A 的历史变成 B 的
```

---

## 二、设计目标

1. **Per-Session 状态隔离** - 每个 session 有独立的消息存储
2. **分层上下文** - Request / Session / Agent 三层分离
3. **可追踪性** - 完整的 requestId、traceId 链路追踪
4. **向后兼容** - 最小化对现有代码的改动
5. **可扩展性** - 易于添加新的上下文层、支持多种存储后端

---

## 三、分层上下文架构

### 3.1 层次结构

```
┌─────────────────────────────────────────────────────────────┐
│                    Request Context                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  requestId    - 唯一请求 ID                          │   │
│  │  traceId      - 分布式追踪 ID                         │   │
│  │  parentSpanId - 父 span ID（用于链路追踪）            │   │
│  │  timeout      - 请求超时时间                          │   │
│  │  startTime    - 请求开始时间                          │   │
│  │  isStream     - 是否为流式请求                         │   │
│  │  userId       - 用户标识（可选）                       │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Session Context                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  sessionId    - 会话 ID                              │   │
│  │  userId       - 用户标识                              │   │
│  │  variables    - Map<key, value> 会话变量            │   │
│  │  metadata      - 会话元数据                           │   │
│  │  messageStore  - Per-Session 消息存储                │   │
│  │    messages[]  - 该 session 的对话历史              │   │
│  │    historyLoaded - 是否已加载历史                     │   │
│  │  createdAt     - 创建时间                            │   │
│  │  lastActive    - 最后活跃时间                        │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Agent Context                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  agentId      - Agent 实例 ID                        │   │
│  │  name         - Agent 名称                           │   │
│  │  tools        - 该 Agent 的工具注册表                │   │
│  │  skills       - 该 Agent 的技能列表                  │   │
│  │  systemPrompt - 系统提示词（动态构建）               │   │
│  │  customData   - Agent 级自定义数据                   │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
```

### 3.2 AsyncLocalStorage 隔离策略

```javascript
// Framework 中的三层 AsyncLocalStorage
class Framework {
  constructor() {
    // 三层独立的异步上下文存储
    this._requestStorage = new AsyncLocalStorage(); // Request 级别
    this._sessionStorage = new AsyncLocalStorage(); // Session 级别
    this._agentStorage = new AsyncLocalStorage(); // Agent 级别

    // SessionContext 管理
    this._sessionContexts = new Map(); // sessionId → SessionContext
  }
}
```

### 3.3 上下文获取方法

```javascript
class Framework {
  // Request Context
  runWithContext(context, fn) {
    return this._requestStorage.run(context, fn);
  }

  getRequestContext() {
    return this._requestStorage.getStore() || null;
  }

  // Session Context
  runInSession(sessionId, fn) {
    const sessionCtx = this.getOrCreateSessionContext(sessionId);
    return this._sessionStorage.run({ sessionContext: sessionCtx }, fn);
  }

  getSessionContext() {
    return this._sessionStorage.getStore()?.sessionContext || null;
  }

  // Agent Context
  runWithAgent(agentId, fn) {
    const agentCtx = this._agentContexts.get(agentId);
    return this._agentStorage.run({ agentContext: agentCtx }, fn);
  }

  getAgentContext() {
    return this._agentStorage.getStore()?.agentContext || null;
  }
}
```

---

## 四、核心类设计

### 4.1 SessionContext 类

```javascript
/**
 * SessionContext - Session 级别的上下文封装
 *
 * 职责：
 * 1. 管理 Per-Session 的消息存储
 * 2. 管理会话变量（variables）
 * 3. 跟踪会话元数据
 * 4. 处理上下文压缩状态
 */
class SessionContext {
  /**
   * @param {string} sessionId - 会话 ID
   * @param {Framework} framework - 框架实例
   * @param {Object} options - 配置选项
   */
  constructor(sessionId, framework, options = {}) {
    this.sessionId = sessionId;
    this.framework = framework;

    // 会话变量（可被工具读写）
    this.variables = new Map();

    // 元数据
    this.metadata = {
      createdAt: Date.now(),
      lastActive: Date.now(),
      messageCount: 0,
      compressionCount: 0,
      ...options.metadata,
    };

    // Per-Session 消息存储
    this.messageStore = {
      messages: [], // 对话历史
      historyLoaded: false, // 是否已从持久化加载
      systemPrompt: null, // 当前系统提示词
    };

    // 压缩状态
    this.compressionState = {
      lastCompressedAt: null,
      lastTokenCount: 0,
      pendingCompression: false,
    };

    // 自定义数据插槽
    this.customData = new Map();
  }

  // ==================== 消息管理 ====================

  /**
   * 获取消息历史
   * @returns {Array} 消息数组
   */
  getMessages() {
    return this.messageStore.messages;
  }

  /**
   * 添加消息
   * @param {Object} message - 消息对象
   */
  addMessage(message) {
    this.messageStore.messages.push(message);
    this.metadata.messageCount++;
    this.metadata.lastActive = Date.now();
  }

  /**
   * 添加多条消息
   * @param {Array} messages - 消息数组
   */
  addMessages(messages) {
    for (const msg of messages) {
      this.addMessage(msg);
    }
  }

  /**
   * 替换所有消息（用于压缩后同步）
   * @param {Array} messages - 新消息数组
   */
  replaceMessages(messages) {
    this.messageStore.messages = messages;
  }

  /**
   * 清空消息历史
   */
  clearMessages() {
    this.messageStore.messages = [];
  }

  // ==================== 变量管理 ====================

  /**
   * 获取变量
   * @param {string} key - 变量名
   * @param {*} defaultValue - 默认值
   * @returns {*}
   */
  getVariable(key, defaultValue = undefined) {
    return this.variables.get(key) ?? defaultValue;
  }

  /**
   * 设置变量
   * @param {string} key - 变量名
   * @param {*} value - 变量值
   */
  setVariable(key, value) {
    this.variables.set(key, value);
  }

  /**
   * 删除变量
   * @param {string} key - 变量名
   */
  deleteVariable(key) {
    this.variables.delete(key);
  }

  /**
   * 获取所有变量
   * @returns {Object}
   */
  getAllVariables() {
    return Object.fromEntries(this.variables);
  }

  // ==================== 元数据 ====================

  /**
   * 更新最后活跃时间
   */
  touch() {
    this.metadata.lastActive = Date.now();
  }

  /**
   * 获取会话摘要
   * @returns {Object}
   */
  getSummary() {
    return {
      sessionId: this.sessionId,
      messageCount: this.metadata.messageCount,
      createdAt: this.metadata.createdAt,
      lastActive: this.metadata.lastActive,
      variables: this.getAllVariables(),
    };
  }
}
```

### 4.2 RequestContext 类（轻量）

```javascript
/**
 * RequestContext - Request 级别的上下文封装
 *
 * 职责：
 * 1. 追踪请求链路
 * 2. 管理请求级超时
 * 3. 传递请求元数据
 */
class RequestContext {
  constructor(options = {}) {
    this.requestId = options.requestId || generateId();
    this.traceId = options.traceId || generateId();
    this.parentSpanId = options.parentSpanId || null;

    this.timeout = options.timeout || 120000; // 默认 2 分钟
    this.startTime = options.startTime || Date.now();

    this.isStream = options.isStream || false;
    this.userId = options.userId || null;

    // 请求级状态
    this.cancelled = false;
    this.abortController = new AbortController();
  }

  /**
   * 检查是否超时
   * @returns {boolean}
   */
  isTimeout() {
    return Date.now() - this.startTime > this.timeout;
  }

  /**
   * 取消请求
   */
  cancel() {
    this.cancelled = true;
    this.abortController.abort();
  }

  /**
   * 获取请求耗时（毫秒）
   * @returns {number}
   */
  getElapsed() {
    return Date.now() - this.startTime;
  }
}
```

### 4.3 AgentContext 类（轻量）

```javascript
/**
 * AgentContext - Agent 级别的上下文封装
 *
 * 职责：
 * 1. 隔离不同 Agent 实例的状态
 * 2. 管理 Agent 级工具注册
 * 3. 管理 Agent 级技能
 */
class AgentContext {
  constructor(agentId, agent) {
    this.agentId = agentId;
    this.agent = agent; // Agent 实例引用

    // Agent 级工具注册（覆盖全局）
    this.tools = new Map();

    // Agent 级技能
    this.skills = [];

    // Agent 级系统提示词
    this.systemPrompt = null;

    // 自定义数据
    this.customData = new Map();
  }

  /**
   * 注册工具
   * @param {Object} toolDef - 工具定义
   */
  registerTool(toolDef) {
    this.tools.set(toolDef.name, toolDef);
  }

  /**
   * 获取工具
   * @param {string} name - 工具名
   * @returns {Object|null}
   */
  getTool(name) {
    return this.tools.get(name) || null;
  }

  /**
   * 获取所有工具
   * @returns {Array}
   */
  getAllTools() {
    return Array.from(this.tools.values());
  }
}
```

### 4.4 ContextManager 类

```javascript
/**
 * ContextManager - 上下文管理器
 *
 * 职责：
 * 1. 统一管理所有 Context 的生命周期
 * 2. 提供上下文查询接口
 * 3. 处理上下文清理和资源释放
 */
class ContextManager {
  constructor(framework) {
    this.framework = framework;

    // Context 存储
    this._requestContexts = new Map(); // requestId → RequestContext
    this._sessionContexts = new Map(); // sessionId → SessionContext
    this._agentContexts = new Map(); // agentId → AgentContext

    // 引用计数（用于自动清理）
    this._refCounts = new Map();
  }

  // ==================== Request Context ====================

  /**
   * 创建 Request Context
   * @param {Object} options
   * @returns {RequestContext}
   */
  createRequestContext(options = {}) {
    const ctx = new RequestContext(options);
    this._requestContexts.set(ctx.requestId, ctx);
    this._refCounts.set(`request:${ctx.requestId}`, 1);
    return ctx;
  }

  /**
   * 获取 Request Context
   * @param {string} requestId
   * @returns {RequestContext|null}
   */
  getRequestContext(requestId) {
    return this._requestContexts.get(requestId) || null;
  }

  /**
   * 释放 Request Context
   * @param {string} requestId
   */
  releaseRequestContext(requestId) {
    const ctx = this._requestContexts.get(requestId);
    if (ctx) {
      ctx.cancel();
      this._requestContexts.delete(requestId);
      this._refCounts.delete(`request:${requestId}`);
    }
  }

  // ==================== Session Context ====================

  /**
   * 获取或创建 Session Context
   * @param {string} sessionId
   * @param {Object} options
   * @returns {SessionContext}
   */
  getOrCreateSessionContext(sessionId, options = {}) {
    let ctx = this._sessionContexts.get(sessionId);
    if (!ctx) {
      ctx = new SessionContext(sessionId, this.framework, options);
      this._sessionContexts.set(sessionId, ctx);
      this._refCounts.set(`session:${sessionId}`, 1);
    } else {
      // 增加引用计数
      this._refCounts.set(
        `session:${sessionId}`,
        (this._refCounts.get(`session:${sessionId}`) || 0) + 1
      );
    }
    return ctx;
  }

  /**
   * 获取 Session Context
   * @param {string} sessionId
   * @returns {SessionContext|null}
   */
  getSessionContext(sessionId) {
    return this._sessionContexts.get(sessionId) || null;
  }

  /**
   * 释放 Session Context
   * @param {string} sessionId
   */
  releaseSessionContext(sessionId) {
    const count = this._refCounts.get(`session:${sessionId}`) || 0;
    if (count <= 1) {
      this._sessionContexts.delete(sessionId);
      this._refCounts.delete(`session:${sessionId}`);
    } else {
      this._refCounts.set(`session:${sessionId}`, count - 1);
    }
  }

  // ==================== 统计 ====================

  /**
   * 获取统计信息
   * @returns {Object}
   */
  getStats() {
    return {
      activeRequests: this._requestContexts.size,
      activeSessions: this._sessionContexts.size,
      activeAgents: this._agentContexts.size,
    };
  }
}
```

---

## 五、Framework 改造

### 5.1 新增方法

```javascript
// src/core/framework.js 新增

const { AsyncLocalStorage } = require('async_hooks');

class Framework extends EventEmitter {
  constructor(config = {}) {
    super();
    // ... 现有代码 ...

    // 三层 AsyncLocalStorage
    this._requestStorage = new AsyncLocalStorage();
    this._sessionStorage = new AsyncLocalStorage();
    this._agentStorage = new AsyncLocalStorage();

    // Context 管理器
    this._contextManager = new ContextManager(this);

    // SessionContext 缓存（轻量管理，不依赖 ContextManager）
    this._sessionContexts = new Map();
  }

  // ==================== Request Context ====================

  /**
   * 在 Request 上下文中执行函数
   * @param {Object} context - Request 上下文
   * @param {Function} fn - 异步函数
   * @returns {Promise}
   */
  runWithContext(context, fn) {
    return this._requestStorage.run(context, fn);
  }

  /**
   * 获取当前 Request 上下文
   * @returns {Object|null}
   */
  getRequestContext() {
    return this._requestStorage.getStore() || null;
  }

  /**
   * 创建 Request Context 并执行
   * @param {Object} options - Request 选项
   * @param {Function} fn - 异步函数
   * @returns {Promise}
   */
  async withRequest(options, fn) {
    const requestCtx = new RequestContext(options);
    return this._requestStorage.run(requestCtx, fn);
  }

  // ==================== Session Context ====================

  /**
   * 获取或创建 SessionContext
   * @param {string} sessionId - 会话 ID
   * @param {Object} options - 配置选项
   * @returns {SessionContext}
   */
  getOrCreateSessionContext(sessionId, options = {}) {
    let ctx = this._sessionContexts.get(sessionId);
    if (!ctx) {
      ctx = new SessionContext(sessionId, this, options);
      this._sessionContexts.set(sessionId, ctx);
      this.emit('session:context-created', ctx);
    }
    return ctx;
  }

  /**
   * 在 Session 上下文中执行函数
   * @param {string} sessionId - 会话 ID
   * @param {Object} options - Session 选项
   * @param {Function} fn - 异步函数
   * @returns {Promise}
   */
  async runInSession(sessionId, options, fn) {
    const sessionCtx = this.getOrCreateSessionContext(sessionId, options);
    const context = { sessionContext: sessionCtx, sessionId };
    return this._sessionStorage.run(context, fn);
  }

  /**
   * 获取当前 Session 上下文（便捷方法）
   * @returns {SessionContext|null}
   */
  getSessionContext() {
    const store = this._sessionStorage.getStore();
    return store?.sessionContext || null;
  }

  /**
   * 获取当前 sessionId（便捷方法）
   * @returns {string|null}
   */
  getCurrentSessionId() {
    const store = this._sessionStorage.getStore();
    return store?.sessionId || null;
  }

  /**
   * 销毁 Session Context
   * @param {string} sessionId
   */
  destroySessionContext(sessionId) {
    if (this._sessionContexts.has(sessionId)) {
      const ctx = this._sessionContexts.get(sessionId);
      this._sessionContexts.delete(sessionId);
      this.emit('session:context-destroyed', ctx);
    }
  }

  // ==================== Agent Context ====================

  /**
   * 获取或创建 AgentContext
   * @param {string} agentId
   * @param {Agent} agent
   * @returns {AgentContext}
   */
  getOrCreateAgentContext(agentId, agent) {
    if (!this._agentContexts) {
      this._agentContexts = new Map();
    }
    let ctx = this._agentContexts.get(agentId);
    if (!ctx) {
      ctx = new AgentContext(agentId, agent);
      this._agentContexts.set(agentId, ctx);
    }
    return ctx;
  }

  /**
   * 在 Agent 上下文中执行函数
   * @param {string} agentId
   * @param {Function} fn
   * @returns {Promise}
   */
  runWithAgent(agentId, fn) {
    const ctx = this._agentContexts.get(agentId);
    if (!ctx) {
      throw new Error(`AgentContext not found: ${agentId}`);
    }
    return this._agentStorage.run({ agentContext: ctx, agentId }, fn);
  }

  /**
   * 获取当前 Agent 上下文
   * @returns {AgentContext|null}
   */
  getAgentContext() {
    const store = this._agentStorage.getStore();
    return store?.agentContext || null;
  }

  // ==================== 组合上下文 ====================

  /**
   * 在完整上下文中执行（Request + Session + Agent）
   * @param {Object} requestOptions - Request 选项
   * @param {string} sessionId - Session ID
   * @param {string} agentId - Agent ID
   * @param {Function} fn - 异步函数
   * @returns {Promise}
   */
  async runInFullContext(requestOptions, sessionId, agentId, fn) {
    const requestCtx = new RequestContext(requestOptions);
    const sessionCtx = this.getOrCreateSessionContext(sessionId);
    const agentCtx = this.getOrCreateAgentContext(
      agentId,
      this._agents.find((a) => a.id === agentId)
    );

    const requestStore = { ...requestCtx };
    const sessionStore = { sessionContext: sessionCtx, sessionId };
    const agentStore = { agentContext: agentCtx, agentId };

    return this._requestStorage.run(requestStore, () => {
      return this._sessionStorage.run(sessionStore, () => {
        return this._agentStorage.run(agentStore, fn);
      });
    });
  }
}
```

---

## 六、AgentChatHandler 改造

### 6.1 Per-Session 消息存储

```javascript
// agent-chat.js 改造

class AgentChatHandler extends EventEmitter {
  constructor(agent, config = {}) {
    super();

    // 移除共享的 _messages
    // this._messages = [];  // 删除！

    // 保留队列机制（已经是 Per-Session，正确）
    this._sessionQueues = new Map();
    this._processingSessions = new Set();

    // Per-Session 消息存储（替代原来的 _messages）
    // 结构：sessionId → { messages: [], historyLoaded: false, compressionState: {} }
    this._sessionMessageStores = new Map();

    // ...
  }

  /**
   * 获取当前 session 的消息存储
   * @private
   * @returns {Object} messageStore
   */
  _getSessionMessageStore(sessionId) {
    if (!sessionId) {
      // 无 session 的单次请求，使用临时存储
      return { messages: [], historyLoaded: false };
    }

    if (!this._sessionMessageStores.has(sessionId)) {
      this._sessionMessageStores.set(sessionId, {
        messages: [],
        historyLoaded: false,
        compressionState: {
          lastCompressedAt: null,
          lastTokenCount: 0,
        },
      });
    }
    return this._sessionMessageStores.get(sessionId);
  }

  /**
   * 从 session 存储加载聊天历史
   * @param {string} sessionId
   * @returns {Array}
   * @private
   */
  _loadHistoryFromSession(sessionId) {
    if (!sessionId) return [];

    try {
      // 优先从 SessionContext 获取
      const sessionCtx = this.framework.getSessionContext();
      if (sessionCtx && sessionCtx.sessionId === sessionId) {
        const messages = sessionCtx.getMessages();
        if (messages && messages.length > 0) {
          return messages;
        }
      }

      // 回退到 SessionPlugin
      const sessionPlugin = this.agent.framework.pluginManager.get('session');
      if (!sessionPlugin) return [];

      const messages = sessionPlugin.getHistory(sessionId);
      return messages || [];
    } catch (err) {
      // 忽略加载错误
    }
    return [];
  }

  /**
   * 保存聊天历史到 session 存储
   * @param {string} sessionId
   * @param {Array} messages
   * @private
   */
  _saveHistoryToSession(sessionId, messages) {
    if (!sessionId) return;

    try {
      // 优先保存到 SessionContext
      const sessionCtx = this.framework.getSessionContext();
      if (sessionCtx && sessionCtx.sessionId === sessionId) {
        sessionCtx.replaceMessages(messages);
        return;
      }

      // 回退到 SessionPlugin
      const sessionPlugin = this.agent.framework.pluginManager.get('session');
      if (!sessionPlugin) return;

      const cleanedMessages = prepareMessagesForAPI(messages);
      sessionPlugin.replaceMessages(sessionId, cleanedMessages);
    } catch (err) {
      // 忽略保存错误
    }
  }

  /**
   * 执行实际聊天逻辑
   * @private
   */
  async _doChat(message, options = {}) {
    const sessionId = options.sessionId || null;
    const framework = this.agent.framework;

    // 获取当前 session 的消息存储
    const messageStore = this._getSessionMessageStore(sessionId);
    const messages = messageStore.messages; // 使用 Per-Session 的消息数组

    try {
      // 从 session 加载聊天历史（只加载一次）
      if (sessionId && !messageStore.historyLoaded) {
        const savedMessages = this._loadHistoryFromSession(sessionId);
        if (savedMessages.length > 0) {
          messages.push(...savedMessages);
          messageStore.historyLoaded = true;
          logger.info(`Loaded ${savedMessages.length} messages from session ${sessionId}`);
        }
      }

      // 刷新系统提示词
      this._systemPrompt = this.agent._buildSystemPrompt();

      const userMessage =
        typeof message === 'string' ? { role: 'user', content: message } : message;
      messages.push(userMessage);

      // 检查是否需要压缩
      const totalTokens = this._countMessagesTokens(messages);
      if (totalTokens > this._maxContextTokens * 0.7) {
        await this._compressContext(sessionId, messages, messageStore);
      }

      // 构建上下文对象
      const requestCtx = framework.getRequestContext() || {};
      const context = {
        ...requestCtx,
        sessionId,
        sessionContext: framework.getSessionContext(),
        isStream: false,
      };

      // 使用 runWithContext 执行
      const result = await framework.runWithContext(context, async () => {
        // 使用 Per-Session 的消息数组
        return agent.generate({ messages, ...this.providerOptions });
      });

      messages.push(...result.response.messages);

      // 保存聊天历史
      if (sessionId) {
        this._saveHistoryToSession(sessionId, messages);
      }

      return {
        success: true,
        message: result.text || '',
        stepCount: result.stepCount || 1,
      };
    } catch (err) {
      this.emit('error', { error: err.message });
      throw err;
    }
  }

  /**
   * 压缩上下文
   * @private
   */
  async _compressContext(sessionId, messages, messageStore) {
    // 使用传入的 messages 引用，直接修改
    // ... 压缩逻辑保持不变，只是不再操作 this._messages
    // ...
  }
}
```

---

## 七、使用示例

### 7.1 完整请求流程

```javascript
// 创建请求
const requestId = generateId();

// 在完整上下文中执行
await framework.runInFullContext(
  { requestId, timeout: 60000, isStream: false },
  sessionId,
  agentId,
  async () => {
    // 在这里可以获取任何层级的上下文
    const reqCtx = framework.getRequestContext();
    const sessCtx = framework.getSessionContext();
    const agentCtx = framework.getAgentContext();

    console.log(`Request ${reqCtx.requestId}, Session ${sessCtx.sessionId}`);

    // Agent 执行
    const result = await agent.chat('Hello');

    return result;
  }
);
```

### 7.2 工具中访问上下文

```javascript
// 在工具执行时获取 session 信息
framework.registerTool({
  name: 'get_session_info',
  description: 'Get current session information',
  inputSchema: z.object({}),
  execute: async (args, framework) => {
    const sessionCtx = framework.getSessionContext();
    const requestCtx = framework.getRequestContext();

    return {
      sessionId: sessionCtx?.sessionId,
      messageCount: sessionCtx?.metadata.messageCount,
      requestId: requestCtx?.requestId,
      elapsed: requestCtx?.getElapsed(),
    };
  },
});
```

### 7.3 Workflow 中使用

```javascript
// workflow-engine.js
async executeStep(step, context) {
  const sessionId = context.variables?._sessionId;

  // 在 session 上下文中执行
  await this.framework.runInSession(sessionId, {}, async () => {
    const sessionCtx = this.framework.getSessionContext();
    sessionCtx.setVariable('workflow_state', state);

    // 执行工具
    const result = await this.framework.executeTool(step.tool, args);

    // 更新状态
    state = sessionCtx.getVariable('workflow_state');
  });
}
```

---

## 八、向后兼容

### 8.1 保留原有接口

```javascript
// Framework 保留原有方法，但标记为 deprecated
class Framework {
  /**
   * @deprecated 使用 runInSession 代替
   */
  runWithContext(context, fn) {
    console.warn('runWithContext is deprecated, use runInSession for session context');
    // 保持原有逻辑兼容
    return this._requestStorage.run(context, fn);
  }

  /**
   * @deprecated 使用 getSessionContext 代替
   */
  getExecutionContext() {
    console.warn('getExecutionContext is deprecated, use getSessionContext');
    const store = this._requestStorage.getStore();
    if (store?.sessionContext) {
      return { sessionId: store.sessionContext.sessionId };
    }
    return store || { sessionId: null };
  }
}
```

### 8.2 SessionPlugin 兼容

```javascript
// SessionPlugin 继续提供原有接口，但内部可以使用 SessionContext
class SessionPlugin {
  getHistory(sessionId) {
    // 优先从 SessionContext 获取
    const ctx = this._framework.getSessionContext();
    if (ctx && ctx.sessionId === sessionId) {
      return ctx.getMessages();
    }

    // 回退到原有存储
    const session = this._sessions.get(sessionId);
    return session?.messages || [];
  }
}
```

---

## 九、迁移步骤

### Phase 1: 引入 SessionContext（✅ 已完成）

1. ✅ 创建 `src/core/session-context.js`
2. ✅ 创建 `src/core/request-context.js`
3. ✅ 创建 `src/core/agent-context.js`
4. ✅ 创建 `src/core/context-manager.js`
5. ✅ 在 Framework 中添加三层 AsyncLocalStorage
6. ✅ 实现 `getOrCreateSessionContext()` 和 `getSessionContext()`
7. ✅ **不修改** `AgentChatHandler`，保持原有 `_messages` 逻辑

**完成时间**: 2026-04-06
**验证**: Bootstrap 测试通过，新组件正常工作

### Phase 2: AgentChatHandler Per-Session 改造（✅ 已完成）

1. ✅ 在 `AgentChatHandler` 中添加 `_sessionMessageStores` Map
2. ✅ 修改 `_doChat` 使用 Per-Session 的消息数组
3. ✅ 修改 `_compressContext` 使用传入的 messages 引用
4. ✅ 修改 `_simpleCompress` 使用传入的 messages 引用
5. ✅ 修改 `chatStream` 使用 Per-Session 消息数组
6. ✅ 修改 `clearHistory` 使用 Per-Session 消息存储
7. ✅ 验证多 session 并行不冲突

**完成时间**: 2026-04-06
**验证**: Per-Session 消息隔离测试通过，clearHistory 测试通过

### Phase 3: 移除 SessionPlugin 依赖（✅ 已完成）

1. ✅ `_loadHistoryFromSession` 直接使用 `framework.getOrCreateSessionContext()`
2. ✅ `_saveHistoryToSession` 直接使用 `framework.getOrCreateSessionContext()`
3. ✅ `clearHistory` 中使用 SessionContext 替代 SessionPlugin
4. ✅ 验证测试通过

**完成时间**: 2026-04-06
**验证**: Bootstrap 测试通过，SessionContext 方法测试通过

### Phase 4: 文档和示例（✅ 已完成）

1. ✅ 更新 CLAUDE.md 中的架构说明
2. ✅ 更新 CLAUDE.md 中的 Key Patterns
3. ✅ 集成测试通过

**完成时间**: 2026-04-06
**验证**: 集成测试全部通过

---

## 十、风险和注意事项

### 10.1 AsyncLocalStorage 嵌套限制

- Node.js 的 AsyncLocalStorage 不支持嵌套相同的 storage 实例
- 需要使用不同的 storage 实例隔离不同层级

### 10.2 SessionContext 内存泄漏

- `_sessionContexts` Map 需要在 session 过期时清理
- 需要与 SessionPlugin 的 TTL 机制协同

### 10.3 向后兼容

- 现有代码使用 `getExecutionContext()` 获取 sessionId
- 需要保留此方法但指向新的 SessionContext

---

## 十一、存储抽象层设计

### 11.1 设计目标

支持多种存储后端（内存、文件、JSON、数据库），通过接口抽象实现可插拔。

### 11.2 架构图

```
┌─────────────────────────────────────────────────────────────┐
│                    SessionContext                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  messages[], variables, metadata...                  │   │
│  └─────────────────────────────────────────────────────┘   │
│                              │                               │
│                              ▼                               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              SessionStorageAdapter                    │   │
│  │  ┌─────────────────────────────────────────────┐     │   │
│  │  │  interface SessionStorage {                 │     │   │
│  │  │    async load(sessionId): SessionData      │     │   │
│  │  │    async save(sessionId, data): void        │     │   │
│  │  │    async delete(sessionId): void            │     │   │
│  │  │    async list(): string[]                   │     │   │
│  │  │  }                                          │     │   │
│  │  └─────────────────────────────────────────────┘     │   │
│  └─────────────────────────────────────────────────────┘   │
│                              │                               │
│         ┌────────────────────┼────────────────────┐        │
│         ▼                    ▼                    ▼        │
│  ┌─────────────┐      ┌─────────────┐      ┌─────────────┐ │
│  │MemoryStorage│      │ FileStorage  │      │ JsonStorage │ │
│  │  (默认)     │      │  (持久化)    │      │  (可迁移)   │ │
│  └─────────────┘      └─────────────┘      └─────────────┘ │
│                                                        │
│         ┌────────────────────┐                         │
│         ▼                    ▼                          │
│  ┌─────────────┐      ┌─────────────┐                 │
│  │SQLiteStorage│      │MongoStorage │  (未来扩展)     │
│  └─────────────┘      └─────────────┘                 │
└─────────────────────────────────────────────────────────────┘
```

### 11.3 接口定义

```javascript
/**
 * Session 存储接口
 * 所有存储后端必须实现此接口
 */
class SessionStorageAdapter {
  /**
   * 加载会话数据
   * @param {string} sessionId - 会话 ID
   * @returns {Promise<Object|null>} 会话数据，不存在返回 null
   */
  async load(sessionId) {
    throw new Error('Not implemented');
  }

  /**
   * 保存会话数据
   * @param {string} sessionId - 会话 ID
   * @param {Object} data - 会话数据
   * @returns {Promise<void>}
   */
  async save(sessionId, data) {
    throw new Error('Not implemented');
  }

  /**
   * 删除会话数据
   * @param {string} sessionId - 会话 ID
   * @returns {Promise<void>}
   */
  async delete(sessionId) {
    throw new Error('Not implemented');
  }

  /**
   * 列出所有会话 ID
   * @returns {Promise<string[]>}
   */
  async list() {
    throw new Error('Not implemented');
  }

  /**
   * 检查存储是否健康
   * @returns {Promise<boolean>}
   */
  async healthCheck() {
    throw new Error('Not implemented');
  }
}
```

### 11.4 内置存储实现

#### 11.4.1 MemoryStorage（默认）

```javascript
/**
 * 内存存储 - 默认实现
 * 适用于单进程、无需持久化的场景
 */
class MemoryStorage extends SessionStorageAdapter {
  constructor() {
    super();
    this._store = new Map(); // sessionId → data
  }

  async load(sessionId) {
    return this._store.get(sessionId) || null;
  }

  async save(sessionId, data) {
    this._store.set(sessionId, {
      ...data,
      _cachedAt: Date.now(),
    });
  }

  async delete(sessionId) {
    this._store.delete(sessionId);
  }

  async list() {
    return Array.from(this._store.keys());
  }

  async healthCheck() {
    return true;
  }
}
```

#### 11.4.2 JsonStorage（文件）

```javascript
/**
 * JSON 文件存储
 * 适用于需要持久化、数据量较小的场景
 */
class JsonStorage extends SessionStorageAdapter {
  /**
   * @param {Object} options
   * @param {string} options.dir - 存储目录
   * @param {string} [options.filePattern='{sessionId}.json'] - 文件名模式
   */
  constructor(options = {}) {
    super();
    this.dir = options.dir || '.sessions';
    this.filePattern = options.filePattern || '{sessionId}.json';
    this._ensureDir();
  }

  _getFilePath(sessionId) {
    const filename = this.filePattern.replace('{sessionId}', sessionId);
    return path.join(this.dir, filename);
  }

  _ensureDir() {
    if (!fs.existsSync(this.dir)) {
      fs.mkdirSync(this.dir, { recursive: true });
    }
  }

  async load(sessionId) {
    const filePath = this._getFilePath(sessionId);
    if (!fs.existsSync(filePath)) {
      return null;
    }
    const content = await fs.readFile(filePath, 'utf-8');
    return JSON.parse(content);
  }

  async save(sessionId, data) {
    const filePath = this._getFilePath(sessionId);
    await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');
  }

  async delete(sessionId) {
    const filePath = this._getFilePath(sessionId);
    if (fs.existsSync(filePath)) {
      await fs.unlink(filePath);
    }
  }

  async list() {
    if (!fs.existsSync(this.dir)) {
      return [];
    }
    const files = await fs.readdir(this.dir);
    return files.filter((f) => f.endsWith('.json')).map((f) => f.replace('.json', ''));
  }

  async healthCheck() {
    return fs.existsSync(this.dir) && fs.statSync(this.dir).isDirectory();
  }
}
```

#### 11.4.3 SQLiteStorage（示例）

```javascript
/**
 * SQLite 数据库存储
 * 适用于生产环境、需要事务支持的场景
 */
class SQLiteStorage extends SessionStorageAdapter {
  /**
   * @param {Object} options
   * @param {string} [options.dbPath=':memory:'] - 数据库路径
   */
  constructor(options = {}) {
    super();
    this.dbPath = options.dbPath || '.sessions/sessions.db';
    this._db = null;
  }

  async _getDb() {
    if (!this._db) {
      const Database = require('better-sqlite3');
      this._db = new Database(this.dbPath);
      this._initTable();
    }
    return this._db;
  }

  _initTable() {
    const db = this._db;
    db.exec(`
      CREATE TABLE IF NOT EXISTS sessions (
        session_id TEXT PRIMARY KEY,
        data TEXT NOT NULL,
        created_at INTEGER NOT NULL,
        updated_at INTEGER NOT NULL
      )
    `);
    db.exec(`CREATE INDEX IF NOT EXISTS idx_updated_at ON sessions(updated_at)`);
  }

  async load(sessionId) {
    const db = await this._getDb();
    const row = db.prepare('SELECT data FROM sessions WHERE session_id = ?').get(sessionId);
    return row ? JSON.parse(row.data) : null;
  }

  async save(sessionId, data) {
    const db = await this._getDb();
    const now = Date.now();
    const stmt = db.prepare(`
      INSERT OR REPLACE INTO sessions (session_id, data, created_at, updated_at)
      VALUES (?, ?, COALESCE((SELECT created_at FROM sessions WHERE session_id = ?), ?), ?)
    `);
    stmt.run(sessionId, JSON.stringify(data), sessionId, now, now);
  }

  async delete(sessionId) {
    const db = await this._getDb();
    db.prepare('DELETE FROM sessions WHERE session_id = ?').run(sessionId);
  }

  async list() {
    const db = await this._getDb();
    const rows = db.prepare('SELECT session_id FROM sessions').all();
    return rows.map((r) => r.session_id);
  }

  async healthCheck() {
    try {
      const db = await this._getDb();
      db.prepare('SELECT 1').get();
      return true;
    } catch {
      return false;
    }
  }
}
```

### 11.5 SessionContext 集成

```javascript
class SessionContext {
  /**
   * @param {string} sessionId
   * @param {Framework} framework
   * @param {Object} options
   * @param {SessionStorageAdapter} [options.storage] - 存储适配器，默认 MemoryStorage
   */
  constructor(sessionId, framework, options = {}) {
    this.sessionId = sessionId;
    this.framework = framework;
    this.storage = options.storage || new MemoryStorage();

    // ... 其他初始化
  }

  /**
   * 加载会话数据（从存储）
   * @returns {Promise<boolean>} 是否加载成功
   */
  async loadFromStorage() {
    const data = await this.storage.load(this.sessionId);
    if (data) {
      this.messageStore.messages = data.messages || [];
      this.messageStore.historyLoaded = true;

      // 恢复 variables
      if (data.variables) {
        this.variables = new Map(Object.entries(data.variables));
      }

      // 恢复 metadata
      if (data.metadata) {
        this.metadata = { ...this.metadata, ...data.metadata };
      }

      return true;
    }
    return false;
  }

  /**
   * 保存会话数据（到存储）
   * @returns {Promise<void>}
   */
  async saveToStorage() {
    const data = {
      sessionId: this.sessionId,
      messages: this.messageStore.messages,
      variables: Object.fromEntries(this.variables),
      metadata: this.metadata,
      savedAt: Date.now(),
    };
    await this.storage.save(this.sessionId, data);
  }

  /**
   * 删除会话数据
   * @returns {Promise<void>}
   */
  async deleteFromStorage() {
    await this.storage.delete(this.sessionId);
  }
}
```

### 11.6 Framework 集成

```javascript
class Framework {
  constructor(config = {}) {
    // ...

    // 配置存储适配器
    const storageConfig = config.storage || {};
    this._configureStorage(storageConfig);
  }

  _configureStorage(config) {
    if (typeof config === 'string') {
      // 简单字符串配置：'memory', 'file', 'json', 'sqlite'
      switch (config) {
        case 'memory':
          this.sessionStorage = new MemoryStorage();
          break;
        case 'file':
        case 'json':
          this.sessionStorage = new JsonStorage({ dir: '.sessions' });
          break;
        case 'sqlite':
          this.sessionStorage = new SQLiteStorage();
          break;
        default:
          this.sessionStorage = new MemoryStorage();
      }
    } else if (config instanceof SessionStorageAdapter) {
      // 直接传入适配器实例
      this.sessionStorage = config;
    } else if (config && typeof config.type === 'string') {
      // 对象配置 { type: 'file', dir: '.sessions' }
      switch (config.type) {
        case 'file':
        case 'json':
          this.sessionStorage = new JsonStorage(config);
          break;
        case 'sqlite':
          this.sessionStorage = new SQLiteStorage(config);
          break;
        default:
          this.sessionStorage = new MemoryStorage();
      }
    } else {
      this.sessionStorage = new MemoryStorage();
    }
  }

  /**
   * 获取当前使用的存储适配器
   * @returns {SessionStorageAdapter}
   */
  getSessionStorage() {
    return this.sessionStorage;
  }
}
```

### 11.7 使用示例

```javascript
// 创建 Framework 时指定存储
const framework = await Framework.bootstrap({
  storage: 'file', // 使用文件存储
  // 或
  storage: {
    type: 'sqlite',
    dbPath: '.sessions/sessions.db',
  },
  // 或
  storage: new CustomStorageAdapter(), // 自定义存储
});

// 运行时切换存储
framework.sessionStorage = new SQLiteStorage({ dbPath: '/tmp/sessions.db' });
```

### 11.8 设计优势

| 特性         | 说明                               |
| ------------ | ---------------------------------- |
| **接口隔离** | SessionContext 不关心具体存储实现  |
| **可测试性** | 使用 MemoryStorage 进行单元测试    |
| **渐进迁移** | 可从 JSON 文件迁移到 SQLite        |
| **插件化**   | 用户可实现自己的存储适配器         |
| **配置灵活** | 支持字符串、对象、实例多种配置方式 |

---

## 附录：关键文件变更清单

| 文件                          | 变更类型 | 描述                                              |
| ----------------------------- | -------- | ------------------------------------------------- |
| `src/core/framework.js`       | 修改     | 添加三层 AsyncLocalStorage，新增 Context 获取方法 |
| `src/core/agent-chat.js`      | 修改     | Per-Session 消息存储，移除共享 `_messages`        |
| `src/core/session-context.js` | 新增     | SessionContext 类                                 |
| `src/core/request-context.js` | 新增     | RequestContext 类                                 |
| `src/core/agent-context.js`   | 新增     | AgentContext 类                                   |
| `src/core/context-manager.js` | 新增     | ContextManager 类                                 |
| `plugins/session-plugin.js`   | 修改     | 优先使用 SessionContext                           |
| `docs/CONTEXT_DESIGN.md`      | 新增     | 本文档                                            |
