From c31e2795609afdcd70310ddbc2b861647aa98094 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Thu, 7 May 2026 00:11:21 +0800 Subject: [PATCH] refactor(agent): rename WORKSPACE_FILE to LOCAL_FILE for memory storage mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该模式的 .agent-session 目录实际位于 workspace.root 之下、与各 session 的 workspace 子目录平级而非嵌套,旧名 WORKSPACE_FILE 容易误导为"存储在 某个 workspace 内部"。LOCAL_FILE 与 REDIS、MYSQL 同层级地描述后端类型, 更准确地反映实际行为。 Co-Authored-By: Claude Opus 4.7 --- docs/liteflow-react-agent-guide.md | 10 ++++---- .../property/agent/LocalFileMemoryConfig.java | 23 +++++++++++++++++++ .../property/agent/MemoryStorageConfig.java | 14 +++++------ .../property/agent/MemoryStorageMode.java | 8 +++---- .../property/agent/WorkspaceMemoryConfig.java | 16 ------------- .../session/factory/AgentSessionFactory.java | 2 +- .../factory/AgentSessionFactoryRegistry.java | 6 ++--- .../factory/InMemoryAgentSessionFactory.java | 2 +- ...java => LocalFileAgentSessionFactory.java} | 21 +++++++++-------- 9 files changed, 55 insertions(+), 47 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/LocalFileMemoryConfig.java delete mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceMemoryConfig.java rename liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/{WorkspaceAgentSessionFactory.java => LocalFileAgentSessionFactory.java} (60%) diff --git a/docs/liteflow-react-agent-guide.md b/docs/liteflow-react-agent-guide.md index 04a75fbc6..c1fe391a1 100644 --- a/docs/liteflow-react-agent-guide.md +++ b/docs/liteflow-react-agent-guide.md @@ -467,7 +467,7 @@ Session ID 只允许直接使用 `[a-zA-Z0-9_-]+`。其他字符会被 URL 编 | --- | --- | --- | | `JVM` | 默认值,使用 AgentScope 的 JVM 内 Session | 单进程内多轮对话,进程退出后可丢失 | | `NONE` | 不加载也不保存持久化 Session | 不需要持久化;如需严格无状态,配合唯一 `sessionId` 使用 | -| `WORKSPACE_FILE` | 保存到 `workspace.root/.agent-session//` | 本地文件持久化、开发测试、小规模部署 | +| `LOCAL_FILE` | 保存到 `workspace.root/.agent-session//` | 本地文件持久化、开发测试、小规模部署 | | `REDIS` | 使用用户提供的 Redis 客户端 Bean | 多实例共享短期会话 | | `MYSQL` | 使用用户提供的 `DataSource` Bean | 需要数据库持久化和运维治理 | @@ -479,10 +479,10 @@ Session ID 只允许直接使用 `[a-zA-Z0-9_-]+`。其他字符会被 URL 编 | `save-after-call` | `true` | 调用成功后保存记忆 | | `save-on-error` | `true` | 调用抛错时也尝试保存记忆 | -`WORKSPACE_FILE` 示例: +`LOCAL_FILE` 示例: ```properties -liteflow.agent.session.memory.mode=WORKSPACE_FILE +liteflow.agent.session.memory.mode=LOCAL_FILE liteflow.agent.session.memory.load-on-first-use=true liteflow.agent.session.memory.save-after-call=true liteflow.agent.session.memory.save-on-error=true @@ -526,7 +526,7 @@ LiteFlow 不创建 JDBC 连接池,`DataSource` 也需要由业务应用提供 └── .agent-session/ ``` -`/` 是 Agent 工具读写文件的目录;`.agent-session/` 只在 `session.memory.mode=WORKSPACE_FILE` 时创建,用于保存 AgentScope 的记忆文件。 +`/` 是 Agent 工具读写文件的目录;`.agent-session/` 只在 `session.memory.mode=LOCAL_FILE` 时创建,用于保存 AgentScope 的记忆文件。 ### 6.2 Workspace 配置 @@ -769,7 +769,7 @@ liteflow.agent.anthropic-compatible.gateway.base-url=https://anthropic-gateway.e | `workspace root does not exist` | `auto-create=false` 且目录不存在 | 提前创建目录,或开启 `auto-create` | | `Missing API key: please configure liteflow.agent.openai.api-key` | 对应平台凭据未配置 | 配置对应平台的 `api-key` | | 多轮对话没有记忆 | 默认 Session ID 由 `NanoIdSessionIdGenerator` 每次随机生成 | 覆写 `resolveSessionId`,返回稳定的业务会话 ID | -| 重启后没有历史记忆 | `session.memory.mode=JVM` 或 `NONE` | 改为 `WORKSPACE_FILE`、`REDIS` 或 `MYSQL` | +| 重启后没有历史记忆 | `session.memory.mode=JVM` 或 `NONE` | 改为 `LOCAL_FILE`、`REDIS` 或 `MYSQL` | | Redis 模式启动失败 | 未配置 Bean 名,或 Bean 类型与 `client-type` 不匹配 | 检查 `bean-name`、`client-type` 和 classpath 依赖 | | MySQL 模式启动失败 | 未配置 `DataSource` Bean,或 Bean 类型错误 | 配置正确的 `data-source-bean-name` | | Shell 返回 `command 'xxx' not allowed by whitelist` | 白名单模式下命令未放行 | 加入白名单,或继续保持禁用 | diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/LocalFileMemoryConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/LocalFileMemoryConfig.java new file mode 100644 index 000000000..14cfe24bd --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/LocalFileMemoryConfig.java @@ -0,0 +1,23 @@ +package com.yomahub.liteflow.property.agent; + +/** + * 仅在 {@link MemoryStorageMode#LOCAL_FILE} 模式下生效的配置项, + * 对应配置段 {@code liteflow.agent.session.memory.local-file.*}。 + * + *

该模式下记忆持久化会落盘到 {@code workspace.root} 之下的 + * {@link #SUB_DIR} 子目录中,按 {@code sessionId} 再分一层;该目录与 + * 各 session 自己的 workspace({@code workspace.root//})平级而不嵌套, + * 这样可以避免内置 {@code WorkspaceFileTools} + * 读到或覆盖 agent 自己的记忆,也让 {@code cleanup-on-session-expire} + * 在清空 workspace 子目录时不会误删持久化的记忆。 + * + *

该位置故意硬编码、不暴露为可配置项:保证不同会话之间结构一致, + * 且与 Redis、MySQL 等远程后端的"持久化与 workspace 生命周期解耦"语义对齐。 + * 需要自定义存储位置的用户应通过 SPI 注入自己的 + * {@code AgentSessionFactory} 实现。 + */ +public class LocalFileMemoryConfig { + + /** 会话 JSON 文件存放的固定子目录名,位于 {@code workspace.root} 之下。 */ + public static final String SUB_DIR = ".agent-session"; +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageConfig.java index d35cded65..733c8c990 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageConfig.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageConfig.java @@ -6,7 +6,7 @@ package com.yomahub.liteflow.property.agent; * *

本配置与 {@link SessionConfig} 是正交的关注点: * {@link SessionConfig} 控制 JVM 内 agent 实例的缓存、空闲超时与 LRU 淘汰; - * 而本配置决定 agent 的对话历史 持久化到哪里,例如 JVM 堆内、工作区文件、 + * 而本配置决定 agent 的对话历史 持久化到哪里,例如 JVM 堆内、本地文件、 * Redis 或 MySQL。 */ public class MemoryStorageConfig { @@ -19,8 +19,8 @@ public class MemoryStorageConfig { */ private MemoryStorageMode mode = MemoryStorageMode.JVM; - /** {@link MemoryStorageMode#WORKSPACE_FILE} 模式下生效的子配置。 */ - private WorkspaceMemoryConfig workspace = new WorkspaceMemoryConfig(); + /** {@link MemoryStorageMode#LOCAL_FILE} 模式下生效的子配置。 */ + private LocalFileMemoryConfig localFile = new LocalFileMemoryConfig(); /** {@link MemoryStorageMode#REDIS} 模式下生效的子配置。 */ private RedisMemoryConfig redis = new RedisMemoryConfig(); @@ -60,12 +60,12 @@ public class MemoryStorageConfig { this.mode = mode; } - public WorkspaceMemoryConfig getWorkspace() { - return workspace; + public LocalFileMemoryConfig getLocalFile() { + return localFile; } - public void setWorkspace(WorkspaceMemoryConfig workspace) { - this.workspace = workspace; + public void setLocalFile(LocalFileMemoryConfig localFile) { + this.localFile = localFile; } public RedisMemoryConfig getRedis() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageMode.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageMode.java index 029a5cb84..3c9b5fc4b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageMode.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/MemoryStorageMode.java @@ -6,8 +6,8 @@ package com.yomahub.liteflow.property.agent; *

    *
  • {@link #NONE} – 不保留也不持久化任何记忆,等价于无状态 agent
  • *
  • {@link #JVM} – 仅保留在 JVM 堆内(默认行为,与 2.15.4 之前版本一致)
  • - *
  • {@link #WORKSPACE_FILE} – 通过 AgentScope 的 JsonSession,把记忆以 JSON 文件 - * 形式持久化到每个会话工作区目录下
  • + *
  • {@link #LOCAL_FILE} – 通过 AgentScope 的 JsonSession,把记忆以 JSON 文件 + * 形式持久化到本地磁盘(与各 session 的 workspace 子目录平级)
  • *
  • {@link #REDIS} – 通过 AgentScope 的 RedisSession 持久化, * 需要用户提供 {@code RedissonClient} / {@code UnifiedJedis} / {@code RedisClient} bean
  • *
  • {@link #MYSQL} – 通过 AgentScope 的 MysqlSession 持久化, @@ -22,8 +22,8 @@ public enum MemoryStorageMode { /** 仅 JVM 堆内缓存,进程重启即丢失;为默认值。 */ JVM, - /** 工作区文件持久化,每个会话一个 JSON 文件,便于排查与离线分析。 */ - WORKSPACE_FILE, + /** 本地文件持久化,每个会话一份 JSON 文件,便于排查与离线分析。 */ + LOCAL_FILE, /** Redis 持久化,适合多实例部署、高并发场景。 */ REDIS, diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceMemoryConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceMemoryConfig.java deleted file mode 100644 index c7f2e6879..000000000 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/agent/WorkspaceMemoryConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.yomahub.liteflow.property.agent; - -/** - * 仅在 {@link MemoryStorageMode#WORKSPACE_FILE} 模式下生效的配置项, - * 对应配置段 {@code liteflow.agent.session.memory.workspace.*}。 - * - *

    该模式下记忆持久化会落盘到每个会话工作区目录下的固定子目录({@link #SUB_DIR}), - * 该位置故意硬编码、不暴露为可配置项:一方面避免与工具产生的业务文件混在一起, - * 另一方面保证不同会话之间结构一致。需要自定义存储位置的用户应通过 SPI - * 注入自己的 {@code AgentSessionFactory} 实现。 - */ -public class WorkspaceMemoryConfig { - - /** 会话 JSON 文件存放的固定子目录名(位于工作区根目录下)。 */ - public static final String SUB_DIR = ".agent-session"; -} diff --git a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactory.java b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactory.java index f5c90469a..379987df8 100644 --- a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactory.java +++ b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactory.java @@ -7,7 +7,7 @@ import io.agentscope.core.session.Session; /** * 用于为 {@link io.agentscope.core.session.Session} 接入额外持久化后端的 SPI。 * - *

    框架内置模式({@code JVM}、{@code WORKSPACE_FILE}、{@code REDIS}、 + *

    框架内置模式({@code JVM}、{@code LOCAL_FILE}、{@code REDIS}、 * {@code MYSQL}、{@code NONE})。需要其他后端(例如 PostgreSQL、OSS、 * 加密 JSON)的用户,可以在 {@code META-INF/services/}{@link AgentSessionFactory} * 下注册自定义工厂。 diff --git a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactoryRegistry.java b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactoryRegistry.java index 5628de0cf..4cb5ed8ba 100644 --- a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactoryRegistry.java +++ b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/AgentSessionFactoryRegistry.java @@ -15,10 +15,10 @@ import java.util.ServiceLoader; *

    解析顺序: *

      *
    1. 通过 {@link ServiceLoader} 注册的外部工厂
    2. - *
    3. 框架内置工厂(JVM、workspace、Redis、MySQL、none)
    4. + *
    5. 框架内置工厂(JVM、local-file、Redis、MySQL、none)
    6. *
    * 出现冲突时外部工厂优先,因此用户可以覆盖内置实现 - * (例如用自定义加密 JSON 工厂替换默认 workspace 工厂)。 + * (例如用自定义加密 JSON 工厂替换默认本地文件工厂)。 */ public final class AgentSessionFactoryRegistry { @@ -27,7 +27,7 @@ public final class AgentSessionFactoryRegistry { static { // 先注册内置实现;如果存在 SPI 实现,再由 SPI 覆盖。 register(new InMemoryAgentSessionFactory()); - register(new WorkspaceAgentSessionFactory()); + register(new LocalFileAgentSessionFactory()); register(new RedisAgentSessionFactory()); register(new MysqlAgentSessionFactory()); register(new NoneAgentSessionFactory()); diff --git a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/InMemoryAgentSessionFactory.java b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/InMemoryAgentSessionFactory.java index c73b59f94..faca4367a 100644 --- a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/InMemoryAgentSessionFactory.java +++ b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/InMemoryAgentSessionFactory.java @@ -10,7 +10,7 @@ import io.agentscope.core.session.Session; * *

    注意:状态仍会在同一个 JVM 内跨调用保留(适合希望在单进程内保留多轮记忆的场景), * 但进程退出后会丢失。如果需要跨重启持久化,请选择 - * {@code WORKSPACE_FILE}、{@code REDIS} 或 {@code MYSQL}。 + * {@code LOCAL_FILE}、{@code REDIS} 或 {@code MYSQL}。 */ public class InMemoryAgentSessionFactory implements AgentSessionFactory { diff --git a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/WorkspaceAgentSessionFactory.java b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/LocalFileAgentSessionFactory.java similarity index 60% rename from liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/WorkspaceAgentSessionFactory.java rename to liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/LocalFileAgentSessionFactory.java index 059b858b0..c66d52147 100644 --- a/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/WorkspaceAgentSessionFactory.java +++ b/liteflow-react-agent/liteflow-react-agent-core/src/main/java/com/yomahub/liteflow/agent/session/factory/LocalFileAgentSessionFactory.java @@ -2,8 +2,8 @@ package com.yomahub.liteflow.agent.session.factory; import com.yomahub.liteflow.agent.exception.AgentConfigException; import com.yomahub.liteflow.property.agent.AgentConfig; +import com.yomahub.liteflow.property.agent.LocalFileMemoryConfig; import com.yomahub.liteflow.property.agent.MemoryStorageMode; -import com.yomahub.liteflow.property.agent.WorkspaceMemoryConfig; import io.agentscope.core.session.JsonSession; import io.agentscope.core.session.Session; @@ -14,28 +14,29 @@ import java.nio.file.Paths; /** * 通过把 JSON 文件存储在 {@code workspace.root/.agent-session//} - * 下来支持 {@link MemoryStorageMode#WORKSPACE_FILE}。 + * 下来支持 {@link MemoryStorageMode#LOCAL_FILE}。 * - *

    session 存储子目录特意与 {@code workspace.root//} - * 形式的单 session 工具 workspace 分离,避免 - * {@link com.yomahub.liteflow.agent.tool.WorkspaceFileTools} 读取或覆盖 - * agent 自身记忆。 + *

    session 存储子目录与各 session 的 workspace({@code workspace.root//}) + * 平级而非嵌套:一方面避免 {@link com.yomahub.liteflow.agent.tool.WorkspaceFileTools} + * 读到或覆盖 agent 自己的记忆;另一方面让 {@code cleanup-on-session-expire} + * 在递归清空 workspace 子目录时不会误删持久化的记忆, + * 与 Redis、MySQL 后端的"持久化与 workspace 生命周期解耦"语义保持一致。 */ -public class WorkspaceAgentSessionFactory implements AgentSessionFactory { +public class LocalFileAgentSessionFactory implements AgentSessionFactory { @Override public MemoryStorageMode mode() { - return MemoryStorageMode.WORKSPACE_FILE; + return MemoryStorageMode.LOCAL_FILE; } @Override public Session create(AgentConfig cfg) { if (cfg.getWorkspace() == null || cfg.getWorkspace().getRoot() == null) { throw new AgentConfigException( - "liteflow.agent.workspace.root is required when session.memory.mode=WORKSPACE_FILE"); + "liteflow.agent.workspace.root is required when session.memory.mode=LOCAL_FILE"); } Path root = Paths.get(cfg.getWorkspace().getRoot()).toAbsolutePath().normalize() - .resolve(WorkspaceMemoryConfig.SUB_DIR); + .resolve(LocalFileMemoryConfig.SUB_DIR); try { Files.createDirectories(root); } catch (IOException e) {