# 05. 会话工作区、运行态和记忆 ![会话工作区、运行态和记忆](assets/05-workspace-memory-observability.png) ## 1. 会话工作区 每个用户、每个会话都有独立目录: ```text .port_sessions/accounts//sessions// input/ scratchpad/ output/ session.json ``` 目录职责: ```text input/ 用户上传或明确提供的输入资料。 scratchpad/ 临时脚本、中间文件、抽样缓存、断点记录。 output/ 最终交付产物。 session.json 会话消息、工具调用、usage、events、file_history、runtime metadata。 ``` ## 2. 工作区路径路由 路径解析实现: ```text src/agent_tools.py:1658 _session_logical_path ``` 逻辑路径: ```text output/... -> session/output/... outputs/... -> session/output/... scratchpad/... -> session/scratchpad/... scratch/... -> session/scratchpad/... input/... -> session/input/... inputs/... -> session/input/... ``` Python 执行 cwd: ```text src/agent_tools.py:1685 _execution_cwd ``` 优先使用当前 session scratchpad。这是为了避免临时脚本和缓存污染项目根目录。 ## 3. 平台代码写保护 相关实现: ```text src/agent_tools.py:1118 _PLATFORM_READONLY_DIRS src/agent_tools.py:1698 _is_platform_code_path src/agent_tools.py:1708 _ensure_not_platform_code_write ``` 当前平台目录: ```text src backend frontend scripts ``` 在数据 Agent 会话中默认视为只读。除非用户明确进入平台开发任务,否则业务任务不应修改平台代码。 ## 4. Run 状态和活动区 后端在 `/api/chat` 运行时创建 run record: ```text backend/api/server.py:1720 run_record = state.run_manager.start(...) backend/api/server.py:1722 state.run_state_store.start(...) ``` 运行事件通过 `emit_agent_event` 记录: ```text backend/api/server.py:1751 emit_agent_event backend/api/server.py:1756 run_manager.record_event backend/api/server.py:1758 run_state_store.record_event ``` 返回前端: ```text backend/api/server.py:2034 StreamingResponse ``` 前端活动区看到的内容主要来自: - `run_started` - `tool_start` - `tool_result` - 模型阶段说明 - final text stream events - run finish/error/cancel 状态 ## 5. 会话持久化 运行结束后,后端序列化结果: ```text backend/api/server.py:2056 _serialize_run_result backend/api/server.py:2069 _normalize_transcript_entry ``` 会话读取: ```text backend/api/server.py:2094 _serialize_stored_session ``` `agent_runtime` 在多个结束路径都会调用: ```text _persist_session(session, result) ``` 这让刷新后可以恢复: - 用户消息。 - assistant 文本。 - tool_calls。 - tool result。 - elapsed。 - file_history。 ## 6. 记忆体系 实现位置: ```text src/personal_memory.py ``` ### 6.1 文件和数据库 ```text memory.db user.md skills/.md ``` 常量: ```text src/personal_memory.py:26 MEMORY_DB_FILENAME src/personal_memory.py:27 USER_MEMORY_FILENAME src/personal_memory.py:28 SKILL_MEMORY_DIRNAME ``` ### 6.2 注入逻辑 ```text src/personal_memory.py:102 render_injection ``` 注入规则: ```text 1. 读取 user.md。 2. 根据 enabled_skill_names 读取对应 skills/.md。 3. 拼成 # 个性化记忆。 4. 如果用户本轮要求冲突,以本轮要求为准。 ``` 后端调用: ```text backend/api/server.py:1739 memory_manager.render_injection(...) ``` ### 6.3 入队逻辑 运行结束后: ```text backend/api/server.py:1920 memory_manager.enqueue_interaction(...) ``` 记忆模块内: ```text src/personal_memory.py:138 enqueue_interaction src/personal_memory.py:635 detect_memory_signals ``` 会检测: - 显式记忆词:记住、以后、下次、默认、总是、不要、应该、固定。 - 纠错词:不对、不是这样、格式错、之前说过、还是不行。 - Skill/工具/流程/格式相关表述。 - 工具参数非法 JSON 等工具经验。 ### 6.4 后台整理 核心逻辑: ```text src/personal_memory.py:378 _consolidate_events src/personal_memory.py:419 _generate_memory_updates src/personal_memory.py:471 _fallback_memory_updates ``` 设计取舍: - 主链路不直接生成记忆。 - 事件先进入 SQLite 队列。 - 后台 worker 批量整理。 - LLM 失败时有 fallback 规则。 - Markdown 是最终可编辑记忆正文。 ## 7. 可观测性设计 当前可观测性来自三个层次: ```text 运行态 run_manager + run_state_store,支持运行中刷新、停止、恢复活动区。 会话态 session.json,保存完整消息和工具调用。 产物态 session/input、scratchpad、output,文件面板可查看和下载。 ``` 这个设计让用户不仅看到最终回复,也能看到 Agent 做了什么、文件在哪里、失败在哪个工具或阶段。